Netty 4.0 на нескольких портах с несколькими протоколами?

Я ищу пример сервера, который сочетал бы обработчик http на порту 80 и обработчик protobuf на другом порту в одном банке. Спасибо!


person jestro    schedule 03.09.2012    source источник


Ответы (2)


Я не знаю, что именно вы ищете. Это всего лишь создание двух разных экземпляров ServerBootstrap, их настройка и вызов bind(..), вот и все.

person Norman Maurer    schedule 11.09.2012
comment
Ах хорошо. Я был сбит с толку, так как вызов sync для closeFuture — это просто способ предотвратить выход из программы. Спасибо! - person jestro; 20.09.2012
comment
Не могли бы вы добавить подробности? Если мы не вызовем sync() для ServerBootstrap, код завершится. Если мы вызовем sync(), то сможем выполнять только один ServerBootstrap за раз! Как это работает? - person Marc; 24.11.2014
comment
@Marc Вам нужен еще один поток, чтобы запустить другой ServerBootstrap. Они могут использовать заблокированный вызов, но блокировка ограничивается самим потоком. - person sja; 02.09.2015

С моей точки зрения, создание разных ServerBootstraps не совсем правильный путь, потому что это приведет к созданию неиспользуемых сущностей, обработчиков, двойной инициализации, возможной несогласованности между ними, совместному использованию или клонированию EventLoopGroups и т. д.

Хорошей альтернативой является просто создание нескольких каналов для всех необходимых портов на одном сервере Bootstrap. Если взять пример «Написание сервера сброса» из Netty 4.x «Начало работы» , мы должны заменить

    // Bind and start to accept incoming connections.
    ChannelFuture f = b.bind(port).sync(); // (7)

    // Wait until the server socket is closed.
    // In this example, this does not happen, but you can do that to gracefully
    // shut down your server.
    f.channel().closeFuture().sync()

С

    List<Integer> ports = Arrays.asList(8080, 8081);
    Collection<Channel> channels = new ArrayList<>(ports.size());
    for (int port : ports) {
        Channel serverChannel = bootstrap.bind(port).sync().channel();
        channels.add(serverChannel);
    }
    for (Channel ch : channels) {
        ch.closeFuture().sync();
    }
person Dmitry Spikhalskiy    schedule 04.09.2015
comment
но если вам нужен каждый порт для реализации другого протокола, разве вам не нужны 2 бутстрапа? - person user2573153; 16.04.2017
comment
@user2573153 user2573153 Это зависит от того, как вы хотите организовать свой код и настройку. Например, ChannelInitializer в моем проекте просматривает порт каналов и выбирает набор обработчиков для добавления в цепочку каналов. Таким образом, вместо двух отдельных загрузчиков вы можете инкапсулировать логику в файл ChannelInitializer. Или создайте абсолютно отдельные загрузчики, если это лучше для ваших нужд. - person Dmitry Spikhalskiy; 16.04.2017
comment
Безопасно ли иметь несколько bind для одного EventLoopGroup? Я думал, что bind эффективно блокирует, поэтому во всех примерах используется один выделенный EventLoopGroup для слушателя. - person Lawrence Wagerfield; 02.09.2017
comment
@LawrenceWagerfield Я давно использую этот код в производстве, и у меня нет проблем с этой конфигурацией. Нет, настоящей блокирующей частью здесь является ch.closeFuture().sync(). bootstrap.bind().sync() завершается быстро. - person Dmitry Spikhalskiy; 03.09.2017
comment
Будет ли во втором цикле вашего примера кода вызываться sync() для всех каналов или только для первого? Я предполагаю, что только первый (поскольку он блокирует). Итак, можем ли мы предположить, что это необязательно во время выполнения? Если у нас есть другие средства для поддержания основного потока в рабочем состоянии, мы должны пропустить его вызов. (ИЛИ мы должны запускать поток для каждого порта только для вызова sync() для полноты картины!?) - person OzgurH; 27.01.2018
comment
@OzgurH Он просто ждет закрытия каналов. Например, если вы хотите поставить какую-либо дополнительную очистку после него или по какой-либо другой причине. Или вам нужно предотвратить завершение вашего main() завершением приложения, потому что netty использует потоки демона. Итак, делаем sync() на ближайшем будущем первого канала, если возвращаемся из него - он закрыт и переходим на sync() на ближайшее будущее второго, если возвращаемся из sync() - он тоже закрыт. После проверки того, что все каналы сервера закрыты, мы можем быть уверены, что сервер не работает, и сделать все, что нам нужно, например, завершить приложение, выйдя из основного. - person Dmitry Spikhalskiy; 28.02.2018