Article directory
netty overview
Netty is a network programming framework based on java NIO encapsulation, which can help us develop network applications conveniently and quickly. For example, the famous dubbo framework is RPC remote service call based on netty. Netty encapsulates most of the underlying operations of NIO, so we need to have a certain understanding of NIO to better grasp the netty framework.
java NIO adopts synchronous non blocking technology. Compared with traditional BIO (synchronous blocking), it can handle more requests and make better use of CPU resources (a thread can handle multiple requests, while a BIO thread can only handle one). Synchronous block: when you cut your hair, you always stand on the edge waiting for the barber to cut the previous customer's hair and do nothing. Synchronous block: when you cut your hair, you first do your own things and come back from time to time to see if it's your turn.
. It sounds very nice, but unfortunately it has not been widely used, because the read and write operations are handed over to the operating system for processing, and the processing speed largely depends on the stability of the operating system and the quality of the kernel, so NIO is still the mainstream. netty is an excellent network programming framework based on NIO.
Someone will ask why netty is needed now that NIO is available? This is like why spring MVC is needed now that Servlet is available, and why spring boot is needed now that spring MVC is available. The operation of native NIO is more complex, and various mechanisms cause headache, which makes us unable to fully focus on the business requirements. Netty is to solve this problem. Let's take a look at the overall architecture model of netty.
netty architecture model
The architecture model of netty is further modified and optimized based on the master-slave Reactor multi-threaded model, which has evolved into the overall architecture model as shown in the figure below:
as shown in the figure above, when a client sends a request, BossGroup is mainly responsible for the Accept connection, and WorkerGroup is responsible for distributing tasks to different handlers. Each handler handles specific business logic. It should be noted that almost all operations in netty are asynchronous, so operations that want to get its specific status can be defined by addListener Implement the method monitoring. NioEventLoop is similar to the selector in NIO, and will always be in a loop.
Manually rolling an http server
.
Introducing netty into pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>netty</groupId> <artifactId>nettyDemo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/io.netty/netty-all --> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.20.Final</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>utf-8</encoding> </configuration> </plugin> </plugins> </build> </project>
Write netty server
package nettyhttp; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; public class TestServer { public static void main(String[] args) throws Exception { //Create BossGroup and workerGroup //bossGroup handles connection requests //workerGroup handles client business EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { //Startup class ServerBootstrap serverBootstrap = new ServerBootstrap(); //Set server parameters serverBootstrap.group(bossGroup, workerGroup)//Set up team .channel(NioServerSocketChannel.class)//Setup channel .childHandler(new TestServerInitializer());//Set up processor System.out.println("server is ready"); ChannelFuture channelFuture = serverBootstrap.bind(9090).sync();//Binding port channelFuture.channel().closeFuture().sync();//Asynchronous monitoring } finally { //Error closing connection gracefully bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
package nettyhttp; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpServerCodec; public class TestServerInitializer extends ChannelInitializer<SocketChannel>{ /** * Initialize pipeline */ @Override protected void initChannel(SocketChannel ch) throws Exception { //Get pipe ChannelPipeline pipeline = ch.pipeline(); //HTTP codec provided by netty pipeline.addLast("myHttpServerCodec",new HttpServerCodec()); //Add custom processor pipeline.addLast("myHttpServerHandler",new TestHttpServerHandler()); } }
package nettyhttp; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpObject; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.CharsetUtil; import java.net.URI; public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> { /** * Read client data * * @param ctx context * @param msg information * @throws Exception abnormal */ @Override protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { if (msg instanceof HttpRequest) { System.out.println("Client address: " + ctx.channel().remoteAddress()); HttpRequest httpRequest = (HttpRequest) msg; URI uri = new URI(httpRequest.uri()); if ("/favicon.ico".equals(uri.getPath())) { System.out.println("favicon.ico"); return; } //Reply to browser ByteBuf content = Unpooled.copiedBuffer("hello,I am the server", CharsetUtil.UTF_8); //Construct http response DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain;charset=UTF-8"); response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); ctx.writeAndFlush(response); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); } }
Up, as follows:
Operation test
Start the server as follows and print out "server is ready":
use a browser to access http://localhost:9090, as follows:
view console:
the reason why the server prints out the client address twice is that the browser accesses it twice. f12 look at the browser network:
! Here a simple http server is built.
Summary
. This blog explains some basic theoretical knowledge of netty and shows the usage of netty through an extremely simple demo. Maybe you have a feeling of To develop their own communication protocol, according to the actual business needs to customize a more suitable network application for the project, so that the project is more robust, with higher performance. There is no end to learning. I'd like to share with you!