Package com.jason.server

Source Code of com.jason.server.MasterServer

package com.jason.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.jason.Config;
import com.jason.server.clusters.ClustersCoder;
import com.jason.server.clusters.ClustersDecoder;
import com.jason.server.clusters.ClustersProcesser;
import com.jason.server.hander.CoderHandler;
import com.jason.server.hander.DecoderHandler;
import com.jason.server.hander.ProcessHandler;
import com.jason.util.MyStringUtil;

/**
*
* <li>类型名称:
* <li>说明:基于JAVA NIO 的面向TCP/IP的,非阻塞式Sockect服务器框架主类
* <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
* <li>创建日期:2011-11-9
* <li>修改人:
* <li>修改日期:
*/
public class MasterServer {
  private static Log log = LogFactory.getLog(MasterServer.class);// 日志记录器
  // 系统配置参数参数名
  private static final String PORT_NAME = "port";// 端口
  private static final String MAX_PRIORITY = "maxPriority";// 线程优先级
  private static final String REQUEST_WORKER = "requestWorker";// 请求处理线程因子/核
  private static final String MONITOR_WORKER = "monitorWorker";// 数据接收监听线程因子/核
  private static final String SOCKECT_SEND_BUFFER_SIZE = "sockectSendBufferSize";// sockect读取缓冲区大小
  private static final String SOCKECT_RECVEID_BUFFER_SIZE = "sockectReceiveBufferSize";// sockect发送缓冲区大小
 
  // 集群相关参数
  private static final String CLUSTERS_SWITCH = "clustersSwitch";// 集群开关
  private static final String CLUSTERS_PORT = "clustersPort";// 集群端口
  private static final String CLUSTERS_ROLE = "clustersRole";// 集群服务器责任
  private static final String MASTER_SERVER = "masterServer";// 集群管理服务器
 
  private static final String BROAD_SWITCH = "broadSwitch";// 广播开关
  private static final String KEEP_CONNECT = "keepConnect";
  private static final String TIME_OUT = "timeOut";// timeout 参数
  public static boolean keepConnect = false;// 是否保持链接
 
  private int sockectSendBufferSize = 64;// 默认为64k
  private int sockectReceiveBufferSize = 5;// 默认为5k
  private Boolean broadSwitch = false;//默认广播开关关闭
  private Integer timeOut = 10;// 默认没有收到数据的超时阀值为10分钟,超过指定时间没有收到数据立即关闭连接
 
  // 定义编码处理器,业务处理器,解码处理器
  private CoderHandler coderHandler;// 编码处理器
  private DecoderHandler decoderHandler;// 解码处理器
  private ProcessHandler processHandler;// 业务处理器
 
  // 定义集群编码处理器,集群处理器和集群解码处理器
  private ClustersCoder clustersCoder;// 集群编码处理器
  private ClustersDecoder clustersDecoder;// 集群解码处理器
  private ClustersProcesser clustersProcesser;// 集群处理器
  private Client localClient;// 连接到集群服务器的客户端
 
  private static volatile LinkedBlockingQueue<Response> broadMessages = new LinkedBlockingQueue<Response>();// 广播消息队列
  private String stockData;// 股指数据,多个股指之间用逗号分隔
 
  private ConcurrentHashMap<Object, Client> clients = new ConcurrentHashMap<Object, Client>();// 客户端链接映射表
  private ConcurrentHashMap<Object, Client> clustersClients = new ConcurrentHashMap<Object, Client>();// 集群服务上的所有节点服务器客户端链接映射表
  private ConcurrentHashMap<Object, Client> localClients = new ConcurrentHashMap<Object, Client>();// 连接到其他非管理服务器上的所有本地链接映射表
 
  private final AtomicInteger connectIndex = new AtomicInteger();// 连接序号
  private final AtomicInteger threadIndex = new AtomicInteger();// 线程索引号
  private final AtomicInteger keyIndex = new AtomicInteger();// 连接序号
 
  private volatile Integer port;// 业务处理服务器端口
 
  // 服务器集群参数变量
  private Boolean clustersSwitch = false;// 集群开关,默认不开启
  private Integer clustersPort = 9292;// 集群端口,默认为9292
  private Integer clustersRole = 1;// 集群服务器责任,默认为普通业务服务器
  private String masterServer;// 集群管理服务器
 
  private Thread connectMonitor;// 连接处理线程
  private Thread clustersMonitor;// 集群连接处理线程
 
  private int coreCount = 1;// CPU内核数量
  private int readerWriterCount = 2;// 读写监听线程数量
  private int workerCount = 1;// 工作线程数量

  private ArrayList<ReadWriteMonitor> readWriteMonitors;// 客户发送请求监督程序
 
  private Thread broadMessageThread;// 发送广播消息的线程
  private Thread clustersClientThread;// 发送广播消息的线程
 
  private Thread clientMonitor;// 客户端连接数据接收状况监听,对于超过时限没有接收到数据的客户端关闭连接
 
  private volatile BlockingQueue<Worker> workers;// 读取的工作线程
  private volatile ArrayList<Worker> workersList;// 读取线程列表
   
  private volatile boolean noStopRequested = true;// 循环控制变量
 
