All streams
Search
Write a publication
Pull to refresh
10
Konstantin Pavlov @xpavlovread⁠-⁠only

User

Send message
UPD: Нашел метод abort(), с помощью которого можно остановить все потоки корректно.
Он в курсе. 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с — еще и транслит.
>Не повезло, сочувствую.

Ну так все прогеры уже разбежались, и остался лишь «сам себе IT директор»
Было бы здорово, именно для этого я и сделал репозиторий на гитхабе, а не просто выложил zip с сорцами
Да, спасибо, как я написал ниже про засыпание — я просто невнимательно прочитал ваш комментарий.

Отдельное спасибо за boost::future и packaged_task — мы давно хотели найти более удобный планировщик задач.
Насчет агрегации — не уверен, но про разбивку подумаем, действительно, смешивать функционал в одном классе нехорошо.
>Для того чтобы избежать ненужного поллинга можно заменить тип очереди на concurrent_bounded_queue Тогда вы избавить от постоянной долбежки функции try_pop и будете дожидаться сообщения без поллинга.

Извиняюсь, проглядел данный совет. В принципе я изначально был за, но полгода назад, во время рождения данной библиотеки, начальство было против данной замены (
Спасибо за замечания и книгу.

>если будет выброшено исключение, то вы все равно продолжаете работу и пытаетесь обрабатывать сообщения.

Так надо. Одно исключение не должно валить весь сервер и обламывать других клиентов.

>Теряется всякая информация об ошибках, что не есть хорошо.

В статье написано, что внутри catch у нас было логирование. Но для статьи я убрал его, чтобы убрать зависимость итогового варианта от log4cxx. Но пустышки catch оставить пришлось, чтобы один эксепшн не валил приложения.

>в коде сервера встречаются строки вида: boost::this_thread::sleep(boost::posix_time::milliseconds(100)); Что убивает ваше стремление к производительности полностью.

Хорошо, сделаем засыпание на 1мс. Но оно все равно должно быть — иначе поедание ресуров процессора на холостом цикле будет слишком большим
Мы хотели максимально избавить внешние компоненты от сторонних зависимостей. Но, честно говоря, наличие указанных вами классов в asio мы проглядели. Спасибо за наводку.
Во время проектирования мы решили, что не будем создавать отдельный класс только ради акцепта новых клиентов. Хотя такое разделение было бы неплохо сделать. В .NET оно есть. Но там в серверный пайп можно и писать и читать.

Information

Rating
Does not participate
Location
Долгопрудный, Москва и Московская обл., Россия
Registered
Activity