多个服务,使用监听一个端口。先上一个demo

Test.thrift

  1. namespace java com.gxf.thrift
  2.  
  3. enum RequestType {
  4. SAY_HELLO, //问好
  5. QUERY_TIME, //询问时间
  6. }
  7.  
  8. struct Request {
  9. 1: required RequestType type; // 请求的类型,必选
  10. 2: required string name; // 发起请求的人的名字,必选
  11. 3: optional i32 age; // 发起请求的人的年龄,可选
  12. }
  13.  
  14. exception RequestException {
  15. 1: required i32 code;
  16. 2: optional string reason;
  17. }
  18.  
  19. // 服务名
  20. service HelloWordService {
  21. string doAction(1: Request request) throws (1:RequestException qe); // 可能抛出异常。
  22. }
  23.  
  24. //乘法
  25. service MultiSerivce{
  26. i32 multi(1:i32 n1, 2:i32 n2);
  27. }

定义了两个服务,一个是hello,一个是mult。第一输出hello信息,第二个做乘法运算。使用thrift命令,生成java代码

  1. thrift -gen java Test.thrift

Server端,两个服务实现类

  1. import org.apache.commons.lang3.StringUtils;
  2.  
  3. import java.util.Date;
  4.  
  5. public class HelloWordServiceImpl implements HelloWordService.Iface {
  6.  
  7. // 实现这个方法完成具体的逻辑。
  8. public String doAction(Request request)
  9. throws RequestException, org.apache.thrift.TException {
  10. System.out.println("Get request: " + request);
  11. if (StringUtils.isBlank(request.getName()) || request.getType() == null) {
  12. throw new com.gxf.thrift.RequestException();
  13. }
  14. String result = "Hello, " + request.getName();
  15. if (request.getType() == com.gxf.thrift.RequestType.SAY_HELLO) {
  16. result += ", Welcome!";
  17. } else {
  18. result += ", Now is " + new Date().toLocaleString();
  19. }
  20. return result;
  21.  
  22. }
  23. }
  1. import org.apache.thrift.TException;
  2.  
  3. public class MultiServiceImpl implements MultiSerivce.Iface {
  4. @Override
  5. public int multi(int n1, int n2) throws TException {
  6. return n1 + n2;
  7. }
  8. }

Service端服务启动类

  1. import org.apache.thrift.TMultiplexedProcessor;
  2. import org.apache.thrift.protocol.TBinaryProtocol;
  3. import org.apache.thrift.server.TServer;
  4. import org.apache.thrift.server.TThreadPoolServer;
  5. import org.apache.thrift.transport.TServerSocket;
  6.  
  7. import java.net.ServerSocket;
  8.  
  9. public class HelloWordServer {
  10.  
  11. public static void main(String[] args) throws Exception {
  12. ServerSocket socket = new ServerSocket(7912);
  13. TServerSocket serverTransport = new TServerSocket(socket);
  14. TBinaryProtocol.Factory proFactory = new TBinaryProtocol.Factory();
  15.  
  16. TMultiplexedProcessor multiplexedProcessor = new TMultiplexedProcessor();
  17. multiplexedProcessor.registerProcessor("helloService", new HelloWordService.Processor<>(
  18. new HelloWordServiceImpl()));
  19. multiplexedProcessor.registerProcessor("multiService", new MultiSerivce.Processor<>(
  20. new MultiServiceImpl()
  21. ));
  22.  
  23. TThreadPoolServer.Args serverArgs = new TThreadPoolServer.Args(serverTransport);
  24. serverArgs.processor(multiplexedProcessor);
  25. serverArgs.protocolFactory(proFactory);
  26. TServer server = new TThreadPoolServer(serverArgs);
  27. System.out.println("Start server on port 7912...");
  28.  
  29. server.serve();
  30. }
  31.  
  32. }