  public MasterServer(CoderHandler coderHandler, DecoderHandler decoderHandler, ProcessHandler processHandler)throws IOException{
    // 设置端口
    this.port = Config.getInt(PORT_NAME);// 从配置中获取端口号
    if(this.port == null){
      this.port = 9090;// 设置默认端口为9090
    }
   
    // 设置超时
    this.timeOut = Config.getInt(TIME_OUT);// 获取配置中的超时设置
    if(this.timeOut == null){
      this.timeOut = 10;// 设置默认超时时限为10分钟
    }
   
    // 设置线程优先级
    Integer serverPriority = Config.getInt(MAX_PRIORITY);// 获取配置中的线程优先级
    if(serverPriority == null){
      serverPriority = 5;// 设置默认线程优先级
    }
   
    // 设置请求读取处理线程每个核心的线程数
    Integer requestWorker = Config.getInt(REQUEST_WORKER);
    if(requestWorker == null){
      requestWorker = 5;
    }
   
    // 设置请求响应处理线程每个核心的线程数
    Integer monitorWorker = Config.getInt(MONITOR_WORKER);
    if(monitorWorker == null){
      monitorWorker = 1;
    }
   
    // 设置sockect数据接收缓冲区大小
    Integer receiveBuffer = Config.getInt(SOCKECT_RECVEID_BUFFER_SIZE);
    if(receiveBuffer != null){
      this.sockectReceiveBufferSize = receiveBuffer;
    }
   
    // 设置sockect数据读取缓冲区大小
    Integer sendBuffer = Config.getInt(SOCKECT_SEND_BUFFER_SIZE);
    if(sendBuffer != null){
      this.sockectSendBufferSize = sendBuffer;
    }
   
    //设置是否保存长连接
    Integer keepAlive = Config.getInt(KEEP_CONNECT);
    if(keepAlive != null){
      keepConnect = (keepAlive == 1 ? true : false);
    }
   
    // 设置广播开关
    Boolean broad = Config.getBoolean(BROAD_SWITCH);
    if(broad != null){
      this.broadSwitch = broad;
    }
   
    // 设置集群开关
    Boolean clustersSwitch = Config.getBoolean(CLUSTERS_SWITCH);
    if(clustersSwitch != null){
      this.clustersSwitch = clustersSwitch;
    }
   
    // 设置集群端口
    Integer clustersPort = Config.getInt(CLUSTERS_PORT);
    if(clustersPort != null){
      this.clustersPort = clustersPort;
    }
   
    // 设置服务器的职责
    Integer clustersRole = Config.getInt(CLUSTERS_ROLE);
    if(clustersRole != null){
      this.clustersRole = clustersRole;
    }
   
    // 设置集群中的上级服务器
    String masterServer = Config.getStr(MASTER_SERVER);
    if(masterServer != null){
      this.masterServer = masterServer;
    }
   
    // 设置解码器,编码器和业务处理器
    this.coderHandler = coderHandler;
    this.decoderHandler = decoderHandler;
    this.processHandler = processHandler;
   
    this.coreCount = Runtime.getRuntime().availableProcessors();
    this.readerWriterCount = coreCount * monitorWorker;
    this.workerCount = coreCount * requestWorker;
   
    this.workers = new ArrayBlockingQueue<Worker>(this.workerCount);
    this.workersList = new ArrayList<Worker>(this.workerCount);//响应处理线程列表
   
    for(int i = 0; i < this.workerCount; ++i){
      workersList.add(new Worker(serverPriority,workers));     
    }   
   
    readWriteMonitors = new ArrayList<ReadWriteMonitor>(this.readerWriterCount);
    for(int i = 0; i < this.readerWriterCount;++i){
      readWriteMonitors.add(create(serverPriority));// 创建请求发送监听线程
    }
   
    if(this.broadSwitch){// 根据开关是否创建广播线程
      this.createBroadMessageThread(serverPriority);//创建广播消息线程
    }
   
    this.createConnectDistributeThread(serverPriority);// 创建业务连接建立监听线程
   
    if(this.timeOut > 0){
      this.createClientMonitorThread(serverPriority);// 创建客户端数据接收状态监听线程
    }   
   
    // 处理集群初始化
    if(this.clustersSwitch){
      // 创建集群编码解码器和集群业务处理器
      this.clustersCoder = new ClustersCoder();
      this.clustersDecoder = new ClustersDecoder();
      this.clustersProcesser = new ClustersProcesser();
     
      this.createClustersDistributeThread(serverPriority);// 创建集群连接建立监听线程
     
      // 连接到自己的直接管理服务器节点
      if((this.clustersRole == 1 || this.clustersRole == 3) && !MyStringUtil.isBlank(this.masterServer)){
        this.createClustersClientThread(serverPriority);// 创建集群通信客户端消息处理线程
      }
    }
  }
 
  /**
   *
   * <li>方法名:createClustersClientThread
   * <li>@param serverPriority
   * <li>返回类型:void
   * <li>说明:创建集群服务器客户端处理线程
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-22
   * <li>修改人:
   * <li>修改日期:
   */
  private void createClustersClientThread(int serverPriority) {
    // 集群服务器通信处理客户端线程
    Runnable writeDistributeRunner = new Runnable(){
      public void run(){
        try{
          startClustersMessage();
        }catch(Exception e){
          e.printStackTrace();
        }
      }     
    };
   
    this.clustersClientThread = new Thread(writeDistributeRunner);
    this.clustersClientThread.setName("集群通信客户端消息处理线程");
    this.clustersClientThread.setPriority(serverPriority);
    this.clustersClientThread.start();
    log.info("集群通信客户端消息处理线程创建完毕");
  }
 
