Java – несколько селекторов в нескольких потоках для неблокирующих сокетов

StackOverflow https://stackoverflow.com/questions/1111527

Вопрос

Я пишу Java-приложение, которое будет создавать экземпляры объектов класса для представления клиентов, которые подключились и зарегистрировались во внешней системе на другой стороне моего приложения.

Внутри каждого клиентского объекта есть два вложенных класса, представляющих интерфейсную и серверную части.интерфейсный класс будет постоянно получать данные от реального клиента и отправлять указания и данные внутреннему классу, который будет брать эти данные из внешнего интерфейса и отправлять их во внешнюю систему, используя правильный формат и протокол. этого требует система.

При проектировании мы хотим, чтобы каждый экземпляр клиентского объекта был потоком.Тогда внутри каждого потока, естественно, будет два сокета [EDIT] со своими собственными каналами NIO каждый [/EDIT], один на стороне клиента, один на стороне системы, расположенный во внешнем и внутреннем интерфейсе соответственно.Однако теперь возникает необходимость в неблокирующих сокетах.Я читал учебник здесь это объясняет, как безопасно использовать селектор в основном потоке для обработки всех потоков с соединениями.

Но мне нужно несколько селекторов, каждый из которых работает в своем потоке.Прочитав вышеупомянутое руководство, я узнал, что наборы ключей в селекторе не являются потокобезопасными.Означает ли это, что отдельные селекторы, созданные в своих собственных репрезентативных потоках, могут создавать конфликтующие ключи, если я попытаюсь дать каждому из них собственную пару сокетов и каналов?Переместить селектор вверх в основной поток — небольшая возможность, но она далека от идеала, исходя из требований к программному обеспечению, которые мне предоставили.Спасибо за помощь.

Это было полезно?

Решение

Использование нескольких селекторов будет правильным, если вы не зарегистрируете один и тот же канал с одинаковыми интересами (OP_READ/OP_WRITE и т. д.) в обоих экземплярах селектора.Регистрация одного и того же канала с несколькими экземплярами селектора может вызвать проблему, когда selector1.select() может использовать событие, в котором может быть заинтересован selector2.select().

Селекторы по умолчанию на большинстве платформ основаны на методе poll() [или epoll()].

Selector.select внутренне вызывает int poll( ListPointer, Nfdsmsgs, Timeout) method.

        where the ListPointer structure can then be initialized as follows:

    list.fds[0].fd = file_descriptorA;
    list.fds[0].events = requested_events;
    list.msgs[0].msgid = message_id;
    list.msgs[0].events = requested_events;

Тем не менее, я бы рекомендовал использовать один поток выбора, как указано в руководстве ROX RPC nio.Реализации NIO зависят от платформы, и вполне возможно, что то, что работает на одной платформе, может не работать на другой.Я видел проблемы и в второстепенных версиях.Например, в AIX JDK 1.6 SR2 использовался селектор на основе poll() — PollSelectorImpl и соответствующий поставщик селектора — PollSelectorProvider, наш сервер работал нормально.Когда я перешел на AIX JDK 1.6 SR5, в которой использовался оптимизированный селектор на основе интерфейса опроса (PollSetSelectorImpl), мы столкнулись с частыми зависаниями на нашем сервере в методах select() и socketchannel.close().Одна из причин, которую я вижу, заключается в том, что мы открываем несколько селекторов в нашем приложении (в отличие от идеальной модели выбора потока) и реализацию PollSetSelectorImpl, как описано. здесь.

Другие советы

Если вам необходимо использовать это соединение с одним сокетом, вам придется отделить процесс приема и записи данных из канала и в канал от самой обработки данных.Вы не обязаны делегировать канал.Канал похож на автобус.Шина (единственный поток, который управляет каналом) должна читать данные и записывать их в (потокобезопасную) входную очередь, включая необходимую информацию, чтобы ваш клиентский поток(и) мог получить правильный пакет датаграмм из очередь.Если клиентский поток предпочитает записывать данные, эти данные записываются в очередь вывода, которая затем считывается потоком каналов для записи данных в канал.

Таким образом, от концепции совместного использования соединения между акторами, использующими это соединение с их непредсказуемым временем обработки (что является основной причиной возникновения блоков), вы переходите к концепции асинхронного чтения, обработки и записи данных.Таким образом, непредсказуемо больше не время обработки, а время чтения или записи ваших данных.Неблокируемость означает, что поток данных является максимально постоянным, независимо от того, сколько времени требуется для их обработки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top