1

Introduction

In fact, the most profitable people in the software world are not code writers. The code writers can only be called Ma Long, and the more advanced ones are called programmers. They are all hard work. So are there any high-level careers? This must be, their name is called the consultant.

Consultants help companies make plans, architectures, and optimizations. Sometimes a simple code change or an architecture adjustment can make software or processes run more efficiently, saving the company hundreds of millions of dollars in expenses.

Today, apart from introducing to you how to support both http and https protocols in netty, I will also introduce you to a website data optimization solution worth hundreds of millions of dollars. With this solution, one million dollars in annual salary is not a dream!

The goal of this article

This article will show you how to support both http and http2 protocols in a netty service. These two servers provide support for accessing multiple images. We will introduce how to return multiple images from the server. Finally, I will introduce a speed optimization program worth hundreds of millions of dollars, which will definitely benefit everyone.

Support multiple image services

For the server side, the service is started through ServerBootstrap. ServerBootstrap has a group method to specify the group of the acceptor and the group of the client.

    public ServerBootstrap group(EventLoopGroup group) 
    public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) 

Of course, you can specify two different groups, or you can specify the same group, it provides two group methods, there is not much difference in effect.

Here we create an EventLoopGroup in the main server, and then pass it to ImageHttp1Server and ImageHttp2Server. Then call the group method in the two servers respectively, and then configure the handler.

First look at the structure of ImageHttp1Server:

        ServerBootstrap b = new ServerBootstrap();
        b.option(ChannelOption.SO_BACKLOG, 1024);
        b.group(group).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO))
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch){
                ch.pipeline().addLast(new HttpRequestDecoder(),
                                      new HttpResponseEncoder(),
                                      new HttpObjectAggregator(MAX_CONTENT_LENGTH),
                                      new Http1RequestHandler());
            }
        });

We passed in the HttpRequestDecoder, HttpResponseEncoder and HttpObjectAggregator that come with netty. There is also a custom Http1RequestHandler.

Look at the structure of ImageHttp2Server:

ServerBootstrap b = new ServerBootstrap();
        b.option(ChannelOption.SO_BACKLOG, 1024);
        b.group(group).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch)  {
                ch.pipeline().addLast(sslCtx.newHandler(ch.alloc()), new CustProtocolNegotiationHandler());
            }
        });

For the sake of simplicity, we use http1 service by default if access is from http, and http2 service if access is from https.

So in the http2 service, we only need to customize the ProtocolNegotiationHandler instead of processing the clear text upgrade request.

http2 processor

In the TLS environment, we customize the CustProtocolNegotiationHandler and inherit from the ApplicationProtocolNegotiationHandler to interact between the client and the server protocol.

For the http2 protocol, the InboundHttp2ToHttpAdapterBuilder and HttpToHttp2ConnectionHandlerBuilder that netty comes with are used to convert the http2 frame into the FullHttpRequest object of http1. In this way, we can directly process the message in http1 format.

The conversion process is as follows:

DefaultHttp2Connection connection = new DefaultHttp2Connection(true);
        InboundHttp2ToHttpAdapter listener = new InboundHttp2ToHttpAdapterBuilder(connection)
                .propagateSettings(true).validateHttpHeaders(false)
                .maxContentLength(MAX_CONTENT_LENGTH).build();

        ctx.pipeline().addLast(new HttpToHttp2ConnectionHandlerBuilder()
                .frameListener(listener)
                .connection(connection).build());

        ctx.pipeline().addLast(new Http2RequestHandler());

The only difference between the converted http2 handler and the ordinary http1 handler is that an additional streamId attribute needs to be set in the request header and the response header.

And there is no need to deal with http1's unique 100-continue and KeepAlive. Others are no different from http1 handlers.

Process pages and images

Because we use a converter to convert the frame of http2 into a normal object of http1, it is not much different from the processing of http1 for requesting the corresponding page and image.

For the page, we need to get the html to be returned, and then set the CONTENT_TYPE to "text/html; charset=UTF-8", and then return:

    private void handlePage(ChannelHandlerContext ctx, String streamId,  FullHttpRequest request) throws IOException {
        ByteBuf content =ImagePage.getContent();
        FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, content);
        response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
        sendResponse(ctx, streamId, response, request);
    }

For images, we get the image to be returned, convert it to ByteBuf, then set CONTENT_TYPE to "image/jpeg", and then return:

    private void handleImage(String id, ChannelHandlerContext ctx, String streamId,
            FullHttpRequest request) {
        ByteBuf image = ImagePage.getImage(parseInt(id));
        FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, image);
        response.headers().set(CONTENT_TYPE, "image/jpeg");
        sendResponse(ctx, streamId, response, request);
    }

In this way, we can process page requests and image requests at the same time on the netty server side.

Speed optimization solution worth hundreds of millions

It's finally the most exciting part of this article. What is the speed optimization solution worth hundreds of millions of dollars?

Before I talk about this plan, let me tell you a story about flood fighting and rescue work. Two counties live by a big river. This big river is very unstable and floods often occur, but the heads of the two counties have very different practices.

The magistrate of County A was serious and responsible. He sent people to regularly inspect the river section to which he belonged, build embankments, plant trees, and patrol.

The head of County B never made inspections. When a river was overflowing, the head of County B organized people to fight floods, and then all the media reported on the great achievements of the head of County B in fighting floods. Finally, the head of County B was promoted to mayor because of his outstanding political achievements.

Okay, the story is over, next is our optimization. Regardless of whether the user requests a page or an image, the ctx.writeAndFlush(response) method needs to be called in the end to write back the response.

If you put it into a timed task, you can execute it regularly, as shown below:

ctx.executor().schedule(new Runnable() {
            @Override
            public void run() {
                ctx.writeAndFlush(response);
            }
        }, latency, TimeUnit.MILLISECONDS);

Then the server will send the corresponding response after the milliseconds specified by the latency. For example, here we set the value of latency to 5 seconds.

Of course, 5 seconds is not satisfactory, so the leader or client finds you and asks you to optimize it. You said that this performance problem is difficult. It involves Maxwell’s equations and the third law of thermodynamics, and it takes a month. The leader said yes, roll up your sleeves and work hard, and give you a 50% salary increase next month.

One month later, you changed the latency to 2.5 seconds and the performance increased by 100%. Is this optimization worth several hundred million?

Summarize

Of course, the last section was a joke for everyone, but the skills of using timed tasks in netty response should be firmly grasped by everyone, you know the reason!

For the examples in this article, please refer to: learn-netty4

This article has been included in http://www.flydean.com/34-netty-multiple-server/

The most popular interpretation, the most profound dry goods, the most concise tutorial, and many tips you don't know are waiting for you to discover!

Welcome to pay attention to my official account: "programs, those things", know the technology, know you better!


flydean
890 声望437 粉丝

欢迎访问我的个人网站:www.flydean.com