该示例在jdk8与jdk17环境下,均支持。
首先引入netty依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.72.Final</version>
</dependency>
然后是一个简单的测试类
public class Test {
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024)
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new HttpServerCodec());
ch.pipeline().addLast(new HttpObjectAggregator(1 * 1024 * 1024));
ch.pipeline().addLast(WebSocketClientCompressionHandler.INSTANCE);
ch.pipeline().addLast(new WebSocketFrameAggregator(2 * 1024 * 1024));
ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", null, true, 2 * 1024 * 1024));
ch.pipeline().addLast(new RequestHandler());
}
}).bind(1601).sync().channel().closeFuture().sync();
}
}
public class RequestHandler extends SimpleChannelInboundHandler<Object> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object request) throws Exception {
if (request instanceof TextWebSocketFrame) {
String msg = ((TextWebSocketFrame) request).text();
System.out.println(msg);
ctx.writeAndFlush(new TextWebSocketFrame(msg));
}
if (request instanceof FullHttpRequest) {
boolean success = ((DecoderResultProvider) request).decoderResult().isSuccess();
System.out.println(success);
ByteBuf bb1 = Unpooled.wrappedBuffer("北京欢迎你\n".getBytes());
ByteBuf bb2 = Unpooled.wrappedBuffer("为你开天辟地\n".getBytes());
ByteBuf target = Unpooled.wrappedBuffer(bb1, bb2);
FullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, target);
fullHttpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain;charset=utf-8");
ctx.writeAndFlush(fullHttpResponse).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
ctx.close();
}
});
}
}
}
启动服务,完成!
可以注意到, 在workerGroup中设置的线程数量Runtime.getRuntime().availableProcessors(),那么这个数量是有说法的,或者说直接这么写可能达不到预期的效果。具体来讲, 跟使用的jdk版本有关,准确信息可以由文档中看出:
Java SE support for Docker CPU and memory limits
For those who have been using Docker’s CPU and memory limits with Java applications may have experienced some challenges. In particular CPU limits since the JVM internally and transparently sets the number of GC threads, and JIT compiler threads. These can be explicitly set via command line options, -XX:ParallelGCThreads and -XX:CICompilerCount. For memory limits, the maximum Java heap size can also be set explicitly via JVM command line option, -Xmx. However, in cases where none of the aforementioned JVM command line options are specified, when a Java application using Java SE 8u121 and earlier, when run in a Docker container, the JVM will use the underlying host configuration of CPUs and memory when transparently determining the number of GC threads, JIT compiler threads and maximum Java heap to use.
As of Java SE 8u131, and in JDK 9, the JVM is Docker-aware with respect to Docker CPU limits transparently. That means if -XX:ParalllelGCThreads, or -XX:CICompilerCount are not specified as command line options, the JVM will apply the Docker CPU limit as the number of CPUs the JVM sees on the system. The JVM will then adjust the number of GC threads and JIT compiler threads just like it would as if it were running on a bare metal system with number of CPUs set as the Docker CPU limit. If -XX:ParallelGCThreads or -XX:CICompilerCount are specified as JVM command line options, and Docker CPU limit are specified, the JVM will use the -XX:ParallelGCThreads and -XX:CICompilerCount values.
For Docker memory limits, there is a little more work for the transparent setting of a maximum Java heap. To tell the JVM to be aware of Docker memory limits in the absence of setting a maximum Java heap via -Xmx, there are two JVM command line options required, -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap. The -XX:+UnlockExperimentalVMOptions is required because in a future release transparent identification of Docker memory limits is the goal. When these two JVM command line options are used, and -Xmx is not specified, the JVM will look at the Linux cgroup configuration, which is what Docker containers use for setting memory limits, to transparently size a maximum Java heap size. FYI, Docker containers also use cgroups configuration for CPU limits too.
These two modifications in Java SE 8u131 and JDK 9 are expected to improve the Java running in Docker experience.
简单来讲,在容器环境下, 与jdk版本有关,jdk8u131版本及以后,对容器环境支持的更为友好
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。