  /**
   *
   * <li>方法名:startClustersMessage
   * <li>
   * <li>返回类型:void
   * <li>说明:开始处理集群通信客户端的消息
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-22
   * <li>修改人:
   * <li>修改日期:
   */
  protected void startClustersMessage(){
    Boolean isConnect = true;// 是否连接集群服务器
    SocketChannel socketChannel = null;// 连接客户端通道
   
    String[] address = this.masterServer.split(":");// 集群服务器地址
    if(address.length < 2){// 集群服务器地址错误
      log.info("集群服务器地址配置错误,集群服务器地址格式为:ip:port,例如:192.168.2.32:9090,请重新配置后再启动");
      return;
    }
    
    if(MyStringUtil.isBlank(address[0]) || MyStringUtil.isBlank(address[1])){// 集群服务器ip地址错误
      log.info("集群服务器ip地址配置错误,集群服务器ip地址格式为:ip:port,例如:192.168.2.32:9090,请重新配置后再启动");
      return;
    }         
    
    InetSocketAddress socketAddress = new InetSocketAddress(address[0], Integer.parseInt(address[1]));
    
    while(noStopRequested){
      try{       
        if(isConnect && socketChannel == null){// 第一次连接或连接断开都需要连接到集群服务器上
        try{          
           if(socketChannel != null && socketChannel.isConnected() && !socketChannel.isOpen()){
             socketChannel.close()
             log.info("已经连接到集群服务器,但连接断开,重新连接")
           }
           socketChannel = SocketChannel.open();
           socketChannel.configureBlocking(false);
           socketChannel.socket().setSoTimeout(0);
           socketChannel.socket().setTcpNoDelay(true);
               socketChannel.socket().setReuseAddress(true);
              
               socketChannel.socket().setReceiveBufferSize(this.sockectReceiveBufferSize * 1024);// 设置接收缓存
               socketChannel.socket().setSendBufferSize(this.sockectSendBufferSize * 1024);// 设置发送缓存
          
               socketChannel.connect(socketAddress);
              
               if(socketChannel.finishConnect()){
                 //socketChannel.finishConnect();// 连接建立完成
                 isConnect = false;// 不需要做连接服务器了的操作了,已经连接上集群服务器了                  
                 this.readWriteMonitors.get(Math.abs(this.connectIndex.getAndIncrement())
                     % this.readWriteMonitors.size()).registeClient(socketChannel);                
                 log.info("成功连接到集群服务器  " + address[0] + " 的端口:" + address[1]);
                 Thread.sleep(60 * 1000);// 休眠60秒钟
                }
              
              }catch(ClosedChannelException e){ 
                  log.info("连接集群服务器失败")
              }catch(IOException e){ 
                  log.info("连接集群服务器失败")
              }
        }else{// 处理消息监听
          if(isConnect && socketChannel.isConnectionPending()){// 正在连接服务器
            Thread.sleep(1000);// 正在连接,等待30秒
          }
         
          try {
            if(isConnect && socketChannel.finishConnect()){// 已经建立连接
               try{
                socketChannel.finishConnect();// 连接建立完成
                  isConnect = false;// 不需要做连接服务器了的操作了,已经连接上集群服务器了   
                this.readWriteMonitors.get(Math.abs(this.connectIndex.getAndIncrement())
                       % this.readWriteMonitors.size()).registeClient(socketChannel);
              }catch(IOException e){               
                log.warn(e.getMessage());
              }                
              log.info("成功连接到集群服务器  ");
              Thread.sleep(60 * 1000);// 休眠60秒钟
            }
          } catch (IOException e) {
            log.warn(e.getMessage());
          }
         
          if(!isConnect && !socketChannel.isConnected()){// 到集群服务器的连接端口,重新连接
            isConnect = true;
            try{
              socketChannel.connect(socketAddress);
            }catch(IOException e){
              log.warn(e.getMessage());
            }// 重新连接
            continue;
          }
         
          if(!isConnect && socketChannel.isConnected()){
            // 汇报本服务的负载情况到集群管理服务器
            if(this.localClient != null){// 已经连接好,等待通信
              StringBuilder sb = new StringBuilder();
              sb.append("节点服务器:").append(this.localClient.getLocalAddress()).append("\r\n")
              .append("服务器CPU内核数量:").append(this.coreCount).append("\r\n")
              .append("服务器读写监听线程数量:").append(this.readerWriterCount).append("\r\n")
              .append("服务器工作线程数量:").append(this.workerCount).append("\r\n")
              .append("活跃连接客户端数量:").append(this.clients.keySet().size()).append("\r\n")
              .append("活跃集群连接客户端数量:").append(this.clustersClients.keySet().size()).append("\r\n")
              .append("活跃本地连接客户端数量:").append(this.localClients.keySet().size()).append("\r\n");
             
              log.info(sb.toString());
              StringBuilder msg = new StringBuilder("action=1&");
              msg.append("coreCount=").append(this.coreCount).append("&")
              .append("readerWriterCount=").append(this.readerWriterCount).append("&")
              .append("workerCount=").append(this.workerCount).append("&")
              .append("clientCount=").append(this.clients.keySet().size()).append("&")
              .append("clustersCount=").append(this.clustersClients.keySet().size()).append("&")
              .append("port=").append(this.port).append("&")
              .append("localCount=").append(this.localClients.keySet().size());
             
              Response response = new Response();
              response.setBody(msg.toString());
              this.localClient.sendMessage(response);
              //coreCount=4&readerWriterCount=8&workerCount=32&clientCount=10000&clustersCount=5&localCount=4&port=9191
            }
            Thread.sleep(30 * 1000);//10分钟检查一次
          }
        }       
      }catch(InterruptedException e){
        e.printStackTrace();
      }
    }   
  }
   