Client端测试类

  1. import org.apache.thrift.protocol.TBinaryProtocol;
  2. import org.apache.thrift.protocol.TMultiplexedProtocol;
  3. import org.apache.thrift.protocol.TProtocol;
  4. import org.apache.thrift.transport.TSocket;
  5. import org.apache.thrift.transport.TTransport;
  6.  
  7. public class HelloWordClient {
  8. public static void main(String[] args) throws Exception {
  9. TTransport transport = new TSocket("127.0.0.1", 7912);
  10.  
  11. TProtocol protocol = new TBinaryProtocol(transport);
  12. TMultiplexedProtocol tMultiplexedProtocol = new TMultiplexedProtocol(protocol, "multiService");
  13. transport.open();
  14. MultiSerivce.Client multiClient = new MultiSerivce.Client(tMultiplexedProtocol);
  15. int mulRes = multiClient.multi(1, 3);
  16. System.out.println("mulRes = " + mulRes);
  17.  
  18. TMultiplexedProtocol helloProtocol = new TMultiplexedProtocol(protocol, "helloService");
  19. HelloWordService.Client helloClient = new HelloWordService.Client(helloProtocol);
  20. Request helloRequest = new Request();
  21. helloRequest.setAge(28);
  22. helloRequest.setName("guanxiangfei");
  23. helloRequest.setType(RequestType.QUERY_TIME);
  24. String helloRes = helloClient.doAction(helloRequest);
  25. System.out.println("helloRes: " + helloRes);
  26.  
  27. transport.close(); // 请求结束,断开连接
  28. }
  29.  
  30. }

下面主要分析Server端源码

跟进TMultiplexedProcessor类

  1. public class TMultiplexedProcessor implements TProcessor {
  2.  
  3. private final Map<String,TProcessor> SERVICE_PROCESSOR_MAP
  4. = new HashMap<String,TProcessor>();
  5. private TProcessor defaultProcessor;

这里有个map存放 servicename --> processor,接着看注册源码

  1. public void registerProcessor(String serviceName, TProcessor processor) {
  2. SERVICE_PROCESSOR_MAP.put(serviceName, processor);
  3. }

直接在map中放了servicename --> processor。我们跟进serve方法

  1. public void serve() {
  2. try {
  3. serverTransport_.listen();
  4. } catch (TTransportException ttx) {
  5. LOGGER.error("Error occurred during listening.", ttx);
  6. return;
  7. }
  8.  
  9. // Run the preServe event
  10. if (eventHandler_ != null) {
  11. eventHandler_.preServe();
  12. }
  13.  
  14. setServing(true);
  15.  
  16. while (!stopped_) {
  17. TTransport client = null;
  18. TProcessor processor = null;
  19. TTransport inputTransport = null;
  20. TTransport outputTransport = null;
  21. TProtocol inputProtocol = null;
  22. TProtocol outputProtocol = null;
  23. ServerContext connectionContext = null;
  24. try {
  25. client = serverTransport_.accept();
  26. if (client != null) {
  27. processor = processorFactory_.getProcessor(client);
  28. inputTransport = inputTransportFactory_.getTransport(client);
  29. outputTransport = outputTransportFactory_.getTransport(client);
  30. inputProtocol = inputProtocolFactory_.getProtocol(inputTransport);
  31. outputProtocol = outputProtocolFactory_.getProtocol(outputTransport);
  32. if (eventHandler_ != null) {
  33. connectionContext = eventHandler_.createContext(inputProtocol, outputProtocol);
  34. }
  35. while (true) {
  36. if (eventHandler_ != null) {
  37. eventHandler_.processContext(connectionContext, inputTransport, outputTransport);
  38. }
  39. if(!processor.process(inputProtocol, outputProtocol)) {
  40. break;
  41. }
  42. }
  43. }
  44. } catch (TTransportException ttx) {
  45. // Client died, just move on
  46. } catch (TException tx) {
  47. if (!stopped_) {
  48. LOGGER.error("Thrift error occurred during processing of message.", tx);
  49. }
  50. } catch (Exception x) {
  51. if (!stopped_) {
  52. LOGGER.error("Error occurred during processing of message.", x);
  53. }
  54. }
  55.  
  56. if (eventHandler_ != null) {
  57. eventHandler_.deleteContext(connectionContext, inputProtocol, outputProtocol);
  58. }
  59.  
  60. if (inputTransport != null) {
  61. inputTransport.close();
  62. }
  63.  
  64. if (outputTransport != null) {
  65. outputTransport.close();
  66. }
  67.  
  68. }
  69. setServing(false);
  70. }

有个accept接收到客户端连接,重点看

  1. if(!processor.process(inputProtocol, outputProtocol)) {
  2. break;
  3. }

这里是处理客户断传来的请求,继续跟进

  1. @Override
  2. public boolean process(TProtocol in, TProtocol out) throws TException {
  3. TMessage msg = in.readMessageBegin();
  4. ProcessFunction fn = processMap.get(msg.name);
  5. if (fn == null) {
  6. TProtocolUtil.skip(in, TType.STRUCT);
  7. in.readMessageEnd();
  8. TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'");
  9. out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));
  10. x.write(out);
  11. out.writeMessageEnd();
  12. out.getTransport().flush();
  13. return true;
  14. }
  15. fn.process(msg.seqid, in, out, iface);
  16. return true;
  17. }

