开发者社区> 无信不立> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

java的nio之:java的bio流下实现的socket服务器同步阻塞模型和socket的伪异步的socket服务器的通信模型

简介: 同步I/O模型的弊端===>每一个线程的创建都会消耗服务端内存,当大量请求进来,会耗尽内存,导致服务宕机伪异步I/O的弊端分析===>当对Socket的输入流进行读取操作的时候,它会一直阻塞下去,知道发生如下三件事情(1)有数据可读(2)可用数据已经读取完毕(3)发生空指针或者I/O异常===>这意味着当对方发送请求或应答消息比较缓慢,或者网络传输比较慢时候,读取输入流的一方的通信线程将被长时间阻塞。
+关注继续查看

同步I/O模型的弊端
===>每一个线程的创建都会消耗服务端内存,当大量请求进来,会耗尽内存,导致服务宕机

伪异步I/O的弊端分析
===>当对Socket的输入流进行读取操作的时候,它会一直阻塞下去,知道发生如下三件事情
(1)有数据可读
(2)可用数据已经读取完毕
(3)发生空指针或者I/O异常
===>这意味着当对方发送请求或应答消息比较缓慢,或者网络传输比较慢时候,读取输入流的一方的通信线程将被长时间阻塞。在阻塞期间,其他接入的消息只能在消息队列中排队。
===>伪异步I/O实际上仅仅只是对之前I/O线程模型的一个简单优化,它无法从根本上解决同步I/O导致的通信线程阻塞问题,下面我们简单分析下如果通信对方返回应答时间过长,会引起的级联鼓掌。
(1)服务端处理缓慢,返回应答消息耗费60s,平时只需要10ms
(2)采用伪异步I/O线程正在读取故障服务节点的响应,由于读取输入流是阻塞的。因此,它将会被同步阻塞60s
(3)假如所有的可用线程都被故障服务器阻塞,那后续所有的I/O消息都将在队列中排队。
(4)由于线程池采用阻塞队列实现,当队列积满之后,后续入队列的操作将被阻塞
(5)由于前端只有一个Accptor线程接收客户端接入,它被阻塞在线程池的同步阻塞队列之后,新的客户端请求消息将被拒绝,客户端会发生大量的连接超时。
(6)由于几乎所有的链接都超时,调用者会认为系统崩溃,无法接收新的请求消息。

【一】同步阻塞I/O服务端通信模型

 

第一:socket同步阻塞服务器的启动

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.IOException;
 4 import java.net.ServerSocket;
 5 import java.net.Socket;
 6 
 7 /**
 8  * 时间服务器
 9  * 基于同步阻塞I/O实现的服务器模型
10  * @author sxf
11  *
12  */
13 public class TimerServer {
14     
15     /**
16      * 启动timerServer服务器
17      */
18     public   void init(){
19         int port=8000;
20         //创建Socket服务
21         ServerSocket server=null;
22         try {
23             server=new ServerSocket(port);
24             System.out.println("TimerServer.init()===>the time server is start in port"+port);
25             Socket socket=null;
26             while(true){
27                 //获取一次socket请求
28                 socket=server.accept();
29                 //启动一个新线程处理socket请求
30                 new Thread(new TimerServerHandler(socket)).start();
31             }
32         } catch (IOException e) {
33             e.printStackTrace();
34         }finally{
35             if(server!=null){
36                 try {
37                     server.close();
38                 } catch (IOException e) {
39                     // TODO Auto-generated catch block
40                     e.printStackTrace();
41                 }
42             }
43             server=null;
44         }
45         
46     }
47 
48     
49     public static void main(String[] args) {
50         //启动timerServer服务
51         TimerServer timerServer=new TimerServer();
52         timerServer.init();
53     }
54 }
View Code

第二:soket服务器接收到请求的处理类

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.io.PrintWriter;
 7 import java.net.Socket;
 8 import java.util.Date;
 9 
10 /**
11  * 时间服务器接受socket请求的处理类
12  * @author sxf
13  * 继承Runnable接口的线程类
14  *
15  */
16 public class TimerServerHandler implements Runnable {
17     
18     private Socket socket;
19 
20     public TimerServerHandler(Socket socket) {
21         this.socket=socket;
22     }
23     
24     /**
25      * 处理socket请求的线程体
26      */
27     @Override
28     public void run() {
29         BufferedReader in=null;
30         PrintWriter out=null;
31         try {
32             //获取请求的输入流
33             in=new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
34             //获取响应请求的输出流
35             out=new PrintWriter(this.socket.getOutputStream(),true);
36             
37             String currentTime=null;
38             String body=null;
39             //读取请求输入流的内容获取请求信息
40             while(true){
41                 body=in.readLine();
42                 if(body==null){
43                     break;
44                 }
45                 //打印请求信息
46                 System.out.println("TimerServerHandler.run()==>the time server receive order:"+body);
47                 
48                 //处理请求信息
49                 if("shangxiaofei".equals(body)){
50                     currentTime=new Date(System.currentTimeMillis()).toString();
51                 }else{
52                     currentTime="you is not get time";
53                 }
54                 //响应请求信息
55                 out.println(currentTime);
56             }
57             
58         } catch (IOException e) {
59             e.printStackTrace();
60         }finally{
61             if(in!=null){
62                 try {
63                     in.close();
64                 } catch (IOException e) {
65                     // TODO Auto-generated catch block
66                     e.printStackTrace();
67                 }
68             }
69             
70             if(out!=null){
71                 out.close();
72             }
73             
74             if(this.socket!=null){
75                 try {
76                     socket.close();
77                 } catch (IOException e) {
78                     // TODO Auto-generated catch block
79                     e.printStackTrace();
80                 }
81             }
82             
83             this.socket=null;
84         }
85         
86         
87         
88         
89     }
90 
91 }
View Code

