Inter-system communication based on Java's own technology to realize message mode
The way of communication between systems based on Java itself package is: Tcp/ip+bio, Tcp/ip+nio, Udp/ip+bio and Udp/ip+nio 4 kinds, the following describes how to implement these 4 ways of inter-system communication.
Tcp/ip+bio
In Java, it is possible to implement TCP/IP+BIO communication between systems based on sockets and ServerSocket .
Socket is mainly used to establish the connection and network IO operation, ServerSocket is mainly used to realize the server-side port monitoring and socket object acquisition.
1, the key code to implement the client based on the socket is as follows:
//Create a connection, if the domain name can not parse will throw unknownhostexception, when the connection is not on the IOException will be thrown, if you want to control the timeout to establish a connection, you can call the new Socket (), Then call Socket.connect (the destination address of the socketaddress type, in milliseconds, time-out)Socket socket=NewSocket (destination IP or domain name, destination port);//Create BufferedReader to read the server-side return streamBufferedReaderinch=NewBufferedReader (NewInputStreamReader (Socket.getinputstream ()));//Create a PrintWriter to write to the serverPrintWriter out=NewPrintWriter (Socket.getoutputstream (),true);//Send string information to the server, note that even if write fails, exception information is not thrown and is always blocked until the write operating system or network IO exception occurs out. println ("Hello");//Block read the return information on the service side, the following code will block to the server return information or network IO exception, if you want to not block after a period of time, then after the creation of the socket object, call Socket.setsotimeout ( Time-out in milliseconds)inch. ReadLine ();
2, the server-side key code is as follows:
// 创建对本地指定端口的监听,如端口冲突则抛出SocketException,其他网络IO方面的异常则抛出IOExceptionServerSocket ss=new ServerSocket(监听的端口)// 接受客户端建立连接的请求,并返回Socket对象,以便和客户端进行交互,交互的方式和客户端相同,也是通过Socket.getInputStream和Socket.getOutputStream来进行读写操作,此方法会一直阻塞到有客户端发送建立连接的请求,如果希望此方法最多阻塞一定的时间,则要在创建ServerSocket后调用其setSoTimeout(以毫秒为单位的超时时间)Socket socket=ss.accept();
3, the performance analysis of the model
Above is an example of a simple inter-system communication based on the socket and ServerSocket implementations. In the actual system, it is usually to face the client to send multiple requests to the server side, the server side is also to accept multiple connections to send requests, the above code is obviously not satisfied.
To satisfy the client's ability to send multiple requests to the server side at the same time, the simplest way is to generate multiple sockets.
But here are two questions:
a)是生成太多的Socket会消耗过多的本地资源,在客户端机器多,服务器端机器少的情况下,客户端生成太多、Socket会导致服务器端须要支撑非常高的连接数;b)是生成Socket(建立连接)通常是比较慢的,因此频繁地创建会导致系统性能不足。
4. Connection Pool
In view of these two problems, it is usually better to use the connection pooling method to maintain the socket, which limits the number of sockets that can be created, on the other hand, because the socket is placed in the pool, the performance degradation caused by duplicate socket creation is avoided. Database connection pooling is a typical representation of this approach.
5, Connection pool should pay attention to the problem
However, the way to connect to the pool brings another problem, the number of sockets in the connection pool is limited, but at the same time to use the socket can be a lot of requests, in this case will cause fierce competition and waiting, there is a need to pay attention to the reasonable control of waiting for response time If you do not set the timeout will cause when the server-side processing slows down, client-related requests are doing infinite wait, and the client's resources must be limited.
Therefore, this situation can easily cause the client to hang up when there is a problem on the server side. The time-out is determined by how much the client can tolerate and the server-side processing time. To ensure performance, but also to ensure that the error rate is not too high, for a direct tcp/ip+bio-based approach, can be used Socket.setSoTimeout to set the waiting time to respond to the timeout.
In order to satisfy the request that the server can accept multiple connections at the same time, the usual method is to handle the socket in a thread after receiving the socket, which is often referred to as a connection line. This way the server can accept multiple connections to send requests, a disadvantage of which is to consume a thread regardless of whether there is a real request on the connection. To avoid creating too many threads that result in server-side resource exhaustion, limit the number of threads created, which results in a limited number of connections that can be supported on the server side in the case of bio.
Tcp/ip+nio
In Java, the communication between systems in Tcp/ip+nio mode can be implemented based on the correlation classes of channel and selector in Java.nio.channels. Channel has Socketchannel and Serversocketchannel two species.
Socketchannel is used to establish connection, listen to events and read and write, Serversocketchannel for listening port and listening connection events;
The program passes selector to get an event to handle.
1. The key code for implementing the client based on these two classes is as follows:
Socketchannel Channel=socketchannel. Open();Set to non-blocking mode channel. configureblocking(false);For non-blocking mode, returns false immediately, indicating that the connection is being established in the channel. Connect(socketaddress);Selector Selector=selector. Open();Register selector with the channel and connect events of interest channel. Register(Selector,selectionkey. OP_connect);Blocking to an IO event of interest occurs, or reaching the time-out, if you want to wait until an IO event of interest occurs, you can call the parameterless Select method and call the Selectnow method int nkeys= If you want to not block directly returning events that are currently of interest to you. Selector. SelectThe time-out (in milliseconds)//, such as Nkeys greater than 0, indicates that an IO event of interest occurred Selectionkey Skey=null;if (nkeys>0) {Set<SelectionKey> Keys=selector. Selectedkeys();for (Selectionkey Key:keys) {//For the event that the connection occurred if (key. Isconnectable()) {Socketchannel sc= (Socketchannel) key. Channel();Sc. configureblocking(false);Register an IO read event of interest, usually not directly register write events, in the case of the sending buffer is not full, is always writable, so such as registering a write event, without writing data, it is easy to cause CPU consumption -% of the phenomenon SKey = SC. Register(Selector, Selectionkey. OP_read);Establish SC for connection completion. Finishconnect();}//There is a stream to read else if (key. IsReadable()) {Bytebuffer Buffer=bytebuffer. Allocate(1024x768);Socketchannel sc= (Socketchannel) key. Channel();int readbytes=0;try{intret=0;try{//read current readable stream, SC. ReadReturns the number of bytes successfully copied to Bytebuffer, which is a blocking operation with a value that may be0When it is already the end of the stream, return-1while ((ret=sc. Read(buffer)) >0) {readbytes+=ret;}} finally{Buffer. Flip();}} finally{if (buffer!=null) {buffer. Clear();}}}//writable stream else if (key. iswritable()) {//Cancel registration of the Op_write event key. Interestops(Key. Interestops() & (~selectionkey. OP_write));Socketchannel sc= (Socketchannel) key. Channel();This step is a blocking operation until the write operating system send buffer or network IO exception occurs, returning the number of bytes successfully written, when the sending buffer of the operating system is full, this will return0int WRITTENEDSIZE=SC. Write(Bytebuffer);If not written, continue registering the Op_write event of interest if (writtenedsize==0) {Key. Interestops(Key. Interestops() | Selectionkey. OP_write);}}} Selector. Selectedkeys(). Clear();}//for the stream to be written, you can call the channel directly. WriteTo complete, register op_write event int Wsize=channel Only if the write is unsuccessful. Write(Bytebuffer);if (wsize==0) {Key. Interestops(Key. Interestops() | Selectionkey. OP_write);}
As can be seen from the above, NIO is a typical implementation of the reactor model by registering events of interest and scanning for events that are of interest, thus doing the corresponding actions.
2, the server-side key code is as follows:
ServerSocketChannel ssc=ServerSocketChannel.open();ServerSocket serverSocket=ssc.socket();// 绑定要监听的端口serverSocket.bind(new InetSocketAddress(port));ssc.configureBlocking(false);// 注册感兴趣的连接建立事件ssc.register(selector, SelectionKey.OP_ACCEPT);
The selector.select can then be polled in the same way as the client, just to add a handle to the key.isacceptable, with the following code:
if(key.isAcceptable()){ server=(ServerSocketChannel)key.channel(); SocketChannel sc=server.accept(); if(sc==null){ continue;} sc.configureBlocking(false); sc.register(selector,SelectionKey.OP_READ);}
The above is just a simple example based on the implementation of Tcp/ip+nio, as well as a look at how the Tcp/ip+nio supports the client to send multiple requests simultaneously and the server accepts multiple connections to send requests.
3, the mode performance analysis
There is no difference in the way that the client sends multiple requests, using Tcp/ip+nio and using Tcp/ip+bio. However, the NiO method can be non-blocking , so if the response returned by the server can bring the request identity, then the client can use a connection multiplexing , that is, every socketchannel after sending a message, do not wait for the response to continue to send other messages, This method can reduce the resource scramble problem caused by the connection pool, and improve the system performance.
对于连接不复用的情况,可基于Socket.setSoTimeout`的方式来控制同步请求的超时;对于连接复用的情况,同步请求的超时可基于BlockingQueue、对象的wait/notify机制或Future机制来实现。
For a server-side requirement to accept multiple connection requests, a thread is typically used to listen for connected events, while another or more threads listen for events that are read and written by the network stream .
When there is an actual network stream read-write event occurs, it is then put into the thread pool for processing. The benefit of this approach over Tcp/ip+bio is that many connections are acceptable, and these connections are created only when there is a real request, which is often referred to as a request thread. When the number of connections is low, or the number of connections is high, and the connection requests are sent very frequently, the Tcp/ip+nio approach does not bring much advantage, but in the actual scenario, the server side typically supports a large number of connections, but these connections do not send many requests at the same time.
When developing Java NIO programs based on the Sun JDK, pay particular attention to the handling of Selector.select throwing IOException exceptions and the situation where the selector.select is returned without blocking. Both of these situations can cause CPU consumption to reach 100%, and for Selector.select to throw IOException, you can bypass the method to catch the exception and sleep the current thread for a period of time, or recreate the selector. To avoid selector.select without blocking the direct return, you can use the bug library mentioned in the proposed modification.
As can be seen from the above, for high-traffic systems, the Tcp/ip+nio method combined with a certain transformation in the client can bring higher performance, on the server side can support the higher number of connections.
Udp/ip+bio
Java to the UDP/IP mode of network data transmission also uses the socket mechanism, just UDP/IP socket does not establish a connection requirements, because the UDP/IP is not connected, it is not possible to conduct two-way communication. This also requires that if two-way communication is required, both ends must become UDP servers.
In Java can be based on DatagramSocket和DatagramPacket the implementation of Udp/ip+bio mode of inter-system communication,Datagramsocket is responsible for listening to the port and read and write data. The datagrampacket is transmitted as a data flow object .
1. The key code for implementing the client based on these two classes is as follows:
//Because the UDP/IP is not connected, if you want to bidirectional communication, you must start a listening port, assume the responsibility of the server, such as cannot bind to the specified port, then throw SocketExceptionDatagramsocket serversocket=NewDatagramsocket (listening port);byte[] buffer=New byte[65507];D Atagrampacket receivepacket=NewDatagrampacket (buffer,buffer.length);D Atagramsocket socket=NewDatagramsocket ();D atagrampacket packet=NewDatagrampacket (Datas,datas.length,Server, port);//block sends packet to the specified server and port, throws IOException when a network IO exception occurs, throws portunreachableexception when the destination address and port are not connectedSocket.send (Packet)//block and synchronously read the stream information, such as the received stream information longer than the packet length, delete the longer information, you can set the read stream time-out by calling Datagramsocket.setsotimeout (time-out in milliseconds)Serversocket.receive (Receivepacket)
The structure of the server-side code and the client code is basically the same, not listed here.
Because the UDP/IP communication is not connected at both ends, there will be no competition for TCP/IP communication connection, but the final reading and writing flow is synchronous .
For the server side to receive multiple requests at the same time, usually take each received a packet into a thread to be processed in a way to achieve.
Udp/ip+nio
In Java, Datagramchannel and Bytebuffer can be used to achieve udp/ip+nio communication between systems,Datagramchannel is responsible for listening to ports and reading and writing, Bytebuffer for data flow transmission .
1. The key code for implementing the client based on these two classes is as follows:
Datagramchannel Receivechannel=datagramchannel. Open();Receivechannel. configureblocking(false);Datagramsocket Socket=receivechannel. Socket();Socket. Bind(New Inetsocketaddress (Rport));Selector Selector=selector. Open();Receivechannel. Register(Selector, Selectionkey. OP_read);The stream information can then be read in the same way as the selector traversal in Tcp/ip+nio. Datagramchannel Sendchannel=datagramchannel. Open();Sendchannel. configureblocking(false);SocketAddress target=new inetsocketaddress ("127.0.0.1", sport);Sendchannel. Connect(target);Blocks the write stream, such as the send buffer is full, returns0, this can be done by registering Selectionkey. OP_write event, so that the write operation can be written, and the Tcp/ip+nio is basically consistent sendchannel. Write(Bytebuffer);
The server-side code and the client code are basically the same, no longer one by one described.
From the above code, for the UDP/IP method, the benefit of NIO is to do the corresponding IO operation only when there is a stream to read or write to the stream, instead of blocking the current thread directly like the bio.
Multicast protocol for communication
The above list is based on the Java package implementation of one-to-one (client and server-to-one "communication") of the system communication between the way, in the actual scenario, usually also to send messages to multiple machines, at this time can choose to set up a connection for each target machine, This approach can cause significant network traffic pressure on the sending message side. For example, the transmission of the message is the scene of video data, there is a network protocol based on the UDP/IP extension of the Multicast protocol , multicast protocol transmission is a data on the network transmission, rather than by the sender to each receiver to send a copy of the data, so, The traffic on the network has dropped dramatically.
Multicast network communication can be implemented in Java based on MulticastSocket and Datagrampacket, MulticastSocket is a class based on Datagramsocket, and its role is based on udp/ IP enables multicast-type network communication. In multicast communication, the different place is to receive the data end by adding to the multicast group to receive the data, the same sending data also required to join the multicast group to send, multicast destination address has a specified address range, between 224.0.0.0 and 239.255.255.255 .
1. The server-side key code for network communication based on multicast is as follows:
// 组播地址InetAddress groupAddress=InetAddress.getByName("224.1.1.1"server=new MulticastSocket(port);// 加入组播,如地址为非组播地址,则抛出IOException,当已经不希望再发送数据到组播地址,或不希望再读取数据时,可调用server.leaveGroup(组播地址)serverclient=new MulticastSocket();client.joinGroup(groupAddress);
You can then use the receive and send methods to read and write like Udp/ip+bio. Client-side code and server-side code are basically the same, no longer listed.
In Java applications, multicasting is typically used to synchronize the state of multiple machines. For example JGroups, the default based on the UDP/IP multicast protocol, because the UDP/IP protocol in the data transmission is not reliable, for high reliability requirements of the system, will want to use a multicast method, but also to be reliable. For this demand, the industry has proposed ways to ensure reliable multicast: SRM (Scalable Reliable multicast), URGCP (Uniform Reliable Group communication Protocol), SRM is based on the UDP/IP multicast to add a confirmation mechanism, so as to ensure reliable, ebay uses the SRM framework to synchronize data from the main database to each search node machine.
From the above introduction, it is more troublesome to use Java packages to implement communication between systems based on message mode. In order for developers to focus more on the business of the data without paying too much attention to pure technical details, the open source industry has created many excellent frameworks for inter-system communication based on the various protocols above. The best of these is Mina.
Communication between systems based on message mode for distributed Java Applications (2)