获取客户端的请求类型和方法,获取服务端注册的service。跟进fn.process()看服务端处理过程

  1. public final void process(int seqid, TProtocol iprot, TProtocol oprot, I iface) throws TException {
  2. T args = getEmptyArgsInstance();
  3. try {
  4. args.read(iprot);
  5. } catch (TProtocolException e) {
  6. iprot.readMessageEnd();
  7. TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage());
  8. oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
  9. x.write(oprot);
  10. oprot.writeMessageEnd();
  11. oprot.getTransport().flush();
  12. return;
  13. }
  14. iprot.readMessageEnd();
  15. TSerializable result = null;
  16. byte msgType = TMessageType.REPLY;
  17.  
  18. try {
  19. result = getResult(iface, args);
  20. } catch (TTransportException ex) {
  21. LOGGER.error("Transport error while processing " + getMethodName(), ex);
  22. throw ex;
  23. } catch (TApplicationException ex) {
  24. LOGGER.error("Internal application error processing " + getMethodName(), ex);
  25. result = ex;
  26. msgType = TMessageType.EXCEPTION;
  27. } catch (Exception ex) {
  28. LOGGER.error("Internal error processing " + getMethodName(), ex);
  29. if(!isOneway()) {
  30. result = new TApplicationException(TApplicationException.INTERNAL_ERROR,
  31. "Internal error processing " + getMethodName());
  32. msgType = TMessageType.EXCEPTION;
  33. }
  34. }
  35.  
  36. if(!isOneway()) {
  37. oprot.writeMessageBegin(new TMessage(getMethodName(), msgType, seqid));
  38. result.write(oprot);
  39. oprot.writeMessageEnd();
  40. oprot.getTransport().flush();
  41. }
  42. }

接着跟进getResult方法,看下服务端如何计算结果

  1. public multi_result getResult(I iface, multi_args args) throws org.apache.thrift.TException {
  2. multi_result result = new multi_result();
  3. result.success = iface.multi(args.n1, args.n2);
  4. result.setSuccessIsSet(true);
  5. return result;
  6. }

这里可以看出,调用了服务端实现类对象对应的方法。保存在multi_result对象中,序列化发给客户端。

总结:

单端口,多服务,主要就是用一个map放service-->processor映射。客户端传servicename给服务端