  /**
   *
   * <li>方法名:createBroadMessageThread
   * <li>@param serverPriority
   * <li>返回类型:void
   * <li>说明:创建广播线程
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-22
   * <li>修改人:
   * <li>修改日期:
   */
  private void createBroadMessageThread(int serverPriority) {
    // 消息广播线程
    Runnable writeDistributeRunner = new Runnable(){
      public void run(){
        try{
          startBroadMessage();
        }catch(Exception e){
          e.printStackTrace();
        }
      }     
    };
   
    this.broadMessageThread = new Thread(writeDistributeRunner);
    this.broadMessageThread.setName("消息广播线程");
    this.broadMessageThread.setPriority(serverPriority);
    this.broadMessageThread.start();
    log.info("消息广播线程创建完毕");
  }
 
  /**
   *
   * <li>方法名:addReadWriteMonitors
   * <li>@param count
   * <li>返回类型:void
   * <li>说明:
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-30
   * <li>修改人:
   * <li>修改日期:
   */
  public Boolean addReadWriteMonitors(Integer count){   
    for(int i = 0; i < count;++i){
      readWriteMonitors.add(create(5));// 创建请求发送监听线程
    }
   
    return true;
  }
 
  /**
   *
   * <li>方法名:addWorkers
   * <li>@param count
   * <li>返回类型:void
   * <li>说明:
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-30
   * <li>修改人:
   * <li>修改日期:
   */
  public Boolean addWorkers(Integer count){
    for(int i = 0; i < this.workerCount; ++i){
      workersList.add(new Worker(5,workers));     
    }
   
    return true;
  }

  /**
   *
   * <li>方法名:startBroadMessage
   * <li>
   * <li>返回类型:void
   * <li>说明:开始处理广播消息
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-22
   * <li>修改人:
   * <li>修改日期:
   */
  protected void startBroadMessage(){   
    while(noStopRequested){
      try{
        Response msg = broadMessages.take();//获取广播消息
        Iterator<Client> it = this.clients.values().iterator();
        boolean isCode = false;     
        while(it.hasNext()){
          //log.info(msg.getBody());
          Client socketer = it.next();
          if(!isCode){
            isCode = true;
            msg.codeMsg(socketer);
          }
         
          socketer.addBroadMsg(Response.msgRespose(msg));
          try{
            workers.take().processResponse(socketer);
          }catch(Exception e){
            e.printStackTrace();
          }
        }
       
      }catch(InterruptedException e){
        e.printStackTrace();
      }
    }   
  }
   
  /**
   *
   * <li>方法名:startInputMonitor
   * <li>@throws InterruptedException
   * <li>@throws IOException
   * <li>返回类型:void
   * <li>说明:如果有客户端发送数据给服务器,服务器将放入到读取缓存池
   * <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2011-9-29
   * <li>修改人:
   * <li>修改日期:
   */
 
  public ReadWriteMonitor create(int serverPriority){
    ReadWriteMonitor inputMonitorThread = new ReadWriteMonitor();
    inputMonitorThread.setPriority(serverPriority);
    inputMonitorThread.start();
   
    return inputMonitorThread;
  }
 
  /**
   *
   * <li>类型名称:SockectServer
   * <li>说明:
   * <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2011-11-8
   * <li>修改人:
   * <li>修改日期:
   */
  public class ReadWriteMonitor extends Thread{   
    private final AtomicBoolean wakenUp = new AtomicBoolean();   
    private Selector selector;// 选择器
    private ConcurrentLinkedQueue<SocketChannel> localSocketChannels = new ConcurrentLinkedQueue<SocketChannel>();//本地连接通道注册队列
    private ConcurrentLinkedQueue<SocketChannel> socketChannels = new ConcurrentLinkedQueue<SocketChannel>();//通道注册队列
    private ConcurrentLinkedQueue<SocketChannel> clustersSocketChannels = new ConcurrentLinkedQueue<SocketChannel>();//集群通道注册队列
    private ConcurrentLinkedQueue<SocketChannel> clientSocketChannels = new ConcurrentLinkedQueue<SocketChannel>();//集群客户端或其他客户端通道注册队列
    private ConcurrentLinkedQueue<SelectionKey> readKeys = new ConcurrentLinkedQueue<SelectionKey>();// 选择键注册read队列
    private ConcurrentLinkedQueue<SelectionKey> writeKeys = new ConcurrentLinkedQueue<SelectionKey>();// 选择键注册write队列
    private volatile LinkedBlockingQueue<SelectionKey> readPool = new LinkedBlockingQueue<SelectionKey>();// 读取队列
    private Thread processDistributer;// 客户请求响应分配线程
   
