Азур и Апач Мина

Я не уверен, связан ли этот вопрос с Mina или больше с Azure, но он связан с сетью. Я также добавил тег Netty, так как у Мины и Нетти много общих принципов работы в сети.

Надеюсь получить совет куда копать.

Я довольно долго использовал определенное приложение Mina в локальной сети, теперь я пытаюсь перенести его в облако. Я развертываю виртуальные машины Linux в Azure (у каждой есть общедоступный IP-адрес, но имеет ли это значение?).

Они подключаются (используя Mina) к машине за пределами Azure, которая также имеет собственный общедоступный IP-адрес. Обычное дело:

SocketConnector connector = new NioSocketConnector(numberOfConnectors);
ConnectFuture connectFuture = connector.connect(new
InetSocketAddress(remoteHost, remotePort));
connectFuture.awaitUninterruptibly(connectTimeout);

На той машине Mina за пределами Azure также работает Mina. Назовем это серверной машиной.

Он принимает такие соединения:

NioSocketAcceptor acceptor = new NioSocketAcceptor(acceptor_threads);
org.apache.mina.core.buffer.IoBuffer.setUseDirectBuffer(false);
acceptor.getSessionConfig().setTcpNoDelay(true);
acceptor.setReuseAddress(true);
acceptor.getSessionConfig().setSendBufferSize(buffer_size);
acceptor.getSessionConfig().setMinReadBufferSize(64000);
acceptor.getSessionConfig().setReceiveBufferSize(buffer_size);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, iddle_time);
acceptor.getFilterChain().addLast("codec", new
ProtocolCodecFilter(CodecFactory.getInstance()));
acceptor.setDefaultLocalAddress(new InetSocketAddress(port));

Когда приложения Azure подключаются к серверу, сервер сохраняет

IoSession session

для асинхронной отправки сообщений в будущем следующим образом:

session.write(message);

Это хорошо работало внутри локальной сети (без Azure), но в текущем развертывании сервер отправляет сообщение

2017-01-17/15:45:19.823/GMT-00:00 [nioEventLoopGroup-3-3] [...] DEBUG
Sending message to /13.94.143.139:41790

и машина Azure ничего не получает. Более того, через некоторое время на серверной машине возникает следующее исключение:

2017-01-17/16:01:11.419/GMT-00:00 [NioProcessor-4] [...] ERROR
Exception in IOHandlerConnection timed out
java.io.IOException: Connection timed out
    at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
    at sun.nio.ch.IOUtil.read(IOUtil.java:197)
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
    at org.apache.mina.transport.socket.nio.NioProcessor.read(NioProcessor.java:280)
    at org.apache.mina.transport.socket.nio.NioProcessor.read(NioProcessor.java:44)
    at org.apache.mina.core.polling.AbstractPollingIoProcessor.read(AbstractPollingIoProcessor.java:695)
    at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(AbstractPollingIoProcessor.java:668)
    at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(AbstractPollingIoProcessor.java:657)
    at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$600(AbstractPollingIoProcessor.java:68)
    at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:1141)
    at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

2017-01-17/16:01:11.424/GMT-00:00 [NioProcessor-3] [...] DEBUG sessionClosed

Я использую Mina версии 2.0.4 (да, она старая, но работает в локальной сети уже несколько лет).

Я настраиваю сеть Azure с помощью Java Azure SDK 1.0.0-beta3.

Network.DefinitionStages.WithCreate creatableNetwork = azure.networks()
                    .define(networkName)
                    .withRegion(region)
                    .withExistingResourceGroup(resourceGroup)
                    .withAddressSpace("10.0.0.0/20");

И создавать виртуальные машины как

VirtualMachine.DefinitionStages.WithCreate creatableVirtualMachine =
         azure.virtualMachines()
           .define(String.format(...))
           .withRegion(region)
           .withExistingResourceGroup(resourceGroup)
           .withNewPrimaryNetwork(creatableNetwork)                             
           .withPrimaryPrivateIpAddressStatic(inetAddress.getHostAddress())
           .withNewPrimaryPublicIpAddress(String.format("chr-vm-%04d", i))                  .withPopularLinuxImage(KnownLinuxVirtualMachineImage.UBUNTU_SERVER_16_04_LTS)
           .withRootUserName(linuxUserName)
           .withPassword(linuxUserPassword)                                                                    
           .withSize(VirtualMachineSizeTypes.STANDARD_D2_V2)                                                 
           .withNewStorageAccount(creatableStorageAccount);

Интересно, какие причины могут препятствовать перемещению сообщений с сервера на клиентские машины Azure? Конфигурация сети Azure? Конфигурация мины? (первые сообщения с клиентских машин на серверную приходят после их подключения)

Я надеюсь, что приведенная выше информация может содержать подсказку.


person Antonio    schedule 18.01.2017    source источник
comment
Не могли бы вы создать правило NSG для своей виртуальной машины, чтобы разрешить входящую связь? Если нет, обратитесь к руководство, чтобы настроить на портале Azure и снова попробовать приложение Mina. Любое обновление, пожалуйста, не стесняйтесь, дайте мне знать.   -  person Peter Pan    schedule 18.01.2017
comment
@PeterPan-MSFT ты волшебник! Благодарю вас! Раньше я не знал о NSG. Я разместил свой ответ ниже.   -  person Antonio    schedule 18.01.2017


Ответы (1)


Я решил свою проблему благодаря тому, что Peter Pan - MSFT упомянул о NSG - Network Security Group.

NSG контролирует правила входа и выхода, как брандмауэр Windows. Вы должны создать NSG, добавить к нему правила и назначить NSG определенному объекту:

Существует как минимум два варианта назначения NSG:

  • в подсеть сети
  • к сетевому интерфейсу

Существует руководство 1 и образец кода Java 2. В моем случае для каждой ВМ создается отдельный сетевой интерфейс (поскольку каждая ВМ имеет публичный IP). Итак, я назначил одну группу безопасности сети одной подсети.

Сначала создайте NSG:

NetworkSecurityGroup NSG = azure.networkSecurityGroups()
                    .define(networkSecurityGroup)
                    .withRegion(region)
                    .withExistingResourceGroup(resourceGroup)
                    .defineRule("Inbound")
                        .allowInbound()
                        .fromAnyAddress()
                        .fromAnyPort()
                        .toAnyAddress()
                        .toAnyPort()
                        .withAnyProtocol()
                        .withDescription("Incoming messsages")
                        .withPriority(100)
                        .attach()
                    .create();

Затем измените код, чтобы явно определить подсеть и назначить ей NSG ( subnet1 автоматически создается без NSG, если ни одна из них не определена явно)

Network.DefinitionStages.WithCreate creatableNetwork = azure.networks()
                    .define(networkName)
                    .withRegion(region)
                    .withExistingResourceGroup(resourceGroup)
                    .withAddressSpace("10.0.0.0/20")
                    .defineSubnet(subnetName)
                        .withAddressPrefix("10.0.0.0/20")
                        .withExistingNetworkSecurityGroup(NSG)
                        .attach();

Таким образом, остальная часть кода остается такой же, как и в вопросе выше.

Полезные ссылки:

  1. Учебное пособие по Azure Portal
  2. Пример NSG из SDK Java Azure
person Antonio    schedule 18.01.2017