Thrift笔记(六)--单端口 多服务的更多相关文章

  1. python thrift 实现 单端口多服务的过程

    Thrift 是一种接口描述语言和二进制通信协议.以前也没接触过,最近有个项目需要建立自动化测试,这个项目之间的微服务都是通过 Thrift 进行通信的,然后写自动化脚本之前研究了一下. 需要定义一个 ...

  2. # go微服务框架kratos学习笔记六(kratos 服务发现 discovery)

    目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批 ...

  3. Java IO学习笔记六:NIO到多路复用

    作者:Grey 原文地址:Java IO学习笔记六:NIO到多路复用 虽然NIO性能上比BIO要好,参考:Java IO学习笔记五:BIO到NIO 但是NIO也有问题,NIO服务端的示例代码中往往会包 ...

  4. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  5. spring boot / cloud (十六) 分布式ID生成服务

    spring boot / cloud (十六) 分布式ID生成服务 在几乎所有的分布式系统或者采用了分库/分表设计的系统中,几乎都会需要生成数据的唯一标识ID的需求, 常规做法,是使用数据库中的自动 ...

  6. WebRTC网关服务器单端口方案实现

    标准WebRTC连接建立流程 这里描述的是Trickle ICE过程,并且省略了通话发起与接受的信令部分.流程如下: 1) WebRTC A通过Signal Server转发SDP OFFER到Web ...

  7. Java学习笔记之---单例模型

    Java学习笔记之---单例模型 单例模型分为:饿汉式,懒汉式 (一)要点 1.某个类只能有一个实例 2.必须自行创建实例 3.必须自行向整个系统提供这个实例 (二)实现 1.只提供私有的构造方法 2 ...

  8. Kubernetes学习笔记(四):服务

    服务介绍 服务是一种为一组相同功能的pod提供单一不变接入点的资源.当服务存在时,他的IP和端口不会改变.客户端通过IP和端口建立连接,这些连接会被路由到任何一个pod上.如此,客户端不需要知道每个单 ...

  9. C#进阶系列——DDD领域驱动设计初探(六):领域服务

    前言:之前一直在搭建项目架构的代码,有点偏离我们的主题(DDD)了,这篇我们继续来聊聊DDD里面另一个比较重要的知识点:领域服务.关于领域服务的使用,书中也介绍得比较晦涩,在此就根据博主自己的理解谈谈 ...

随机推荐

  1. 加快npm包安装的方法

    一直以来都感觉使用npm安装包的速度特别的慢,但是由于npm上面的包比较齐全,所以一直在忍受这种安装依赖包的折磨. 不过这种折磨,到今天为止应该是可以结束了,在知乎看到一个这样的说法: 用npmins ...

  2. SDUT OJ 顺序表应用2:多余元素删除之建表算法

    顺序表应用2:多余元素删除之建表算法 Time Limit: 3 ms Memory Limit: 600 KiB Submit Statistic Discuss Problem Descripti ...

  3. 首字母变大写(stringstream的应用)

    Problem Description 输入一个英文句子,将每个单词的第一个字母改成大写字母.   Input 输入数据包含多个测试实例,每个测试实例是一个长度不超过100的英文句子,占一行.   O ...

  4. Maven搭建Spring+SpringMVC+Mybatis+Shiro项目详解

    一. 环境搭建: 1. 开发工具:myeclipse 2014 / IDEA: 2. maven管理版本:apache-maven-3.0+: 3. jdk 1.7.0+4. Tomcat8.0 二: ...

  5. 解压与压缩(把dataset转为string、、 )

    /// <summary> /// 压缩 解压 /// </summary> public class ZipHelper { #region 压缩解缩 /// <sum ...

  6. [Python]打印a..z的字符

    import string print string.letters[0:26]

  7. python学习之路---day04

    一:元组 元组案例:tuple=("张三","李四","王五","小六","大七",["1 ...

  8. Codeforce-1106-D. Lunar New Year and a Wander(DFS遍历+vector存图+set)

    Lunar New Year is approaching, and Bob decides to take a wander in a nearby park. The park can be re ...

  9. Python爬虫常用之PyQuery

    PyQuery是解析页面常用的库.是python对jquery的封装.下面是一份解析基本页面的代码.后期用到复杂或者实用的方式再增加. from pyquery import PyQuery as p ...

  10. EntityFramework CodeFirst 数据库迁移

    参考: https://msdn.microsoft.com/en-us/data/jj591621 https://msdn.microsoft.com/en-us/library/dd394698 ...