Он в курсе. MessagePack, кстати, вполне может заменить BSON.
Проблема тут в том, что тот же 1с или MSSQL средствами встроенного языка умеет формировать и парсить только xml-ки. Поэтому в наше приложение из обозначенных систем приходит именно xml. Так как наше приложение фактически без изменений засылает его в другую (но удаленную) систему, то особого резона преобразовывать xml<->BSON мы не видели. Разве что трафик экономить.
Мне кажется, что в случае использования данной очереди возможна следующая проблема.
В документации написано, что метод pop() «Block until an item becomes available, and then dequeue it.».
Давайте представим, что все потоки-обработчики клиентов встали на методе pop() и ждут, когда в очереди что-то появится. А в это время мы хотим остановить сервер. Поток с WaitForConnection() мы уже остановили, новых клиентов нет, а другие потоки по-прежнему стоят на блокирующем pop() и, следовательно, вызов join() применительно к ним просто повесит главный поток выполнения.
Заказчику очень хочется посылать именно xml. Причем, по замыслу проекта, он просто гоняет эти xml между разными системами, никак их не меняя и даже не читая.
Messagepack мы используем для мериализации класса сообщений, которые передаем по сети.
Для ответа на этот вопрос мне проще всего восстановить по памяти диалог полугодовой давности:
— как мы будем связываться из внешней компоненты с нашим проектом?
— сокеты
— не айс, loopback это — медленно, посмотри что-нибудь вроде shared memory
— вот есть межпроцессная очередь сообщений в бусте
— она с приоритетами, это тоже медленно.
— ну вот когда я делал компоненту для MSSQL, то там я использовал именованные каналы из .NET
— поищи такое же для плюсов
— нашел только QLocalsocket в Qt
(пауза)
— это слишком толстая либа, ставить ее на все компы заказчика не айс. Может, попробуем свою написать?
Собственно, как-то так оно и было. Заказчик системы тоже «шарит» и обладает чертой, присущей большинству заказчиков — не называет проблему, а требует запрогать то решение, которое пришло ему в голову, пытается контролировать процесс разработки.
С одной стороны это хорошо. С другой — когда влияние заказчика распространяется на выбор библиотек — нет.
Теперь мое видение велосипедостроения. Для того чтобы обучаться — писать велосипеды очень даже хорошо. И набивать шишки. Но с другой стороны, впаривать велосипеды заказчику совсем не хорошо. Хотя бы сточки зрения поддержки и уровня покрытия тестами кода. За 10мб Qt-библиотеки стоит большое коммьюнити разработчиков, сама библиотека использовалась в миллионах проектов и шанс словить в ней ошибку гораздо меньше шанса словить ошибки от велосипеда.
Только при написании этой статьи я убрал 6 багов из той версии, что сейчас крутится у заказчика. Ошибки были не критичные — при определенных условиях сервер посылал клиент после соединения, но клиент умел переподключаться, да пара утечек памяти (одна в деструкторе сервера, который никогда не вызывался).
С именами машин проблемы и не должно быть — по ТЗ и система и наше приложение должны быть развернуты на одной машине. Иначе бы мы использовали только сокеты и этой статьи не было бы.
Кроме этого, есть соглашение что имена пайпов должны быть на английском и хардкодятся в бинарниках. Ну, есть, конечно, опция с добавлением префиксов (если одна копия приложения на машине слушает, скажем 1ску а вторая — оракл), но там мы явно применяем конвертацию юникода в ascII, а в случае с 1с — еще и транслит.
>Для того чтобы избежать ненужного поллинга можно заменить тип очереди на concurrent_bounded_queue Тогда вы избавить от постоянной долбежки функции try_pop и будете дожидаться сообщения без поллинга.
Извиняюсь, проглядел данный совет. В принципе я изначально был за, но полгода назад, во время рождения данной библиотеки, начальство было против данной замены (
>если будет выброшено исключение, то вы все равно продолжаете работу и пытаетесь обрабатывать сообщения.
Так надо. Одно исключение не должно валить весь сервер и обламывать других клиентов.
>Теряется всякая информация об ошибках, что не есть хорошо.
В статье написано, что внутри catch у нас было логирование. Но для статьи я убрал его, чтобы убрать зависимость итогового варианта от log4cxx. Но пустышки catch оставить пришлось, чтобы один эксепшн не валил приложения.
>в коде сервера встречаются строки вида: boost::this_thread::sleep(boost::posix_time::milliseconds(100)); Что убивает ваше стремление к производительности полностью.
Хорошо, сделаем засыпание на 1мс. Но оно все равно должно быть — иначе поедание ресуров процессора на холостом цикле будет слишком большим
Мы хотели максимально избавить внешние компоненты от сторонних зависимостей. Но, честно говоря, наличие указанных вами классов в asio мы проглядели. Спасибо за наводку.
Во время проектирования мы решили, что не будем создавать отдельный класс только ради акцепта новых клиентов. Хотя такое разделение было бы неплохо сделать. В .NET оно есть. Но там в серверный пайп можно и писать и читать.
Проблема тут в том, что тот же 1с или MSSQL средствами встроенного языка умеет формировать и парсить только xml-ки. Поэтому в наше приложение из обозначенных систем приходит именно xml. Так как наше приложение фактически без изменений засылает его в другую (но удаленную) систему, то особого резона преобразовывать xml<->BSON мы не видели. Разве что трафик экономить.
В документации написано, что метод pop() «Block until an item becomes available, and then dequeue it.».
Давайте представим, что все потоки-обработчики клиентов встали на методе pop() и ждут, когда в очереди что-то появится. А в это время мы хотим остановить сервер. Поток с WaitForConnection() мы уже остановили, новых клиентов нет, а другие потоки по-прежнему стоят на блокирующем pop() и, следовательно, вызов join() применительно к ним просто повесит главный поток выполнения.
Messagepack мы используем для мериализации класса сообщений, которые передаем по сети.
— как мы будем связываться из внешней компоненты с нашим проектом?
— сокеты
— не айс, loopback это — медленно, посмотри что-нибудь вроде shared memory
— вот есть межпроцессная очередь сообщений в бусте
— она с приоритетами, это тоже медленно.
— ну вот когда я делал компоненту для MSSQL, то там я использовал именованные каналы из .NET
— поищи такое же для плюсов
— нашел только QLocalsocket в Qt
(пауза)
— это слишком толстая либа, ставить ее на все компы заказчика не айс. Может, попробуем свою написать?
Собственно, как-то так оно и было. Заказчик системы тоже «шарит» и обладает чертой, присущей большинству заказчиков — не называет проблему, а требует запрогать то решение, которое пришло ему в голову, пытается контролировать процесс разработки.
С одной стороны это хорошо. С другой — когда влияние заказчика распространяется на выбор библиотек — нет.
Теперь мое видение велосипедостроения. Для того чтобы обучаться — писать велосипеды очень даже хорошо. И набивать шишки. Но с другой стороны, впаривать велосипеды заказчику совсем не хорошо. Хотя бы сточки зрения поддержки и уровня покрытия тестами кода. За 10мб Qt-библиотеки стоит большое коммьюнити разработчиков, сама библиотека использовалась в миллионах проектов и шанс словить в ней ошибку гораздо меньше шанса словить ошибки от велосипеда.
Только при написании этой статьи я убрал 6 багов из той версии, что сейчас крутится у заказчика. Ошибки были не критичные — при определенных условиях сервер посылал клиент после соединения, но клиент умел переподключаться, да пара утечек памяти (одна в деструкторе сервера, который никогда не вызывался).
Кроме этого, есть соглашение что имена пайпов должны быть на английском и хардкодятся в бинарниках. Ну, есть, конечно, опция с добавлением префиксов (если одна копия приложения на машине слушает, скажем 1ску а вторая — оракл), но там мы явно применяем конвертацию юникода в ascII, а в случае с 1с — еще и транслит.
Ну так все прогеры уже разбежались, и остался лишь «сам себе IT директор»
Отдельное спасибо за boost::future и packaged_task — мы давно хотели найти более удобный планировщик задач.
Извиняюсь, проглядел данный совет. В принципе я изначально был за, но полгода назад, во время рождения данной библиотеки, начальство было против данной замены (
>если будет выброшено исключение, то вы все равно продолжаете работу и пытаетесь обрабатывать сообщения.
Так надо. Одно исключение не должно валить весь сервер и обламывать других клиентов.
>Теряется всякая информация об ошибках, что не есть хорошо.
В статье написано, что внутри catch у нас было логирование. Но для статьи я убрал его, чтобы убрать зависимость итогового варианта от log4cxx. Но пустышки catch оставить пришлось, чтобы один эксепшн не валил приложения.
>в коде сервера встречаются строки вида: boost::this_thread::sleep(boost::posix_time::milliseconds(100)); Что убивает ваше стремление к производительности полностью.
Хорошо, сделаем засыпание на 1мс. Но оно все равно должно быть — иначе поедание ресуров процессора на холостом цикле будет слишком большим