    public ReadWriteMonitor(){
      try {
        this.selector = Selector.open();
        this.setName("请求数据传输监听线程" + threadIndex.getAndIncrement());
        log.info("数据读取回写监听线程创建成功:" + this.getName());
        this.createProcessDistributer();// 创建回写响应线程
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
   
    /**
     *
     * <li>方法名:registe
     * <li>@param socketChannel
     * <li>@throws IOException
     * <li>返回类型:void
     * <li>说明:将sockect channel注册到轮询器上
     * <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
     * <li>创建日期:2012-2-2
     * <li>修改人:
     * <li>修改日期:
     */
    public void registe(SocketChannel socketChannel) throws IOException {   
      // Register the new SocketChannel with our Selector, indicating
      // we'd like to be notified when there's data waiting to be read     
      this.socketChannels.offer(socketChannel);
     
      if (wakenUp.compareAndSet(false, true)) {
              selector.wakeup();
          }
    }
   
    /**
     *
     * <li>方法名:registeClusters
     * <li>@param socketChannel
     * <li>@throws IOException
     * <li>返回类型:void
     * <li>说明:注册集群客户端连接通道
     * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
     * <li>创建日期:2012-10-22
     * <li>修改人:
     * <li>修改日期:
     */
    public void registeClusters(SocketChannel socketChannel) throws IOException {   
      // Register the new SocketChannel with our Selector, indicating
      // we'd like to be notified when there's data waiting to be read     
      this.clustersSocketChannels.offer(socketChannel);
     
      if (wakenUp.compareAndSet(false, true)) {
              selector.wakeup();
          }
    }
   
    /**
     *
     * <li>方法名:registeLocalClient
     * <li>@param socketChannel
     * <li>@throws IOException
     * <li>返回类型:void
     * <li>说明:注册本地连接通道
     * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
     * <li>创建日期:2012-10-28
     * <li>修改人:
     * <li>修改日期:
     */
    public void registeLocalClient(SocketChannel socketChannel) throws IOException {   
      // Register the new SocketChannel with our Selector, indicating
      // we'd like to be notified when there's data waiting to be read     
      this.localSocketChannels.offer(socketChannel);
     
      if (wakenUp.compareAndSet(false, true)) {
              selector.wakeup();
          }
    }
   
    /**
     *
     * <li>方法名:registeClient
     * <li>@param socketChannel
     * <li>@throws IOException
     * <li>返回类型:void
     * <li>说明:注册连接到集群服务器的本地连接通道
     * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
     * <li>创建日期:2012-10-28
     * <li>修改人:
     * <li>修改日期:
     */
    public void registeClient(SocketChannel socketChannel) throws IOException {   
      // Register the new SocketChannel with our Selector, indicating
      // we'd like to be notified when there's data waiting to be read     
      this.clientSocketChannels.offer(socketChannel);
     
      if (wakenUp.compareAndSet(false, true)) {
              selector.wakeup();
          }
    }
   
    /**
     *
     * <li>方法名:interestWriteOps
     * <li>@param key
     * <li>@throws IOException
     * <li>返回类型:void
     * <li>说明:注册写事件
     * <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
     * <li>创建日期:2012-2-2
     * <li>修改人:
     * <li>修改日期:
     */
    public void registeWrite(SelectionKey key){         
      this.writeKeys.offer(key);
     
      if (wakenUp.compareAndSet(false, true)) {
              selector.wakeup();
          }
    }
   
    /**
     *
     * <li>方法名:interestReadOps
     * <li>@param key
     * <li>@throws IOException
     * <li>返回类型:void
     * <li>说明:注册读取事件
     * <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
     * <li>创建日期:2012-2-2
     * <li>修改人:
     * <li>修改日期:
     */
    public void registeRead(SelectionKey key) throws IOException {         
      this.readKeys.offer(key);
     
      if (wakenUp.compareAndSet(false, true)) {
              selector.wakeup();
          }
    }
   
    /**
     *
     * <li>方法名:processRegisteAnd
     * <li>
     * <li>返回类型:void
     * <li>说明:处理读取通道注册和读取事件注册
     * <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
     * <li>创建日期:2011-11-21
     * <li>修改人:
     * <li>修改日期:
     */
    private void processRegisteAndOps(){
      SocketChannel socketChannel = this.clustersSocketChannels.poll();
      // 集群服务器连接通道注册
      while(socketChannel != null){// 处理新建立的链接
        SelectionKey sk = null;
        try {
          sk = socketChannel.register(this.selector, SelectionKey.OP_READ);         
          Client sockector = new Client(sk,MasterServer.this,this);
           
          // 根据key中的标识位判断是否为集群
          sockector.registeHandler(clustersCoder, clustersDecoder, clustersProcesser);// 注册集群处理器
         
          sk.attach(sockector);         
          MasterServer.this.clustersClients.put(sockector.getRouteAddress(), sockector);
        }catch(Exception e){
          e.printStackTrace();
          try {
            if(sk != null ){
              sk.interestOps(0);
              sk.cancel();
            }
            socketChannel.close();
          }catch(IOException e1){
            e1.printStackTrace();
          }
        }// 将事件注册放到一个容器中统一进行处理
        socketChannel = this.clustersSocketChannels.poll();
      }
     
      // 注册本地连接通道
      socketChannel = this.localSocketChannels.poll();
      // 集群服务器连接通道注册
      while(socketChannel != null){// 处理新建立的链接
        SelectionKey sk = null;
        try {
          sk = socketChannel.register(this.selector, SelectionKey.OP_READ);         
          Client sockector = new Client(sk,MasterServer.this,this);
           
          // 根据key中的标识位判断是否为集群
          sockector.registeHandler(clustersCoder, clustersDecoder, clustersProcesser);// 注册集群处理器
         
          sk.attach(sockector);         
          MasterServer.this.localClients.put(sockector.getRouteAddress(), sockector);
        }catch(Exception e){
          e.printStackTrace();
          try {
            if(sk != null ){
              sk.interestOps(0);
              sk.cancel();
            }
            socketChannel.close();
          }catch(IOException e1){
            e1.printStackTrace();
          }
        }// 将事件注册放到一个容器中统一进行处理
        socketChannel = this.localSocketChannels.poll();
      }
     
      // 注册集群客户端请求通道的选择器
      socketChannel = this.clientSocketChannels.poll();
      while(socketChannel != null){// 处理新建立的链接
        SelectionKey sk = null;
        try {
          sk = socketChannel.register(this.selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ);
          Client sockector = new Client(sk,MasterServer.this,this);
         
          // 根据key中的标识位判断是否为集群
          sockector.registeHandler(clustersCoder, clustersDecoder, clustersProcesser);// 注册集群处理器
         
          sk.attach(sockector);
         
          sockector.requestHandShak();// 发起握手请求       
          MasterServer.this.localClient = sockector;
        }catch(Exception e){
          e.printStackTrace();
          try {
            if(sk != null ){
              sk.interestOps(0);
              sk.cancel();
            }
            socketChannel.close();
          }catch(IOException e1){
            e1.printStackTrace();
          }
        }// 将事件注册放到一个容器中统一进行处理
        socketChannel = this.clientSocketChannels.poll();
      }
     
      // 注册业务请求通道的选择器
      socketChannel = this.socketChannels.poll();
      while(socketChannel != null){// 处理新建立的链接
        SelectionKey sk = null;
        try {
          sk = socketChannel.register(this.selector, SelectionKey.OP_READ);
          Client sockector = new Client(sk,MasterServer.this,this);
         
          // 根据key中的标识位判断是否为集群
          //sockector.registeHandler(clustersCoder, clustersDecoder, clustersProcesser);// 注册集群处理器
          if(MasterServer.this.clustersSwitch && MasterServer.this.clustersRole == 2){
            sockector.registeHandler(coderHandler, decoderHandler, clustersProcesser);// 注册业务处理器
          }else{
            sockector.registeHandler(coderHandler, decoderHandler, processHandler);// 注册业务处理器
          }                     
         
          sk.attach(sockector);
          Integer index = keyIndex.incrementAndGet();
          sockector.setIndex(index);// 设置索引
          clients.put(index, sockector);// 放入到连接中         
        }catch(Exception e){
          e.printStackTrace();
          try {
            if(sk != null ){
              sk.interestOps(0);
              sk.cancel();
            }
            socketChannel.close();
          }catch(IOException e1){
            e1.printStackTrace();
          }
        }// 将事件注册放到一个容器中统一进行处理
        socketChannel = this.socketChannels.poll();
      }
     
      // 处理注册读取监听事件
      SelectionKey key = this.readKeys.poll();// 处理已经建立链接,上次请求读取完毕,再次注册读取事件监听器
      while(key != null){
        try{
          if(key.isValid()){
            key.interestOps(key.interestOps() | SelectionKey.OP_READ);// 关注读取事件           
          }
        }catch(Exception e){
          Client.getSockector(key).close();
          e.printStackTrace();
        }
       
        key = this.readKeys.poll();
      }
     
      // 处理注册回写监听事件
      key = this.writeKeys.poll();// 处理已经建立链接,注册写事件
      while(key != null){
        try{
          if(key.isValid()){
            key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);// 关注读取事件
          }
        }catch(Exception e){
          Client.getSockector(key).close();
          e.printStackTrace();
        }
       
        key = this.writeKeys.poll();
      }
     
      wakenUp.set(false);// 设置睡眠标识
    }
   
    public void run(){
      try{
        startInputMonitor();
      }catch(Exception e){
        e.printStackTrace();
      }
    }
   
    private void startInputMonitor(){   
      while(noStopRequested){ 
        try{
          //this.processRegisteAndOps();// 处理通道监听注册和读取事件注册
         
          int num = 0;
          //this.selector.selectedKeys().clear();// 清除所有key
          // Wait for an event one of the registered channels
          num = this.selector.select(50);
         
          //num = this.selector.selectNow();
          if (num > 0){
            // Iterate over the set of keys for which events are available
            Iterator selectedKeys = this.selector.selectedKeys().iterator();
            while (selectedKeys.hasNext()) {
              SelectionKey key = (SelectionKey) selectedKeys.next();
              selectedKeys.remove();
             
              if (!key.isValid()) {
                Client sk = Client.getSockector(key);
                if(sk != null){
                  sk.close();
                }
                continue;
              }
   
              if (key.isReadable()){
                Client sockector = Client.getSockector(key);               
                sockector.unregisteRead();// 解除监听器对该连接输入数据的监听
                //key.interestOps(key.interestOps() ^ SelectionKey.OP_READ);
                addToReadPoll(key);// 添加到读取请求队列中
              }
             
              if (key.isWritable()){
                Client.getSockector(key).sendMsgs();
              }
            }
          }
         
          this.processRegisteAndOps();// 处理通道监听注册和读取事件注册
        }catch(Exception e){
          e.printStackTrace();
        }
      }   
    }
   
    /**
     *
     * <li>方法名:addToReadPoll
     * <li>@param key
     * <li>返回类型:void
     * <li>说明:将需要读取请求,进行处理的通道放入队列中
     * <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
     * <li>创建日期:2012-2-6
     * <li>修改人:
     * <li>修改日期:
     */
    public void addToReadPoll(SelectionKey key){
      // 如果客户端链接还没有放入读取等待队列或没有正在处理,则将key放入读取队列,否则不做任何处理
      if(Client.getSockector(key).getInRead().compareAndSet(false, true)){
        this.readPool.add(key);
      }
    }
   
    /**
     *
     * <li>方法名:createWriteDistributeThread
     * <li>@return
     * <li>返回类型:Thread
     * <li>说明:创建响应回写处理线程,负责调度响应回写任务
     * <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
     * <li>创建日期:2012-1-19
     * <li>修改人:
     * <li>修改日期:
     */
    private Thread createProcessDistributer(){
      // 创建请求响应分配线程
      Runnable writeDistributeRunner = new Runnable(){
        public void run(){
          try{
            startProcessDistribute();
          }catch(Exception e){
            e.printStackTrace();
          }
        }
      };
     
      this.processDistributer = new Thread(writeDistributeRunner);
      this.processDistributer.setName("响应处理线程");
      log.info("请求处理调度线程创建完毕");
      this.processDistributer.setPriority(Thread.NORM_PRIORITY);// 普通优先级
      this.processDistributer.start();
     
      return processDistributer;
    }
   
    /**
     *
     * <li>方法名:startProcessDistribute
     * <li>
     * <li>返回类型:void
     * <li>说明:响应调度处理程序
     * <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
     * <li>创建日期:2012-2-6
     * <li>修改人:
     * <li>修改日期:
     */
    private void startProcessDistribute(){       
      while(noStopRequested){
        try{
          workers.take().processResponse(this.readPool.take());
        }catch(Exception e){
          e.printStackTrace();
        }
      } 
    }
  }
 
