2015-05-21 9 views
6

Ich bin eine Messaging-Anwendung mit Netty 4.1 Beta3 zum Entwerfen meines Servers erstellen und der Server versteht MQTT-Protokoll.Performance-Tuning für Netty 4.1 auf Linux-Rechner

Dies ist meine MqttServer.java-Klasse, die den Netty-Server einrichtet und an einen bestimmten Port bindet.

 EventLoopGroup bossPool=new NioEventLoopGroup(); 
     EventLoopGroup workerPool=new NioEventLoopGroup(); 

     try { 

      ServerBootstrap boot=new ServerBootstrap(); 

      boot.group(bossPool,workerPool); 
      boot.channel(NioServerSocketChannel.class); 
      boot.childHandler(new MqttProxyChannel()); 

      boot.bind(port).sync().channel().closeFuture().sync(); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     }finally {   
      workerPool.shutdownGracefully(); 
      bossPool.shutdownGracefully(); 
     } 
    } 

Jetzt habe ich einen Belastungstest meiner Anwendung auf meinem Mac die folgende Konfiguration enter image description here

Die netty Leistung war außergewöhnlich war. Ich habe mir den Jstack angesehen, während ich meinen Code ausgeführt habe, und festgestellt, dass netto NIO ungefähr 19 Threads erzeugt und keiner von ihnen scheint auf den Kanälen oder etwas anderem zu warten.

Dann ausgeführt ich meinen Code auf einem Linux-Rechner

enter image description here

Dies ist eine 2-Kern 15GB Maschine. Das Problem ist, dass das Paket von meinem MQTT Client gesendet scheint eine lange Zeit in Anspruch nimmt durch die netty Pipeline passieren und auch unter jstack Ich fand, dass es 5 netty Fäden waren und alle waren wie diese

."nioEventLoopGroup-3-4" #112 prio=10 os_prio=0 tid=0x00007fb774008800 nid=0x2a0e runnable [0x00007fb768fec000] 
     java.lang.Thread.State: RUNNABLE 
      at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method) 
      at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269) 
      at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79) 
      at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86) 
      - locked <0x00000006d0fdc898> (a 
io.netty.channel.nio.SelectedSelectionKeySet) 
      - locked <0x00000006d100ae90> (a java.util.Collections$UnmodifiableSet) 
      - locked <0x00000006d0fdc7f0> (a sun.nio.ch.EPollSelectorImpl) 
      at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97) 
      at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:621) 
      at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:309) 
      at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:834) 
      at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137) 
      at java.lang.Thread.run(Thread.java:745) 
hochnäsig

Ist das ein Leistungsproblem im Zusammenhang mit epoll auf Linux-Rechner? Wenn ja, welche Änderungen sollten an netty configuration vorgenommen werden, um damit umzugehen oder um die Leistung zu verbessern?

bearbeiten

Java Version auf lokales System ist: -

java version "1.8.0_40" Java (TM) SE Runtime Environment Java (1.8.0_40-b27 bauen) HotSpot (TM) 64-Bit Server VM (Build 25.40-b25, mixed mode)

Java-Version auf AWS ist: -

openjdk Version "1.8.0_40-intern" OpenJDK Runtime Environment (build 1.8.0_40-internal-b09) OpenJDK 64-Bit Server VM (Build 25.40-b13, mixed mode)

+0

Sind Sie sicher, dass Sie auf beiden Rechnern die gleichen Java-Versionen haben? Gleiches JVM? –

+0

versuchen Sie die neueste Version 4.1.0.Beta5. Ich lese über einige Fixes für Epoll. –

+0

@ArnaudPotier. Die JVM-Versionen sind unterschiedlich. –

Antwort

1

mit den Spielen um Worker-Threads, um zu sehen, ob dies die Leistung verbessert. Der Standard-Konstruktor von NioEventLoopGroup() erstellt die Standard-Menge von Ereignisschleife Themen:

DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
      "io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2)); 

Wie Sie sehen können Sie io.netty.eventLoopThreads als Start Argument übergeben kann, aber ich, dass in der Regel nicht tun. Sie können auch die Anzahl der Threads im Konstruktor NioEventLoopGroup() übergeben.

In unserer Umgebung haben wir Netty-Server, die die Kommunikation von Hunderten von Clients akzeptieren. Normalerweise genügt ein Boss-Thread, um die Verbindungen zu bewältigen. Die Worker-Thread-Menge muss jedoch skaliert werden.Wir verwenden diese:

private final static int BOSS_THREADS = 1; 
private final static int MAX_WORKER_THREADS = 12; 

EventLoopGroup bossGroup = new NioEventLoopGroup(BOSS_THREADS); 
EventLoopGroup workerGroup = new NioEventLoopGroup(calculateThreadCount()); 

private int calculateThreadCount() { 
    int threadCount; 
    if ((threadCount = SystemPropertyUtil.getInt("io.netty.eventLoopThreads", 0)) > 0) { 
     return threadCount; 
    } else { 
     threadCount = Runtime.getRuntime().availableProcessors() * 2; 
     return threadCount > MAX_WORKER_THREADS ? MAX_WORKER_THREADS : threadCount; 
    } 
} 

So in unserem Fall verwenden wir nur einen Chef-Thread. Die Worker-Threads hängen davon ab, ob ein Startargument angegeben wurde. Wenn nicht, dann verwenden Sie Kerne * 2 aber nie mehr als 12.

Sie müssen sich selbst testen, welche Zahlen für Ihre Umgebung am besten funktionieren.

+0

Ich habe das schon mal probiert, aber ohne Erfolg. Wir hatten etwa 10k Worker-Threads verwendet;) und auch einen CachedPoolExecutor angegeben, der jedoch die Latenz in keiner Weise reduziert hat. Das Problem besteht immer noch. Danke aber :) –

+2

10k Threads auf einem Dual-Core könnte kontraproduktiv sein und könnte auch Langsamkeit verursachen. http://stackoverflow.com/questions/481970/how-many-threads-is-too-many –

+0

Ich versuchte die 12 Threads auch. Noch gab mir nicht die erforderliche Leistung :( –