Netty and WebSocket application case

In the JD.com home business center system, merchants have put forward the need to implement automatic printing on the Web. They no longer need to manually keep track of prints and print small tickets directly to save on labor costs.

Solutions

Two thinking logics about the problem:

You can use ajax to poll the server for the latest order, which is pull.

It can be implemented in a push-like design, namely push.

We evaluated the advantages and disadvantages of the two ideas:

The ajax method is simple to implement. It only needs timing to pull data from the server, but it also increases the number of invalid polls, that is, it virtually increases the server invalid query.

The implementation of the push mode is slightly complicated, requiring the server and the PC to maintain the connection. This requires establishing a long connection and finally implementing a push effect through a long connection.

After discussion, we chose the second, and the new orders produced by the order center were pushed to the web through MQ, and finally got a better user experience.

An Introduction

Regarding the selection of the long connection scheme, we have referred to a lot of posts, and finally chose to use the websocket protocol to achieve long connections. Similar scenarios such as IM, instant push on the server side all use this protocol.

Next we compare the websocket framework, and compare the mainstream with netty, tomcat, sockeTIO three frameworks:

Based on websocket-enabled containers, the development is simple, such as tomcat, but the support for high concurrency is not very good, the connection is easily disconnected, and there is a dependent container.

netty-sockeTIO is based on netty4 and has a layer of encapsulation. The efficiency is the same as netty. It is a full platform solution and friendly API. Jingdong's logbook also uses sockeTIO to deliver logs. It is also an alternative for us.

Netty is the mainstream NIO framework in the industry. Netty encapsulates Java NIO, allowing developers to pay more attention to the business and reduce development costs.

Many well-known RPC frameworks use netty as the transport layer, friendly APIs, powerful functions, built-in codec protocols, and websocket protocol.

Then we compare these frameworks horizontally:

Netty and WebSocket application case

Therefore, we are still targeting sockeTIO and netty in terms of selection. While taking into account both scalability and flexibility, we also consider that netty can provide http functionality.

In the end, we chose to use netty. Of course, socketIO encapsulates a lot of features and is very powerful. In comparison, netty is more suitable for us and is lighter.

Netty features

Netty has asynchronous, non-blocking features. Traditional IO is stream-oriented and NIO is buffer-oriented, which is why it is non-blocking.

The netty thread model looks like this:

Netty and WebSocket application case

This model is what we often call the Reactor model. The boss thread is actually a separate NIO thread pool used to receive client requests. The default thread pool size is 1, the worker thread pool is used to handle specific read and write operations, and the default thread pool The size is 2*cpu number.

In the above model, we must pay special attention to the ExecutionHandler, ExecutionHandler is run in the worker thread, so the time-consuming operation is best to run in the thread pool, such as IO or calculation, or will affect the entire netty throughput.

Understand this, we design the flow according to one's own business, as shown below:

Step 1: The web server requests the server to register. The registration succeeds in maintaining a long connection.

Step 2: The server sends MQ.

Step 3: Netty pushes the received message to the web side.

Step 4: The Web side invokes the print control to print. The print control needs to be installed in advance (the print control is a driver installed on the PC and is called in JS mode).

If the call to JS is successful, the control will put the print information in the print queue. If it is unsuccessful, repeat step 4.

Netty and WebSocket application case

Of course, the current structure is only a stand-alone version and does not meet the production conditions. The future structure may evolve into the following diagram:

Netty and WebSocket application case

We will establish a routing layer between the server and netty. The main responsibilities of the routing layer are:

Collect cluster survival information

Record the landing point, which machine is on the top

Receive messages and news distribution

With these three capabilities, we can easily specify information distribution strategies. We want to use the http protocol for routing. This requires that netty has the ability to accept http short connections, so netty as a whole needs to connect two capabilities.

Here is a partial code:

The netty startup class, we start netty through spring, because the netty startup will block the main thread, so you need to start netty in the child thread, the following is the startup parameters.

Netty and WebSocket application case

Then write our ChannelInitializer, HttpServerCodec is the codec, and WSServerProtocolHandler is the websocket protocol handshake.

We are more concerned with customizing the two handers at the business level, httpRequestHandler, and authorizeHandler.

