<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Apache thrift 之使用示例

          共 20848字,需瀏覽 42分鐘

           ·

          2021-05-23 20:59

          最近看到一些招聘說明有關(guān)于thrift的要求:

          作為一個(gè)面向簡歷編程的程序員,多年來使用的都是springmvc下的http調(diào)用,不免對這個(gè)thrift有了一絲好奇,于是thrift的學(xué)習(xí)就提上了日程。

          Thrift 基本概念

          百度百科的定義如下:

          Thrift是一種接口描述語言和二進(jìn)制通訊協(xié)議,它被用來定義和創(chuàng)建跨語言的服務(wù)。它被當(dāng)作一個(gè)遠(yuǎn)程過程調(diào)用(RPC)框架來使用,是由Facebook為“大規(guī)??缯Z言服務(wù)開發(fā)”而開發(fā)的。

          關(guān)于那些大而泛的概念,本文就不多介紹了,直接進(jìn)入thfrit的學(xué)習(xí)吧。

          Thrift的數(shù)據(jù)類型

          Thrift 腳本可定義的數(shù)據(jù)類型包括以下幾種類型:

          • 基本類型:

            • bool: 布爾值
            • byte: 8位有符號整數(shù)
            • i16: 16位有符號整數(shù)
            • i32: 32位有符號整數(shù)
            • i64: 64位有符號整數(shù)
            • double: 64位浮點(diǎn)數(shù)
            • string: UTF-8編碼的字符串
            • binary: 二進(jìn)制串
          • 結(jié)構(gòu)體類型:

            • struct: 定義的結(jié)構(gòu)體對象
          • 容器類型:

            • list: 有序元素列表
            • set: 無序無重復(fù)元素集合
            • map: 有序的key/value集合
          • 異常類型:

            • exception: 異常類型
          • 服務(wù)類型:

            • service: 具體對應(yīng)服務(wù)的類

          Thrift的協(xié)議

          Thrift可以讓用戶選擇客戶端與服務(wù)端之間傳輸通信協(xié)議的類別,在傳輸協(xié)議上總體劃分為**文本(text)「和」二進(jìn)制(binary)**傳輸協(xié)議。為節(jié)約帶寬,提高傳輸效率,一般情況下使用二進(jìn)制類型的傳輸協(xié)議為多數(shù),有時(shí)還會使用基于文本類型的協(xié)議,這需要根據(jù)項(xiàng)目/產(chǎn)品中的實(shí)際需求。常用協(xié)議有以下幾種:

          • TBinaryProtocol:二進(jìn)制編碼格式進(jìn)行數(shù)據(jù)傳輸
          • TCompactProtocol:高效率的、密集的二進(jìn)制編碼格式進(jìn)行數(shù)據(jù)傳輸
          • TJSONProtocol: 使用JSON文本的數(shù)據(jù)編碼協(xié)議進(jìn)行數(shù)據(jù)傳輸
          • TSimpleJSONProtocol:只提供JSON只寫的協(xié)議,適用于通過腳本語言解析

          Thrift的傳輸層

          常用的傳輸層有以下幾種:

          • TSocket:使用阻塞式I/O進(jìn)行傳輸,是最常見的模式
          • TNonblockingTransport:使用非阻塞方式,用于構(gòu)建異步客戶端
          • TFramedTransport:使用非阻塞方式,按塊的大小進(jìn)行傳輸,類似于Java中的NIO

          Thrift的服務(wù)端類型

          • TSimpleServer:單線程服務(wù)器端,使用標(biāo)準(zhǔn)的阻塞式I/O
          • TThreadPoolServer:多線程服務(wù)器端,使用標(biāo)準(zhǔn)的阻塞式I/O
          • TNonblockingServer:單線程服務(wù)器端,使用非阻塞式I/O
          • THsHaServer:半同步半異步服務(wù)器端,基于非阻塞式IO讀寫和多線程工作任務(wù)處理
          • TThreadedSelectorServer:多線程選擇器服務(wù)器端,對THsHaServer在異步IO模型上進(jìn)行增強(qiáng)

          簡單了解完上面的概念后,接下來我們將通過一個(gè)實(shí)例來演示thrift的使用。

          安裝

          使用thrift前,需要安裝thrift命令行工具,該工具用來將編寫的thfirt文件編譯成指定的源碼文件。

          在 Mac 上用如下命令安裝:

          $ brew install thrift

          安裝成功后,查看版本:

          $ thrift -v
          Thrift version 0.14.1

          其他操作系統(tǒng)的安裝過程可自行百度。

          編寫 thrift 文件

          這里我們編寫兩個(gè)服務(wù)。

          HelloService.thrift

          namespace java com.attempt.thrift02.gen.service

          service HelloService {
          string hello(1: string text);
          }

          這里定義了一個(gè)HelloService,里面僅有一個(gè)hello(String)方法

          QueryResult.thrift

          namespace java com.attempt.thrift02.gen.vo

          struct QueryResult {
          1: required i32 code; // 請求的code 必選
          2: optional string msg; // 請求返回信息,可選
          }

          這里定義了一個(gè)對象實(shí)體,里面有兩個(gè)屬性:codemsg,用來接收返回參數(shù)。

          QueryService.thrift

          namespace java com.attempt.thrift02.gen.service

          // 引入另一文件
          include "QueryResult.thrift"

          service QueryService {
          // QueryResult在另一個(gè)文件中,使用方式為 文件名.對象名
          QueryResult.QueryResult query(1: i32 code);
          }

          這是另一個(gè)ServiceQueryService,該service中只有一個(gè)方法:query(...),該方法返回對象為QueryResult,由于該對象在QueryResult.thrift文件中,因此需要使用include命令引入,并且在引用時(shí),需要使用文件名.對象名的方式。

          生成

          在命令行中執(zhí)行如下命令(指定文件的源碼文件為java):

          $ thrift -r --gen java QueryService.thrift
          $ thrift -r --gen java HelloService.thrift

          QueryService.thrift中引用了QueryResult.thrift文件,因此只需生成QueryService.thriftQueryResult.thrift就可自動生成。

          生成的文件如下:

          實(shí)現(xiàn)

          我們將上一步生成的java代碼復(fù)制到src/main/java下,目錄結(jié)構(gòu)如下:

          引入 thrift jar 包

          除了復(fù)制生成的文件外,還需要在項(xiàng)目中引入thrift 的 jar 包,jar包的GAV如下:

          <dependency>
              <groupId>org.apache.thrift</groupId>
              <artifactId>libthrift</artifactId>
              <version>0.14.1</version>
          </dependency>

          HelloService的實(shí)現(xiàn):HelloServiceImpl

          package com.attempt.thrift02.serviceImpl;

          import com.attempt.thrift02.gen.service.HelloService;
          import org.apache.thrift.TException;

          /**
           * {這里添加描述}
           *
           * @author chengyan
           * @date 2021-05-06 11:50 上午
           */

          public class HelloServiceImpl implements HelloService.Iface {

              @Override
              public String hello(String text) throws TException {
                  return "hello, " + text + " !";
              }
          }

          HelloServiceImpl是我們自己編寫的類,它實(shí)現(xiàn)了HelloService.Iface,在對應(yīng)的方法中編寫我們自己的業(yè)務(wù)邏輯,而HelloService.Iface是由thrift生成的類。

          QueryService的實(shí)現(xiàn):QueryServiceImpl

          package com.attempt.thrift02.serviceImpl;

          import com.attempt.thrift02.gen.service.QueryService;
          import com.attempt.thrift02.gen.vo.QueryResult;
          import org.apache.thrift.TException;

          /**
           * {這里添加描述}
           *
           * @author chengyan
           * @date 2021-05-06 11:51 上午
           */

          public class QueryServiceImpl implements QueryService.Iface {

              @Override
              public QueryResult query(int code) throws TException {
                  QueryResult result = new QueryResult();
                  if (code == 1) {
                      result.code = 1;
                      result.msg = "success";
                  } else {
                      result.code = 0;
                      result.msg = "fail";
                  }
                  return result;
              }
          }

          同樣地,QueryServiceImpl是我們自己編寫的類,它實(shí)現(xiàn)了QueryService.Iface,在對應(yīng)的方法中編寫我們自己的業(yè)務(wù)邏輯,而QueryService.Iface是由thrift生成的類。

          客戶端與服務(wù)端

          接下來就是實(shí)現(xiàn)各服務(wù)對應(yīng)的客戶端了。

          HelloService

          server:

          package com.attempt.thrift02.server;

          import com.attempt.thrift02.gen.service.HelloService;
          import com.attempt.thrift02.serviceImpl.HelloServiceImpl;
          import org.apache.thrift.server.TServer;
          import org.apache.thrift.server.TSimpleServer;
          import org.apache.thrift.transport.TServerSocket;
          import org.apache.thrift.transport.TServerTransport;

          /**
           * {這里添加描述}
           *
           * @author chengyan
           * @date 2021-05-06 11:53 上午
           */

          public class HelloServer {

              private static final int SERVER_PORT = 8090;

              public static void main(String[] args) {
                  try {
                      HelloService.Processor processor = new HelloService.Processor<>(
                          new HelloServiceImpl());
                      TServerTransport transport = new TServerSocket(SERVER_PORT);
                      TServer server = new TSimpleServer(new TServer.Args(transport)
                          .processor(processor));
                      System.out.println("Starting the simple server...");
                      server.serve();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }

          client:

          package com.attempt.thrift02.client;

          import com.attempt.thrift02.gen.service.HelloService;
          import org.apache.thrift.protocol.TBinaryProtocol;
          import org.apache.thrift.protocol.TProtocol;
          import org.apache.thrift.transport.TSocket;
          import org.apache.thrift.transport.TTransport;

          /**
           * {這里添加描述}
           *
           * @author chengyan
           * @date 2021-05-06 11:52 上午
           */

          public class HelloClient {
              private static final int SERVER_PORT = 8090;

              public static void main(String[] args) {
                  TTransport transport = null;
                  try {
                      transport = new TSocket("localhost", SERVER_PORT);
                      transport.open();

                      TProtocol protocol = new TBinaryProtocol(transport);
                      HelloService.Client client = new HelloService.Client(protocol);

                      String result = client.hello("thrift world");
                      System.out.println("result=" + result);
                  } catch (Exception e) {
                      e.printStackTrace();
                  } finally {
                      if(null != transport) {
                          transport.close();
                      }
                  }
              }

          }

          啟動 server:

          運(yùn)行 client:

          QueryService

          server:

          package com.attempt.thrift02.server;

          import com.attempt.thrift02.gen.service.QueryService;
          import com.attempt.thrift02.serviceImpl.QueryServiceImpl;
          import org.apache.thrift.server.TServer;
          import org.apache.thrift.server.TSimpleServer;
          import org.apache.thrift.transport.TServerSocket;
          import org.apache.thrift.transport.TServerTransport;

          /**
           * {這里添加描述}
           *
           * @author chengyan
           * @date 2021-05-06 11:53 上午
           */

          public class QueryServer {
              private static final int SERVER_PORT = 8091;

              public static void main(String[] args) {
                  try {
                      QueryService.Processor processor = new QueryService.Processor<>(
                          new QueryServiceImpl());
                      TServerTransport transport = new TServerSocket(SERVER_PORT);
                      TServer server = new TSimpleServer(new TServer.Args(transport)
                          .processor(processor));
                      System.out.println("Starting the simple server...");
                      server.serve();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }

          client:

          package com.attempt.thrift02.client;

          import com.attempt.thrift02.gen.service.QueryService;
          import com.attempt.thrift02.gen.vo.QueryResult;
          import org.apache.thrift.protocol.TBinaryProtocol;
          import org.apache.thrift.protocol.TProtocol;
          import org.apache.thrift.transport.TSocket;
          import org.apache.thrift.transport.TTransport;

          /**
           * {這里添加描述}
           *
           * @author chengyan
           * @date 2021-05-06 11:53 上午
           */

          public class QueryClient {
              private static final int SERVER_PORT = 8091;

              public static void main(String[] args) {
                  TTransport transport = null;
                  try {
                      transport = new TSocket("localhost", SERVER_PORT);
                      transport.open();

                      TProtocol protocol = new TBinaryProtocol(transport);
                      QueryService.Client client = new QueryService.Client(protocol);

                      QueryResult result = client.query(1);
                      System.out.println("query result=" + result);
                  } catch (Exception e) {
                      e.printStackTrace();
                  } finally {
                      if(null != transport) {
                          transport.close();
                      }
                  }
              }
          }

          啟動 server:

          運(yùn)行 client:

          復(fù)合服務(wù)

          以上同一個(gè)項(xiàng)目中有兩個(gè)thrift服務(wù),我們是開兩個(gè)端口對外提供服務(wù),在實(shí)際生產(chǎn)環(huán)境,thrift服務(wù)可能會更多,這種時(shí)候我們能不能只開一個(gè)jvm進(jìn)程來處理呢?thrift 提供了TMultiplexedProcessor來解決這個(gè)問題,使用方法如下:

          server:

          package com.attempt.thrift02.server;

          import com.attempt.thrift02.gen.service.HelloService;
          import com.attempt.thrift02.gen.service.QueryService;
          import com.attempt.thrift02.serviceImpl.HelloServiceImpl;
          import com.attempt.thrift02.serviceImpl.QueryServiceImpl;
          import org.apache.thrift.TMultiplexedProcessor;
          import org.apache.thrift.TProcessor;
          import org.apache.thrift.server.THsHaServer;
          import org.apache.thrift.server.TNonblockingServer;
          import org.apache.thrift.server.TServer;
          import org.apache.thrift.server.TSimpleServer;
          import org.apache.thrift.server.TThreadPoolServer;
          import org.apache.thrift.transport.TNonblockingServerSocket;
          import org.apache.thrift.transport.TServerSocket;
          import org.apache.thrift.transport.TServerTransport;
          import org.apache.thrift.transport.TTransportException;

          /**
           * {這里添加描述}
           *
           * @author chengyan
           * @date 2021-05-06 12:45 下午
           */

          public class MultipleServer {

              private static final int SERVER_PORT = 8093;

              public static void main(String[] args) {
                  try {
                      TMultiplexedProcessor processor = new TMultiplexedProcessor();
                      // 注冊 helloService
                      processor.registerProcessor("helloService",
                              new HelloService.Processor<>(new HelloServiceImpl()));
                      // 注冊 queryService
                      processor.registerProcessor("queryService",
                              new QueryService.Processor<>(new QueryServiceImpl()));
                      TServer server = getSimpleServer(SERVER_PORT, processor);
                      System.out.println("Starting the simple server...");
                      server.serve();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }

              /** 簡單的單線程服務(wù)模型,一般用于測試 */
              public static TServer getSimpleServer(int port, TProcessor processor) 
                      throws TTransportException 
          {
                  TServerTransport transport = new TServerSocket(port);
                  TServer server = new TSimpleServer(new TServer.Args(transport)
                      .processor(processor));
                  return server;
              }

          }

          client:

          服務(wù)端使用了TMultiplexedProcessor,客戶端也需要使用:

          package com.attempt.thrift02.client;

          import com.attempt.thrift02.gen.service.HelloService;
          import com.attempt.thrift02.gen.service.QueryService;
          import org.apache.thrift.TException;
          import org.apache.thrift.protocol.TBinaryProtocol;
          import org.apache.thrift.protocol.TMultiplexedProtocol;
          import org.apache.thrift.protocol.TProtocol;
          import org.apache.thrift.transport.TSocket;
          import org.apache.thrift.transport.TTransport;

          /**
           * {這里添加描述}
           *
           * @author chengyan
           * @date 2021-05-06 12:46 下午
           */

          public class MultipleClient {
              private static final int SERVER_PORT = 8093;
              public static void main(String[] args) {
                  TTransport transport = null;
                  try {
                      transport = new TSocket("localhost", SERVER_PORT);
                      transport.open();
                      TProtocol protocol = new TBinaryProtocol(transport);

                      // helloService
                      TMultiplexedProtocol helloService = new TMultiplexedProtocol(
                              protocol, "helloService");
                      HelloService.Client client = new HelloService.Client(helloService);
                      System.out.println(client.hello("thrift world"));

                      // queryService
                      TMultiplexedProtocol helloProtocol = new TMultiplexedProtocol(
                              protocol, "queryService");
                      QueryService.Client queryClient = new QueryService.Client(helloProtocol);
                      System.out.println(queryClient.query(1));

                  } catch (TException e) {
                      e.printStackTrace();
                  } finally {
                      transport.close();
                  }
              }
          }

          啟動 server:

          啟動 client:

          關(guān)于 thrift 的使用介紹就到這里了,下篇我們來分析源碼的實(shí)現(xiàn)。

          參考:

          • Apache Thrift系列詳解(一) - 概述與入門:https://juejin.cn/post/6844903622380093447

          限于作者個(gè)人水平,文中難免有錯(cuò)誤之處,歡迎指正!原創(chuàng)不易,商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

          本文首發(fā)于微信公眾號 「Java技術(shù)探秘」,如果您喜歡本文,歡迎關(guān)注該公眾號,讓我們一起在技術(shù)的世界里探秘吧!


          瀏覽 55
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉不卡视频 | 喷水人妻在线播放视频 | 一道本一二三区 | 特色黄片网站 | 国产成人久久精品激情 |