第三:向socket服务器发送请求

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.io.PrintWriter;
 7 import java.net.Socket;
 8 
 9 /**
10  * 创建一个客户端请求
11  * @author sxf
12  *
13  */
14 public class TimerClient {
15     
16     
17     
18     public static void main(String[] args) {
19         int port=8000;
20         Socket socket=null;
21         BufferedReader in=null;
22         PrintWriter out=null;
23         try {
24             socket=new Socket("127.0.0.1",port);
25             in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
26             out=new PrintWriter(socket.getOutputStream(),true);
27             //发送请求
28             out.println("shangxiaofei!=");
29             System.out.println("TimerClient.main()send order to server success");
30             
31             //等待服务器响应
32             String resp=in.readLine();
33             System.out.println("TimerClient.main(Now is:)"+resp);
34         } catch (Exception e) {
35             // TODO Auto-generated catch block
36             e.printStackTrace();
37         }finally{
38             if(out!=null){
39                 out.close();
40                 out=null;
41             }
42             if(in !=null){
43                 try {
44                     in.close();
45                 } catch (IOException e) {
46                     // TODO Auto-generated catch block
47                     e.printStackTrace();
48                 }
49                 in=null;
50             }
51             
52             if(socket!=null){
53                 try {
54                     socket.close();
55                 } catch (IOException e) {
56                     // TODO Auto-generated catch block
57                     e.printStackTrace();
58                 }
59             }
60         }
61     }
62 
63 }
View Code

 

 

【二】同步阻塞I/O服务端通信模型构造的伪异步通信模型

一:伪异步socket服务端启动(就是在同步的基础上使用了线程池)

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.IOException;
 4 import java.net.ServerSocket;
 5 import java.net.Socket;
 6 
 7 /**
 8  * 时间服务器
 9  * 基于同步阻塞I/O实现的服务器模型
10  * @author sxf
11  *
12  */
13 public class TimerServer {
14     
15     /**
16      * 启动timerServer服务器
17      */
18     public   void init(){
19         int port=8000;
20         //创建Socket服务
21         ServerSocket server=null;
22         try {
23             server=new ServerSocket(port);
24             System.out.println("TimerServer.init()===>the time server is start in port"+port);
25             Socket socket=null;
26             //创建处理socket请求的线程池
27             TimerServerHandlerExcetorPool pool=new TimerServerHandlerExcetorPool(50, 10000);
28             
29             while(true){
30                 //获取一次socket请求
31                 socket=server.accept();
32                 //将请求任务提交到线程池处理
33                 pool.execute(new TimerServerHandler(socket));
34             }
35         } catch (IOException e) {
36             e.printStackTrace();
37         }finally{
38             if(server!=null){
39                 try {
40                     server.close();
41                 } catch (IOException e) {
42                     // TODO Auto-generated catch block
43                     e.printStackTrace();
44                 }
45             }
46             server=null;
47         }
48         
49     }
50 
51     
52     public static void main(String[] args) {
53         //启动timerServer服务
54         TimerServer timerServer=new TimerServer();
55         timerServer.init();
56     }
57 }
View Code

二:伪异步socket服务处理socket请求的线程池

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.util.concurrent.ArrayBlockingQueue;
 4 import java.util.concurrent.ExecutorService;
 5 import java.util.concurrent.ThreadPoolExecutor;
 6 import java.util.concurrent.TimeUnit;
 7 /**
 8  * 处理socket服务器接收到的socket请求的线程池
 9  * @author sxf
10  *
11  */
12 public class TimerServerHandlerExcetorPool {
13 
14     private ExecutorService executorService;
15     
16     /**
17      * 初始化线程池
18      * @param maxPoolSize
19      * @param queueSize
20      */
21     public TimerServerHandlerExcetorPool(int maxPoolSize,int queueSize){
22         executorService=new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), maxPoolSize, 120L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize));
23     }
24     
25     /**
26      * 提交到线程池,执行socket请求任务
27      * @param runnable
28      */
29     public void execute(Runnable runnable){
30         executorService.execute(runnable);
31     }
32     
33 }
View Code