Netty and WebSocket application case

The role of httpRequestHandler is to handle whether the URL is valid and receive parameters.

httpRequestHandler This method can also be filtered based on the URL to customize your own short connection request.

Netty and WebSocket application case

The role of authorizeHandler is to check if the data is correct. If it is correct, the channel will be stored in the map and the relationship between the service ID and the channel will be established through the map.

The validation process is expanded in channelRead in authorizeHandler. If it fails, the current channel is closed directly.

If passed, the information is passed to the next handler via the ctx.fireChannelRead(msg); method.

In the project, data validation is mainly performed by passing parameters, that is, passing parameters through URLs.

In httpRequestHandler we set the URL parameter to channel's attr and pass it to the next handler, authorizeHandler.

So in the authorize method we can use the get() method to get the value of the parameter, u is the encrypted data, we need to decrypt it here, the decryption fails, we can think that the verification failed.

Of course, if you have a cross-application service, you can also use the cookie to read and write encrypted strings. You can obtain the information in the cookie through request.getHeader. This depends on the specific service.

The sample code is as follows:

Netty and WebSocket application case

This map can be understood as a session in the servlet. When information needs to be sent to a client, we call map.get(key) to the channel of the current client and call the writeAndFlush method to send information out. The logic behind the MQ message.

Someone may think of what to do next if the channel is closed. Is the channel in the map invalid?

In fact, we also need to have a heartbeat-like mechanism to maintain the channel, indirect to maintain the map.

If the channel is closed properly, you can listen to it using the channelInactive method.

If it is idle for a long time, we use the added IdleStateHandler in the project to handle idle channels by overriding the userEventTriggered method. When a channel reaches the timeout we set, netty will call back this method.

At this point, the core part has been processed, and the rest is to send information to the client through the saved channel.

Finally, on the Web side, we used reconnecting-websocket, which is a small JavaScript library that encapsulates the WebSocket API and provides a mechanism for automatically reconnecting when a connection is disconnected. This helps us to complete disconnected reconnections.

Problems encountered

After testing, no arguments can be passed after the uri of ws, otherwise disconnection will occur when netty implements the websocket protocol handshake.

For this case, a layer of httpHander filtering is done before the websocketHandler, passing parameters to the channel's attr, then overwriting the request's uri and passing it to the next pipe, basically solving the problem.

When reading and writing idle, try to maintain the connection by sending heartbeat packets. However, when the client is unstable or the server is restarting, the connection will be disconnected and the order message may not be received in an instant. Therefore, the client needs to do this. Implement disconnected reconnection mechanism.

For this problem, we use the JS framework of reconnecting-websocket. This framework extends the implementation of native websockets and does a disconnect and reconnection mechanism to effectively prevent timely disconnection after disconnection.

In the test process, due to problems with controls and ticket machines, printing abnormalities or small ticket machines may be out of paper. The Lodop control can put print information in the computer's print queue.

If there is no paper, the small ticket will be alarmed and put into a small ticket again. The printer will automatically print the data in the queue.

Occurrence of a call control exception occurs occasionally, and the processing method is now a try catch in JS.

If it fails, it will try again, and the number of retries will be customized. If the number of retries exceeds the number of times, it will not be processed for the time being. This is not yet rigorous and needs to be optimized.

to sum up

Through the above practices, we have basically achieved automatic printing on the Web side. After a long period of internal testing, the server and client communications are stable. We will use the grayscale business as a user experience.

In a particular scenario, choosing the right technology will increase our efficiency, otherwise it will be counterproductive.

With a long connection, everyone can grasp these three principles:

Whether the server needs to actively push data to the client for control.

The demand for real-time performance is harsh.

Whether the client needs to pay attention to the real-time changes of its online status.

Portable AC Ev Charger

China Portable 240V Ev Charger,Portable Electric Car Charger supplier & manufacturer, offer low price, high quality Portable Electric Vehicle Charger,Portable Level 2 Charger, etc.

Portable 240V Ev Charger,Portable Electric Car Charger,Portable Electric Vehicle Charger,Portable Level 2 Charger

Shenzhen Hongjiali New Energy Co., Ltd. , https://www.hjlcharger.com