Thrift笔记(六)--单端口 多服务
多个服务,使用监听一个端口。先上一个demo
Test.thrift
- namespace java com.gxf.thrift
- enum RequestType {
- SAY_HELLO, //问好
- QUERY_TIME, //询问时间
- }
- struct Request {
- 1: required RequestType type; // 请求的类型,必选
- 2: required string name; // 发起请求的人的名字,必选
- 3: optional i32 age; // 发起请求的人的年龄,可选
- }
- exception RequestException {
- 1: required i32 code;
- 2: optional string reason;
- }
- // 服务名
- service HelloWordService {
- string doAction(1: Request request) throws (1:RequestException qe); // 可能抛出异常。
- }
- //乘法
- service MultiSerivce{
- i32 multi(1:i32 n1, 2:i32 n2);
- }
定义了两个服务,一个是hello,一个是mult。第一输出hello信息,第二个做乘法运算。使用thrift命令,生成java代码
- thrift -gen java Test.thrift
Server端,两个服务实现类
- import org.apache.commons.lang3.StringUtils;
- import java.util.Date;
- public class HelloWordServiceImpl implements HelloWordService.Iface {
- // 实现这个方法完成具体的逻辑。
- public String doAction(Request request)
- throws RequestException, org.apache.thrift.TException {
- System.out.println("Get request: " + request);
- if (StringUtils.isBlank(request.getName()) || request.getType() == null) {
- throw new com.gxf.thrift.RequestException();
- }
- String result = "Hello, " + request.getName();
- if (request.getType() == com.gxf.thrift.RequestType.SAY_HELLO) {
- result += ", Welcome!";
- } else {
- result += ", Now is " + new Date().toLocaleString();
- }
- return result;
- }
- }
- import org.apache.thrift.TException;
- public class MultiServiceImpl implements MultiSerivce.Iface {
- @Override
- public int multi(int n1, int n2) throws TException {
- return n1 + n2;
- }
- }
Service端服务启动类
- import org.apache.thrift.TMultiplexedProcessor;
- import org.apache.thrift.protocol.TBinaryProtocol;
- import org.apache.thrift.server.TServer;
- import org.apache.thrift.server.TThreadPoolServer;
- import org.apache.thrift.transport.TServerSocket;
- import java.net.ServerSocket;
- public class HelloWordServer {
- public static void main(String[] args) throws Exception {
- ServerSocket socket = new ServerSocket(7912);
- TServerSocket serverTransport = new TServerSocket(socket);
- TBinaryProtocol.Factory proFactory = new TBinaryProtocol.Factory();
- TMultiplexedProcessor multiplexedProcessor = new TMultiplexedProcessor();
- multiplexedProcessor.registerProcessor("helloService", new HelloWordService.Processor<>(
- new HelloWordServiceImpl()));
- multiplexedProcessor.registerProcessor("multiService", new MultiSerivce.Processor<>(
- new MultiServiceImpl()
- ));
- TThreadPoolServer.Args serverArgs = new TThreadPoolServer.Args(serverTransport);
- serverArgs.processor(multiplexedProcessor);
- serverArgs.protocolFactory(proFactory);
- TServer server = new TThreadPoolServer(serverArgs);
- System.out.println("Start server on port 7912...");
- server.serve();
- }
- }
Client端测试类
- 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;
- public class HelloWordClient {
- public static void main(String[] args) throws Exception {
- TTransport transport = new TSocket("127.0.0.1", 7912);
- TProtocol protocol = new TBinaryProtocol(transport);
- TMultiplexedProtocol tMultiplexedProtocol = new TMultiplexedProtocol(protocol, "multiService");
- transport.open();
- MultiSerivce.Client multiClient = new MultiSerivce.Client(tMultiplexedProtocol);
- int mulRes = multiClient.multi(1, 3);
- System.out.println("mulRes = " + mulRes);
- TMultiplexedProtocol helloProtocol = new TMultiplexedProtocol(protocol, "helloService");
- HelloWordService.Client helloClient = new HelloWordService.Client(helloProtocol);
- Request helloRequest = new Request();
- helloRequest.setAge(28);
- helloRequest.setName("guanxiangfei");
- helloRequest.setType(RequestType.QUERY_TIME);
- String helloRes = helloClient.doAction(helloRequest);
- System.out.println("helloRes: " + helloRes);
- transport.close(); // 请求结束,断开连接
- }
- }
下面主要分析Server端源码
跟进TMultiplexedProcessor类
- public class TMultiplexedProcessor implements TProcessor {
- private final Map<String,TProcessor> SERVICE_PROCESSOR_MAP
- = new HashMap<String,TProcessor>();
- private TProcessor defaultProcessor;
这里有个map存放 servicename --> processor,接着看注册源码
- public void registerProcessor(String serviceName, TProcessor processor) {
- SERVICE_PROCESSOR_MAP.put(serviceName, processor);
- }
直接在map中放了servicename --> processor。我们跟进serve方法
- public void serve() {
- try {
- serverTransport_.listen();
- } catch (TTransportException ttx) {
- LOGGER.error("Error occurred during listening.", ttx);
- return;
- }
- // Run the preServe event
- if (eventHandler_ != null) {
- eventHandler_.preServe();
- }
- setServing(true);
- 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;
- }
- }
- }
- } catch (TTransportException ttx) {
- // Client died, just move on
- } catch (TException tx) {
- if (!stopped_) {
- LOGGER.error("Thrift error occurred during processing of message.", tx);
- }
- } catch (Exception x) {
- if (!stopped_) {
- LOGGER.error("Error occurred during processing of message.", x);
- }
- }
- if (eventHandler_ != null) {
- eventHandler_.deleteContext(connectionContext, inputProtocol, outputProtocol);
- }
- if (inputTransport != null) {
- inputTransport.close();
- }
- if (outputTransport != null) {
- outputTransport.close();
- }
- }
- setServing(false);
- }
有个accept接收到客户端连接,重点看
- if(!processor.process(inputProtocol, outputProtocol)) {
- break;
- }
这里是处理客户断传来的请求,继续跟进
- @Override
- public boolean process(TProtocol in, TProtocol out) throws TException {
- TMessage msg = in.readMessageBegin();
- ProcessFunction fn = processMap.get(msg.name);
- if (fn == null) {
- TProtocolUtil.skip(in, TType.STRUCT);
- in.readMessageEnd();
- TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'");
- out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));
- x.write(out);
- out.writeMessageEnd();
- out.getTransport().flush();
- return true;
- }
- fn.process(msg.seqid, in, out, iface);
- return true;
- }
获取客户端的请求类型和方法,获取服务端注册的service。跟进fn.process()看服务端处理过程
- public final void process(int seqid, TProtocol iprot, TProtocol oprot, I iface) throws TException {
- T args = getEmptyArgsInstance();
- try {
- args.read(iprot);
- } catch (TProtocolException e) {
- iprot.readMessageEnd();
- TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage());
- oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
- x.write(oprot);
- oprot.writeMessageEnd();
- oprot.getTransport().flush();
- return;
- }
- iprot.readMessageEnd();
- TSerializable result = null;
- byte msgType = TMessageType.REPLY;
- try {
- result = getResult(iface, args);
- } catch (TTransportException ex) {
- LOGGER.error("Transport error while processing " + getMethodName(), ex);
- throw ex;
- } catch (TApplicationException ex) {
- LOGGER.error("Internal application error processing " + getMethodName(), ex);
- result = ex;
- msgType = TMessageType.EXCEPTION;
- } catch (Exception ex) {
- LOGGER.error("Internal error processing " + getMethodName(), ex);
- if(!isOneway()) {
- result = new TApplicationException(TApplicationException.INTERNAL_ERROR,
- "Internal error processing " + getMethodName());
- msgType = TMessageType.EXCEPTION;
- }
- }
- if(!isOneway()) {
- oprot.writeMessageBegin(new TMessage(getMethodName(), msgType, seqid));
- result.write(oprot);
- oprot.writeMessageEnd();
- oprot.getTransport().flush();
- }
- }
接着跟进getResult方法,看下服务端如何计算结果
- public multi_result getResult(I iface, multi_args args) throws org.apache.thrift.TException {
- multi_result result = new multi_result();
- result.success = iface.multi(args.n1, args.n2);
- result.setSuccessIsSet(true);
- return result;
- }
这里可以看出,调用了服务端实现类对象对应的方法。保存在multi_result对象中,序列化发给客户端。
总结:
单端口,多服务,主要就是用一个map放service-->processor映射。客户端传servicename给服务端
Thrift笔记(六)--单端口 多服务的更多相关文章
- python thrift 实现 单端口多服务的过程
Thrift 是一种接口描述语言和二进制通信协议.以前也没接触过,最近有个项目需要建立自动化测试,这个项目之间的微服务都是通过 Thrift 进行通信的,然后写自动化脚本之前研究了一下. 需要定义一个 ...
- # go微服务框架kratos学习笔记六(kratos 服务发现 discovery)
目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批 ...
- Java IO学习笔记六:NIO到多路复用
作者:Grey 原文地址:Java IO学习笔记六:NIO到多路复用 虽然NIO性能上比BIO要好,参考:Java IO学习笔记五:BIO到NIO 但是NIO也有问题,NIO服务端的示例代码中往往会包 ...
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- spring boot / cloud (十六) 分布式ID生成服务
spring boot / cloud (十六) 分布式ID生成服务 在几乎所有的分布式系统或者采用了分库/分表设计的系统中,几乎都会需要生成数据的唯一标识ID的需求, 常规做法,是使用数据库中的自动 ...
- WebRTC网关服务器单端口方案实现
标准WebRTC连接建立流程 这里描述的是Trickle ICE过程,并且省略了通话发起与接受的信令部分.流程如下: 1) WebRTC A通过Signal Server转发SDP OFFER到Web ...
- Java学习笔记之---单例模型
Java学习笔记之---单例模型 单例模型分为:饿汉式,懒汉式 (一)要点 1.某个类只能有一个实例 2.必须自行创建实例 3.必须自行向整个系统提供这个实例 (二)实现 1.只提供私有的构造方法 2 ...
- Kubernetes学习笔记(四):服务
服务介绍 服务是一种为一组相同功能的pod提供单一不变接入点的资源.当服务存在时,他的IP和端口不会改变.客户端通过IP和端口建立连接,这些连接会被路由到任何一个pod上.如此,客户端不需要知道每个单 ...
- C#进阶系列——DDD领域驱动设计初探(六):领域服务
前言:之前一直在搭建项目架构的代码,有点偏离我们的主题(DDD)了,这篇我们继续来聊聊DDD里面另一个比较重要的知识点:领域服务.关于领域服务的使用,书中也介绍得比较晦涩,在此就根据博主自己的理解谈谈 ...
随机推荐
- 加快npm包安装的方法
一直以来都感觉使用npm安装包的速度特别的慢,但是由于npm上面的包比较齐全,所以一直在忍受这种安装依赖包的折磨. 不过这种折磨,到今天为止应该是可以结束了,在知乎看到一个这样的说法: 用npmins ...
- SDUT OJ 顺序表应用2:多余元素删除之建表算法
顺序表应用2:多余元素删除之建表算法 Time Limit: 3 ms Memory Limit: 600 KiB Submit Statistic Discuss Problem Descripti ...
- 首字母变大写(stringstream的应用)
Problem Description 输入一个英文句子,将每个单词的第一个字母改成大写字母. Input 输入数据包含多个测试实例,每个测试实例是一个长度不超过100的英文句子,占一行. O ...
- Maven搭建Spring+SpringMVC+Mybatis+Shiro项目详解
一. 环境搭建: 1. 开发工具:myeclipse 2014 / IDEA: 2. maven管理版本:apache-maven-3.0+: 3. jdk 1.7.0+4. Tomcat8.0 二: ...
- 解压与压缩(把dataset转为string、、 )
/// <summary> /// 压缩 解压 /// </summary> public class ZipHelper { #region 压缩解缩 /// <sum ...
- [Python]打印a..z的字符
import string print string.letters[0:26]
- python学习之路---day04
一:元组 元组案例:tuple=("张三","李四","王五","小六","大七",["1 ...
- 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 ...
- Python爬虫常用之PyQuery
PyQuery是解析页面常用的库.是python对jquery的封装.下面是一份解析基本页面的代码.后期用到复杂或者实用的方式再增加. from pyquery import PyQuery as p ...
- EntityFramework CodeFirst 数据库迁移
参考: https://msdn.microsoft.com/en-us/data/jj591621 https://msdn.microsoft.com/en-us/library/dd394698 ...