  /**
   *
   * <li>方法名:addBroadMessage
   * <li>@param msg
   * <li>返回类型:void
   * <li>说明:将要广播的消息放到广播线程中,有广播线程负责广播
   * <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2011-10-9
   * <li>修改人:
   * <li>修改日期:
   */
  public static void addBroadMessage(Response msg){
    broadMessages.add(msg);
  }
 
  // 创建链接调度线程
  private void createClientMonitorThread(int serverPriority){
    //创建监听线程
    noStopRequested = true;
    Runnable monitorRunner = new Runnable(){
      public void run(){
        try{
          startClientMonitor();
        }catch(Exception e){
          e.printStackTrace();
        }
      }
    };
   
    this.clientMonitor = new Thread(monitorRunner);
    this.clientMonitor.setName("客户端数据接收状况监听主线程");
    log.info("客户端数据接收状况监听主线程创建成功");
    this.clientMonitor.setPriority(serverPriority);
    this.clientMonitor.start();
  }
 
  /**
   *
   * <li>方法名:startClientMonitor
   * <li>
   * <li>返回类型:void
   * <li>说明:开始执行客户端数据发送状况监听
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-12
   * <li>修改人:
   * <li>修改日期:
   */
  private void startClientMonitor(){     
    while(noStopRequested){
      try {
        if(this.timeOut > 0){// 超时阀值       
          Iterator<Object> it = clients.keySet().iterator();
          while(it.hasNext()){
            try{
              Object key = it.next();
              Client client = clients.get(key);
             
              if(client.getReadStatus() == 1){// 将没有上传过数据的连接状态由1设置为4,如果下个周期检查到状态还为4,则果断关闭连接
                client.setReadStatus(4);
              }
             
              if(client.getReadStatus() == 2){// 将上传过数据的连接状态由2设置为3,如果下个周期检查到状态还为3,则果断关闭连接
                client.setReadStatus(3);
              }
             
              if(client.getReadStatus() == 3){// 关闭超时还没有交互的连接
                client.close();// 关闭连接
                clients.remove(key);// 从映射表中删除连接
              }
             
              if(client.getReadStatus() == 4){// 关闭一直没有发送数据的连接
                client.close();// 关闭连接
                clients.remove(key);// 从映射表中删除连接
              }
            }catch(Exception e){
             
            }       
          }
         
          this.clientMonitor.sleep(this.timeOut * 60 * 1000);// 暂停10分钟
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  /**
   *
   * <li>方法名:createConnectDistributeThread
   * <li>@param serverPriority
   * <li>返回类型:void
   * <li>说明:创建连接建立请求监听线程
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-21
   * <li>修改人:
   * <li>修改日期:
   */
  private void createConnectDistributeThread(int serverPriority){
    //创建监听线程
    noStopRequested = true;
    Runnable monitorRunner = new Runnable(){
      public void run(){
        try{
          startMonitor();
        }catch(Exception e){
          e.printStackTrace();
        }
      }
    };
   
    this.connectMonitor = new Thread(monitorRunner);
    this.connectMonitor.setName("sockent 接收主线程1");
    log.info("连接监听线程创建成功");
    this.connectMonitor.setPriority(serverPriority);
    this.connectMonitor.start();
  }
 
  /**
   *
   * <li>方法名:createClustersDistributeThread
   * <li>@param serverPriority
   * <li>返回类型:void
   * <li>说明:创建集群连接建立请求监听线程
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-21
   * <li>修改人:
   * <li>修改日期:
   */
  private void createClustersDistributeThread(int serverPriority){
    //创建监听线程
    noStopRequested = true;
    Runnable monitorRunner = new Runnable(){
      public void run(){
        try{
          startClustersMonitor();
        }catch(Exception e){
          e.printStackTrace();
        }
      }
    };
   
    this.clustersMonitor = new Thread(monitorRunner);
    this.clustersMonitor.setName("sockent 集群接收主线程");
    log.info("集群连接监听线程创建成功");
    this.clustersMonitor.setPriority(serverPriority);
    this.clustersMonitor.start();
  }
 
  /**
   *
   * <li>方法名:startClustersMonitor
   * <li>
   * <li>返回类型:void
   * <li>说明:开始监听集群服务器节点中的连接请求
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-21
   * <li>修改人:
   * <li>修改日期:
   */
  private void startClustersMonitor(){   
    try{
      // Create a new selector
      Selector selector = Selector.open();
     
      // Create a new non-blocking server socket channel
      ServerSocketChannel serverChannel = ServerSocketChannel.open();
      serverChannel.configureBlocking(false);
     
      InetSocketAddress isa = new InetSocketAddress(this.clustersPort);// 集群端口
      serverChannel.socket().bind(isa);     
           
      // Register the server socket channel, indicating an interest in
      // accepting new connections
      serverChannel.register(selector, SelectionKey.OP_ACCEPT);
     
      log.info("集群服务器准备就绪,等待集群请求到来");
      while(noStopRequested){
        try {         
          int num = 0;
          // Wait for an event one of the registered channels
          num = selector.select(100);
          if (num > 0) {
            // Iterate over the set of keys for which events are available
            Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
            while (selectedKeys.hasNext()) {
              SelectionKey key = (SelectionKey) selectedKeys.next();
              selectedKeys.remove();
             
              if (!key.isValid()) {
                continue;
              }
   
              // Check what event is available and deal with it
              if (key.isAcceptable()) {
                this.accept(key,true);// 注册集群连接
              }
            }
          }         
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
     
      serverChannel.close();// 关闭服务器
     
    }catch(Exception e){
      e.printStackTrace();
      System.out.println("Clusters Server start up fail");
    }
  }
 
  /**
   *
   * <li>方法名:startMonitor
   * <li>
   * <li>返回类型:void
   * <li>说明:开始监听业务请求处理
   * <li>创建人:CshBBrain;技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2011-9-28
   * <li>修改人:
   * <li>修改日期:
   */
  private void startMonitor(){   
    try{
      // Create a new selector
      Selector selector = Selector.open();
     
      // Create a new non-blocking server socket channel
      ServerSocketChannel serverChannel = ServerSocketChannel.open();
      serverChannel.configureBlocking(false);
     
      InetSocketAddress isa = new InetSocketAddress(this.port);
      serverChannel.socket().bind(isa);     
           
      // Register the server socket channel, indicating an interest in
      // accepting new connections
      serverChannel.register(selector, SelectionKey.OP_ACCEPT);
     
      log.info("服务器准备就绪,等待请求到来");
      while(noStopRequested){
        try {         
          int num = 0;
          // Wait for an event one of the registered channels
          num = selector.select(100);
          if (num > 0) {
            // Iterate over the set of keys for which events are available
            Iterator selectedKeys = selector.selectedKeys().iterator();
            while (selectedKeys.hasNext()) {
              SelectionKey key = (SelectionKey) selectedKeys.next();
              selectedKeys.remove();
             
              if (!key.isValid()) {
                continue;
              }
   
              // Check what event is available and deal with it
              if (key.isAcceptable()) {
                this.accept(key,false);
              }
            }
          }         
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
     
      serverChannel.close();// 关闭服务器
     
    }catch(Exception e){
      e.printStackTrace();
      System.out.println("Server start up fail");
    }
  }
 
  /**
   *
   * <li>方法名:accept
   * <li>@param key
   * <li>@param isClusters
   * <li>@throws IOException
   * <li>返回类型:void
   * <li>说明:根据请求创建连接,可以是来自客户端的请求,也可能是来自集群中其他服务器的请求
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-21
   * <li>修改人:
   * <li>修改日期:
   */
  private void accept(SelectionKey key,Boolean isClusters) throws IOException {
    // For an accept to be pending the channel must be a server socket channel.
    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();

    // Accept the connection and make it non-blocking
    SocketChannel socketChannel = serverSocketChannel.accept();
    socketChannel.configureBlocking(false);// 设置为非阻塞式
   
   
    socketChannel.socket().setReceiveBufferSize(this.sockectReceiveBufferSize * 1024);// 设置接收缓存
    socketChannel.socket().setSendBufferSize(this.sockectSendBufferSize * 1024);// 设置发送缓存
   
    socketChannel.socket().setSoTimeout(0);
   
    socketChannel.socket().setTcpNoDelay(true);
    if(keepConnect){//使用长连接,保持连接状态
      socketChannel.socket().setKeepAlive(true);
    }
   
    // 将客户端sockect通道注册到指定的输入监听线程上
    if(isClusters){// 集群请求通道注册
      this.readWriteMonitors.get(Math.abs(this.connectIndex.getAndIncrement())
           % this.readWriteMonitors.size()).registeClusters(socketChannel);
    }else{// 业务请求通道注册
      this.readWriteMonitors.get(Math.abs(this.connectIndex.getAndIncrement())
           % this.readWriteMonitors.size()).registe(socketChannel);
    }
  }
 
 
  public boolean isAlive(){
    return this.connectMonitor.isAlive();
  }
   
    public void closeServer(){
    //this.serverSocket.close();//关闭链接
   
    //停止接收主线程
    this.noStopRequested = false;
    this.connectMonitor.interrupt();   
    }

  public String getStockData() {
    return stockData;
  }

  public void setStockData(String stockData) {
    this.stockData = stockData;
  }
 
  /**
   *
   * <li>方法名:clearSocket
   * <li>@param index
   * <li>返回类型:void
   * <li>说明:删除指定的连接
   * <li>创建人:CshBBrain, 技术博客:http://cshbbrain.iteye.com/
   * <li>创建日期:2012-10-22
   * <li>修改人:
   * <li>修改日期:
   */
  public void clearSocket(Object index){
    Client client = this.localClients.remove(index);// 从本地连接中清除
    if(client != null){
      return;
    }
   
    client = this.clustersClients.remove(index);// 从集群连接中清除
    if(client != null){
      return;
    }
       
    client = this.clients.remove(index);// 从客户端连接中清除
    if(client != null){
      return;
    }
  }
 
  public Client getLocalClient() {
    return localClient;
  }

  public void setLocalClient(Client localClient) {
    this.localClient = localClient;
  }
 
  public ConcurrentHashMap<Object, Client> getClustersClients() {
    return clustersClients;
  }

  public void setClustersClients(ConcurrentHashMap<Object, Client> clustersClients) {
    this.clustersClients = clustersClients;
  }
 
  public ConcurrentHashMap<Object, Client> getLocalClients() {
    return localClients;
  }

  public void setLocalClients(ConcurrentHashMap<Object, Client> localClients) {
    this.localClients = localClients;
  }
}
TOP

Related Classes of com.jason.server.MasterServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.