三:处理请求的Handler类(线程类)

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.io.PrintWriter;
 7 import java.net.Socket;
 8 import java.util.Date;
 9 
10 /**
11  * 时间服务器接受socket请求的处理类
12  * @author sxf
13  * 继承Runnable接口的线程类
14  *
15  */
16 public class TimerServerHandler implements Runnable {
17     
18     private Socket socket;
19 
20     public TimerServerHandler(Socket socket) {
21         this.socket=socket;
22     }
23     
24     /**
25      * 处理socket请求的线程体
26      */
27     @Override
28     public void run() {
29         BufferedReader in=null;
30         PrintWriter out=null;
31         try {
32             //获取请求的输入流
33             in=new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
34             //获取响应请求的输出流
35             out=new PrintWriter(this.socket.getOutputStream(),true);
36             
37             String currentTime=null;
38             String body=null;
39             //读取请求输入流的内容获取请求信息
40             while(true){
41                 body=in.readLine();
42                 if(body==null){
43                     break;
44                 }
45                 //打印请求信息
46                 System.out.println("TimerServerHandler.run()==>the time server receive order:"+body);
47                 
48                 //处理请求信息
49                 if("shangxiaofei".equals(body)){
50                     currentTime=new Date(System.currentTimeMillis()).toString();
51                 }else{
52                     currentTime="you is not get time";
53                 }
54                 //响应请求信息
55                 out.println(currentTime);
56             }
57             
58         } catch (IOException e) {
59             e.printStackTrace();
60         }finally{
61             if(in!=null){
62                 try {
63                     in.close();
64                 } catch (IOException e) {
65                     // TODO Auto-generated catch block
66                     e.printStackTrace();
67                 }
68             }
69             
70             if(out!=null){
71                 out.close();
72             }
73             
74             if(this.socket!=null){
75                 try {
76                     socket.close();
77                 } catch (IOException e) {
78                     // TODO Auto-generated catch block
79                     e.printStackTrace();
80                 }
81             }
82             
83             this.socket=null;
84         }
85         
86         
87         
88         
89     }
90 
91 }
View Code

四:客户端发送请求

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.io.PrintWriter;
 7 import java.net.Socket;
 8 
 9 /**
10  * 创建一个客户端请求
11  * @author sxf
12  *
13  */
14 public class TimerClient {
15     
16     
17     
18     public static void main(String[] args) {
19         int port=8000;
20         Socket socket=null;
21         BufferedReader in=null;
22         PrintWriter out=null;
23         try {
24             socket=new Socket("127.0.0.1",port);
25             in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
26             out=new PrintWriter(socket.getOutputStream(),true);
27             //发送请求
28             out.println("shangxiaofei!=");
29             System.out.println("TimerClient.main()send order to server success");
30             
31             //等待服务器响应
32             String resp=in.readLine();
33             System.out.println("TimerClient.main(Now is:)"+resp);
34         } catch (Exception e) {
35             // TODO Auto-generated catch block
36             e.printStackTrace();
37         }finally{
38             if(out!=null){
39                 out.close();
40                 out=null;
41             }
42             if(in !=null){
43                 try {
44                     in.close();
45                 } catch (IOException e) {
46                     // TODO Auto-generated catch block
47                     e.printStackTrace();
48                 }
49                 in=null;
50             }
51             
52             if(socket!=null){
53                 try {
54                     socket.close();
55                 } catch (IOException e) {
56                     // TODO Auto-generated catch block
57                     e.printStackTrace();
58                 }
59             }
60         }
61     }
62 
63 }
View Code

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
分布式服务器框架之Servers.Core库中实现 MongoEntityBase 实现阻塞 异步对MongoDB的增删改查
YFMongoDBModelBase类是个模板类,对模板参数进行了约束YFMongoEntityBase,必须要继承YFMongoEntityBase
0 0
【Spark Summit EU 2016】Glint: Spark的异步参数服务器
本讲义出自Rolf Jagerman在Spark Summit EU 2016上的演讲,主要介绍了Spark的异步参数服务器Glint,随着机器学习的数据量越来越多,其所生成的模型的规模也越来越大,于是就出现了模型大小已经超出了一台机器的内存的情况,于是就需要参数服务器来解决这一问题。
2784 0
Linux服务器的关机或者重启你一般会怎么操作?今天介绍5种办法,最后一种可以成救命草!
Linux服务器的关机或者重启你一般会怎么操作?今天介绍5种办法,最后一种可以成救命草!
0 0
+关注
无信不立
人无信不立,业不勤不精
文章
问答
文章排行榜
最热
最新
相关电子书
更多
网站/服务器取证 实践与挑战
立即下载
固守服务器的第一道防线——美联集团堡垒机的前世今生
立即下载
机器学习在大规模服务器治理复杂场景的实践
立即下载