zoukankan      html  css  js  c++  java
  • java的nio之:java的bio流下实现的socket服务器同步阻塞模型和socket的伪异步的socket服务器的通信模型

    同步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
  • 相关阅读:
    简单明了的带你理解springboot原理和三大核心注解
    Spring Boot(一):入门篇
    【Mysql优化】聚簇索引与非聚簇索引概念
    Mysql索引原理与优化
    Mysql全文索引的使用
    索引的优缺点,如何创建索引
    184 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 04 例:字符串与byte(即:字节)数组间的相互转换
    183 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 03 String常用方法(下)
    182 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 02 String常用方法(上)
    181 01 Android 零基础入门 03 Java常用工具类03 Java字符串 02 String类 01 String常用方法简介
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/5827323.html
Copyright © 2011-2022 走看看