Thrift server比较和使用

Thrift提供了多种服务器实现。

WechatIMG20.jpeg

它们各有特点,适应不同的需求环境。下面我将结合网络资源和自己的理解来梳理一下Thrift各种java server的特点和使用姿势。

  • TSimpleServer

while (!stopped_) {
  TTransport client = null;
  TProcessor processor = null;
  TTransport inputTransport = null;
  TTransport outputTransport = null;
  TProtocol inputProtocol = null;
  TProtocol outputProtocol = null;
  ServerContext connectionContext = null;
  try {
    client = serverTransport_.accept();
    if (client != null) {
      processor = processorFactory_.getProcessor(client);
      inputTransport = inputTransportFactory_.getTransport(client);
      outputTransport = outputTransportFactory_.getTransport(client);
      inputProtocol = inputProtocolFactory_.getProtocol(inputTransport);
      outputProtocol = outputProtocolFactory_.getProtocol(outputTransport);
      if (eventHandler_ != null) {
        connectionContext = eventHandler_.createContext(inputProtocol, outputProtocol);
      }
      while (true) {
        if (eventHandler_ != null) {
          eventHandler_.processContext(connectionContext, inputTransport, outputTransport);
        }
        if(!processor.process(inputProtocol, outputProtocol)) {
          break;
        }
      }
    }
  }
}

TSimplerServer在while循环中每次接受一个连接,处理连接请求,直到客户端关闭了连接,它才会去接受一个新的连接。由于它只在一个单独的线程中以阻塞I/O的方式完成这些工作,所以它只能服务一个客户端连接,其他所有客户端在被服务器端接受之前都只能等待。其使用方法如下:

public static void sample() throws Exception {
    ServerSocket socket = new ServerSocket(8912);
    TServerSocket serverTransport = new TServerSocket(socket); // HelloServiceImpl 为自己实现的Thrift服务接口的具体实现  
    TServer server = new TSimpleServer(new TServer.Args(serverTransport).processor(processor));
    System.out.println("Server start...");
    server.serve();
}
  • TNonblockingServer

public void run() {
  try {
    if (eventHandler_ != null) {
      eventHandler_.preServe();
    }

    while (!stopped_) {
      select();
      processInterestChanges();
    }
    for (SelectionKey selectionKey : selector.keys()) {
      cleanupSelectionKey(selectionKey);
    }
  } catch (Throwable t) {
    LOGGER.error("run() exiting due to uncaught error", t);
  } finally {
    try {
      selector.close();
    } catch (IOException e) {
      LOGGER.error("Got an IOException while closing selector!", e);
    }
    stopped_ = true;
  }
}
private void select() {
  try {
    // wait for io events.
    selector.select();

    // process the io events we received
    Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
    while (!stopped_ && selectedKeys.hasNext()) {
      SelectionKey key = selectedKeys.next();
      selectedKeys.remove();

      // skip if not valid
      if (!key.isValid()) {
        cleanupSelectionKey(key);
        continue;
      }

      // if the key is marked Accept, then it has to be the server
      // transport.
      if (key.isAcceptable()) {
        handleAccept();
      } else if (key.isReadable()) {
        // deal with reads
        handleRead(key);
      } else if (key.isWritable()) {
        // deal with writes
        handleWrite(key);
      } else {
        LOGGER.warn("Unexpected state in select! " + key.interestOps());
      }
    }
  } catch (IOException e) {
    LOGGER.warn("Got an IOException while selecting!", e);
  }
}

TNonblockingServer 使用非阻塞的 I/O 解决了TSimpleServer一个客户端阻塞其他所有客户端的问题。它使用了java.nio.channels.Selector,通过调用select(),它使得你阻塞在多个连接上,而不是阻塞在单一的连接上。当一或多个连接准备好被接受/读/写时,select()调用便会返回。TNonblockingServer处理这些连接的时候,要么接受它,要么从它那读数据,要么把数据写到它那里,然后再次调用select()来等待下一个可用的连接。通用这种方式,server可同时服务多个客户端,而不会出现一个客户端把其他客户端全部“饿死”的情况。
使用方法:

public static void nonBlock() throws TTransportException {
    TNonblockingServerSocket serverSocket = new TNonblockingServerSocket(8912);
    Hello.Processor processor = new Hello.Processor(new HelloServiceImpl());
    TNonblockingServer.Args args = new TNonblockingServer.Args(serverSocket);
    args.transportFactory(new TFramedTransport.Factory());
    args.protocolFactory(new TCompactProtocol.Factory());
    args.processor(processor);
    TNonblockingServer server = new TNonblockingServer(args);
    server.serve();
}
  • ThreadedSelectorServer

ThreadedSelectorServer允许你用多个线程来处理网络 I/O。它维护了两个线程池,一个用来处理网络 I/O,另一个用来进行请求的处理。使用方法:

public static void threadSelector() throws TTransportException, IOException {
    TNonblockingServerSocket serverSocket = new TNonblockingServerSocket(8912);
    Hello.Processor processor = new Hello.Processor(new HelloServiceImpl());
    TThreadedSelectorServer.Args args = new TThreadedSelectorServer.Args(serverSocket);
    args.transportFactory(new TFramedTransport.Factory());
    args.protocolFactory(new TBinaryProtocol.Factory());
    args.selectorThreads(10);
    args.acceptQueueSizePerThread(10);
    args.processor(processor);
    TThreadedSelectorServer server = new TThreadedSelectorServer(args);
    server.serve();
}
  • TThreadPoolServer

TThreadPoolServer有一个专用的线程用来接受连接旦接受了一个连接,它就会被放入ThreadPoolExecutor中的一个 worker 线程里处理。worker 线程被绑定到特定的客户端连接上,直到它关闭。一旦连接关闭,该worker线程就又回到了线程池中。你可以配置线程池的最小、最大线程数,默认值分别是5(最?。┖虸nteger.MAX_VALUE(最大)。使用方法:

public static void threadPool() throws Exception {
    TNonblockingServerSocket serverSocket = new TNonblockingServerSocket(8912);
    Hello.Processor processor = new Hello.Processor(new HelloServiceImpl());
    TThreadPoolServer.Args args = new TThreadPoolServer.Args(serverSocket);
    args.transportFactory(new TFramedTransport.Factory());
    args.protocolFactory(new TBinaryProtocol.Factory());
    args.processor(processor);
    args.maxWorkerThreads(10);
    TThreadPoolServer server = new TThreadPoolServer(args);
    server.serve();
}
最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,172评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,346评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,788评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,299评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,409评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,467评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,476评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,262评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,699评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,994评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,167评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,499评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,149评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,387评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,028评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,055评论 2 352

推荐阅读更多精彩内容