RPC - Thrift
背景:公司提供给第三方的数据传输接口一直是以Hessian的协议进行发布的,但是由于交通车辆通行数据量较大,导致第三方反应出现数据延迟的情况或者连接超时的情况,所以需要更换Hessian,换成性能更高的Thrift协议
区别:
Hessian | Thrift | |
优点 |
1、简单易用,面向接口,通过接口暴露服务,jar包只有200、300k,不需要配置防火墙 |
1、支持非常多的语言绑定 2、thrift文件生成目标代码,简单易用 3、消息定义文件支持注释 4、数据结构与传输表现的分离,支持多种消息格式 5、包含完整的客户端/服务端堆栈,可快速实现RPC 6、支持同步和异步通信 7、在大数据量下,性能较强 |
缺点 | 大数据量情况下,性能不是很高,会出现一些意料之外的错误 | 编写代码步骤较繁琐,需要使用thrift.exe工具来进行代码编译,与idea结合的不是很好 |
Thrift Demo
1、首先需要编写一个Thrift文件 StudyService.thrift
//定义Thrift服务 service StudyService { string thriftFun(1:required string name) ; }
2、用thrift.exe对StudyService.thrift进行java代码生成(https://thrift.apache.org/ 下载thrift编译工具),执行命令(windows)
thrift-0.13.0.exe -gen java StudyThrift.thrift
3、把生成的代码拷贝到项目当中:
4、开始编写实现类:
@Slf4j @Service public class StudyServiceImpl implements StudyService.Iface { @Override public String thriftFun(String name) throws TException { log.info("getStudentByName"); return name; } }
5、编写Thrift的conf文件,即启动类
@Component public class ThriftServerConf { /** * 监听的端口 */ @Value("${server.thrift.port}") private Integer port; /** * 线程池最小线程数 */ @Value("${server.thrift.min-thread-pool}") private Integer minThreadPool; /** * 线程池最大线程数 */ @Value("${server.thrift.max-thread-pool}") private Integer maxThreadPool; /** * 业务服务对象 */ @Autowired StudyServiceImpl myServerService; public void start() { try { //thrift支持的scoker有很多种 //非阻塞的socker TNonblockingServerSocket socket = new TNonblockingServerSocket(port); //THsHaServer 一个高可用的server //minWorkerThreads 最小的工作线程2 //maxWorkerThreads 最大的工作线程4 //如果这里Args不使用executorService指定线程池的话,创建THsHaServer会创建一个默认的LinkedBlockingQueue THsHaServer.Args arg = new THsHaServer.Args(socket).minWorkerThreads(minThreadPool).maxWorkerThreads(maxThreadPool); //可以自定义指定线程池 //ExecutorService pool = Executors.newFixedThreadPool(minThreadPool); //arg.executorService(pool); //Processor处理区 用于处理业务逻辑 //泛型就是实现的业务 StudyService.Processor<StudyServiceImpl> processor = new StudyService.Processor<>(myServerService); //---------------thrift传输协议------------------------------ //1. TBinaryProtocol 二进制传输协议 //2. TCompactProtocol 压缩协议 他是基于TBinaryProtocol二进制协议在进一步的压缩,使得体积更小 //3. TJSONProtocol Json格式传输协议 //4. TSimpleJSONProtocol 简单JSON只写协议,生成的文件很容易通过脚本语言解析,实际开发中很少使用 //5. TDebugProtocol 简单易懂的可读协议,调试的时候用于方便追踪传输过程中的数据 //----------------------------------------------------------- //设置工厂 //协议工厂 TCompactProtocol压缩工厂 二进制压缩协议 arg.protocolFactory(new TCompactProtocol.Factory()); //---------------thrift传输格式------------------------------ //---------------thrift数据传输方式------------------------------ //1. TSocker 阻塞式Scoker 相当于Java中的ServerSocket //2. TFrameTransport 以frame为单位进行数据传输,非阻塞式服务中使用 //3. TFileTransport 以文件的形式进行传输 //4. TMemoryTransport 将内存用于IO,Java实现的时候内部实际上是使用了简单的ByteArrayOutputStream //5. TZlibTransport 使用zlib进行压缩,与其他传世方式联合使用;java当前无实现所以无法使用 //传输工厂 更加底层的概念 arg.transportFactory(new TFramedTransport.Factory()); //arg.transportFactory(new TTransportFactory()); //---------------thrift数据传输方式------------------------------ //设置处理器(Processor)工厂 arg.processorFactory(new TProcessorFactory(processor)); //---------------thrift支持的服务模型------------------------------ //1.TSimpleServer 简单的单线程服务模型,用于测试 //2.TThreadPoolServer 多线程服务模型,使用的标准的阻塞式IO;运用了线程池,当线程池不够时会创建新的线程,当线程池出现大量空闲线程,线程池会对线程进行回收 //3.TNonBlockingServer 多线程服务模型,使用非阻塞式IO(需要使用TFramedTransport数据传输方式) //4.THsHaServer YHsHa引入了线程池去处理(需要使用TFramedTransport数据传输方式),其模型把读写任务放到线程池去处理;Half-sync/Half-async(半同步半异步)的处理模式;Half-sync是在处理IO时间上(sccept/read/writr io),Half-async用于handler对RPC的同步处理 //---------------------------- //根据参数实例化server //半同步半异步的server TServer server = new THsHaServer(arg); //---------------thrift支持的服务模型------------------------------ System.out.println("shrift server started; port:" + port); //启动server // 异步非阻塞的死循环 server.serve(); } catch (TTransportException e) { e.printStackTrace(); } } }
6、项目启动,将Thrift进行启动发布即可
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class,args); } /** * 向Spring注册一个Bean对象 * initMethod = "start" 表示会执行名为start的方法 * start方法执行之后,就会阻塞接受客户端的请求 * * @return */ @Bean(initMethod = "start") public ThriftServerConf init() { ThriftServerConf thriftServer = new ThriftServerConf(); return thriftServer; } }
7、编写客户端进行测试
public class ThriftClientTest { public static void main(String[] args) throws TException { TTransport tTransport = new TFramedTransport(new TSocket("127.0.0.1", 9991), 600); tTransport.open(); //协议对象 这里使用协议对象需要和服务器的一致 TProtocol tProtocol = new TCompactProtocol(tTransport); StudyService.Client client = new StudyService.Client(tProtocol); String s = client.thriftFun("测试名称"); System.out.println(JSONUtil.toJsonStr(s)); } }
项目源码git地址:https://github.com/1924605670/STUDY_DEMO.git