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里面另一个比较重要的知识点:领域服务.关于领域服务的使用,书中也介绍得比较晦涩,在此就根据博主自己的理解谈谈 ...
随机推荐
- django中ModelForm解决多表单组合显示问题
一.多表单组合显示问题 在项目中用ModelForm生成页面时 当有多表单组合显示时,会显示全部的关联表单数据. 而在实际项目中可能会出现只想让用户选择部分数据,这时候这样的显示就有问题. 二.问题解 ...
- 【guava】前提条件
guava为编写漂亮代码提供了很大的便利,今天,我想向你展示下我是怎么使用预判断来避免不必要的if/throw 申明,使用选择来提升代码逻辑性. 预判断并不是新东西,Apache Commons项目有 ...
- Python之路系列:面向对象初级:静态属性、静态方法、类方法
一.静态属性 静态属性相当于数据属性. 用@property语法糖装饰器将类的函数属性变成可以不用加括号直接的类似数据属性. 可以封装逻辑,让用户感觉是在调用一个普通的数据属性. 例子: class ...
- Jenkins持续集成企业实战系列之Jenkins配置演示-----03
注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任. 最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...
- java基础(多态)_03
一.多态 1.概念:一个对象的多种形态 2.前提: a:必须有继承 b:必须有重写(只有重写才会有意义,没重写语法没错) 3.体现形式: 父类类型 变量名 = new 子类类型(): 4.注意事项: ...
- java基础_02
一.this和super 作用: this:区分成员变量和局部变量 super:区分父类的成员变量和局部变量 用法: this.成员变量名://访问本类的成员变量 this.成员方法名()://访问本 ...
- shim和polyfill,前端术语
最近项目临近发布,JS的bug大都修改完毕,终于进入了我在这家公司实习+入职为数不多的摸鱼时刻.(想想真是有点感人啊) 因为项目要兼容IE8,所以我们的代码里常常要用到 shim 以支持ES5 的相关 ...
- 洛谷 P2147 [SDOI2008]洞穴勘测 (线段树分治)
题目链接 题解 早就想写线段树分治的题了. 对于每条边,它存在于一段时间 我们按时间来搞 我们可把一条边看做一条线段 我们可以模拟线段树操作,不断分治下去 把覆盖\(l-r\)这段时间的线段筛选出来, ...
- Magic Odd Square (思维+构造)
Find an n × n matrix with different numbers from 1 to n2, so the sum in each row, column and both ma ...
- POJ - 1061 扩展gcd
题意:求\((n-m)t+Lk=x-y\)的解\(t\) #include<iostream> #include<algorithm> #include<cstdio&g ...