• Thrift快速入门和简单示例


    Thrift介绍

    Thrift是一个轻量级、跨语言的RPC框架,主要用于各个服务之间的RPC通信,它通过自身的IDL中间语言, 并借助代码生成引擎生成各种主流语言的RPC服务端/客户端模板代码。Thrift支持多种不同的编程语言,包括C++, Java, Python, PHP等。

    Thrift官网地址,以下内容基于Apache Thrift v0.15.0。

    RPC 全称 Remote Procedure Call——远程过程调用。RPC技术简单说就是为了解决远程调用服务的一种技术,使得调用者像调用本地服务一样方便透明

    Thrift是一个典型的CS(客户端/服务端)结构,客户端和服务端可以使用不同的语言开发。既然客户端和服务端能使用不同的语言开发,那么一定就要有一种中间语言来关联客户端和服务端的语言,这种语言就是IDL (InterfaceDescription Language)

    Thrift的架构

    在这里插入图片描述
    Thrift技术栈分层从下向上分别为:传输层(Transport Layer)、协议层(Protocol Layer)、处理层(Processor Layer)和服务层(Server Layer)。最底层是IO层,如通过socket进行网络通信。

    • 传输层(Transport Layer):传输层负责直接从网络中读取和写入数据,它定义了具体的网络传输协议。thrift传输层支持阻塞式IO和非阻塞式IO。
    • 协议层(Protocol Layer):协议层定义了数据传输格式,负责网络传输数据的序列化和反序列化;比如说JSON、XML、二进制数据等。
    • 处理层(Processor Layer):处理层是由具体的IDL(接口描述语言)生成的,封装了具体的底层网络传输和序列化方式,并委托给用户实现的Handler进行处理。
    • 服务层(Server Layer):整合上述组件,提供具体的网络IO模型(单线程/多线程/事件驱动),形成最终的服务。即业务逻辑代码。

    Thrift的特性

    开发速度快

    通过编写RPC接口Thrift IDL文件,利用编译生成器自动生成服务端骨架(Skeletons)和客户端桩(Stubs)。从而省去开发者自定义和维护接口编解码、消息传输、服务器多线程模型等基础工作。

    服务端:只需要按照服务骨架即接口,编写好具体的业务处理程序(Handler)即实现类即可。

    客户端:只需要拷贝IDL定义好的客户端桩和服务对象,然后就像调用本地对象的方法一样调用远端服务。

    接口维护简单

    通过维护Thrift格式的IDL(接口描述语言)文件(注意写好注释),即可作为给Client使用的接口文档使用,也自动生成接口代码,始终保持代码和文档的一致性。且Thrift协议可灵活支持接口的可扩展性。

    学习成本低

    因为其来自Google Protobuf开发团队,所以其IDL文件风格类似Google Protobuf,且更加易读易懂;特别是RPC服务接口的风格就像写一个面向对象的Class一样简单。
    初学者只需参照:http://thrift.apache.org/,一个多小时就可以理解Thrift IDL文件的语法使用。

    多语言/跨语言支持

    Thrift支持C++、 Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk等多种语言,即可生成上述语言的服务器端和客户端程序。

    稳定/广泛使用

    Thrift在很多开源项目中已经被验证是稳定和高效的,例如Cassandra、Hadoop、HBase等;国外在Facebook中有广泛使用,国内包括百度、美团小米、和饿了么等公司。

    快速入门例子

    编写user.thrift,通过IDL中间语言生成java代码,python代码,结合生成的代码,编写java服务端和python客户端,实现python跨语言调用java服务端接口代码。

    编译安装

    thrift编译器的安装
    参考文档:https://thrift.apache.org/docs/install/
    windows 安装
    下载地址:https://thrift.apache.org/download
    centos 安装
    参考文档:https://thrift.apache.org/docs/install/centos.html

    安装好后,配置好环境变量,测试安装是否成功:

    #可以通过以下命令查看生成命令的格式
    thrift -help
    
    • 1
    • 2

    创建Thrift IDL文件

    namespace java com.test
    namespace py com.test
    
    struct User{
        1:i32 id
        2:string name
        3:i32 age=0
    }
    
    service  UserService {
      User getById(1:i32 id)
      bool isExist(1:string name)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    通过编译器编译user.thrift文件,生成java接口类文件

    # 编译user.thrift
    thrift -gen java user.thrift
    
    • 1
    • 2

    生成UserService.java、User.java

    User.java:

    @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
    @javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.15.0)", date = "2022-01-14")
    public class User implements org.apache.thrift.TBase<User, User._Fields>, java.io.Serializable, Cloneable, Comparable<User> {
      private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("User");
    
      private static final org.apache.thrift.protocol.TField ID_FIELD_DESC = new org.apache.thrift.protocol.TField("id", org.apache.thrift.protocol.TType.I32, (short)1);
      private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)2);
      private static final org.apache.thrift.protocol.TField AGE_FIELD_DESC = new org.apache.thrift.protocol.TField("age", org.apache.thrift.protocol.TType.I32, (short)3);
    
      private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new UserStandardSchemeFactory();
      private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new UserTupleSchemeFactory();
      ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    UserService.java:

    @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
    @javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.15.0)", date = "2022-01-14")
    public class UserService {
    
      public interface Iface {
    
        public User getById(int id) throws org.apache.thrift.TException;
    
        public boolean isExist(java.lang.String name) throws org.apache.thrift.TException;
    
      }
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    实现UserServiceService.Iface的定义方法

    将生成类的UserService.java、User.java源文件拷贝进项目源文件目录中,并实现UserServiceService.Iface的定义的getById()方法。

    package com.test.service;
    
    import org.apache.thrift.TException;
    
    import com.test.User;
    import com.test.UserService;
    
    public class UserServiceImpl implements UserService.Iface {
    
        @Override
        public User getById(int id) throws TException {
    
            System.out.println("=====调用getById=====");
            //todo 模拟业务调用
            User user = new User();
            user.setId(id);
            user.setName("fox");
            user.setAge(30);
    
            return user;
        }
    
        @Override
        public boolean isExist(String name) throws TException {
            return false;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    服务器端程序编写

    public class SimpleService {
    
        public static void main(String[] args) {
    
            try {
                TServerTransport serverTransport = new TServerSocket(9090);
    
                //获取processor
                UserService.Processor processor = new UserService.Processor(new UserServiceImpl());
                //指定TBinaryProtocol
                TBinaryProtocol.Factory protocolFactory = new TBinaryProtocol.Factory();
    
                TSimpleServer.Args targs = new TSimpleServer.Args(serverTransport);
                targs.processor(processor);
                targs.protocolFactory(protocolFactory);
    
                //单线程服务模型,一般用于测试
                TServer server = new TSimpleServer(targs);
    
                System.out.println("Starting the simple server...");
                //暴露服务
                server.serve();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    python客户端代码编写

    1. 通过编译器编译user.thrift文件,生成python代码然后将生成的 python 代码 和 文件,放到新建的 python 项目中
    thrift -gen py user.thrift
    
    • 1
    1. python中使用thrift需要安装thrift模块
    pip install thrift
    
    • 1
    1. 创建python客户端程序
    from thrift.transport import TSocket, TTransport
    from thrift.protocol import TBinaryProtocol
    from com.tuling import UserService
    # Make socket
    transport = TSocket.TSocket('localhost', 9090)
    transport.setTimeout(600)
    # Buffering is critical. Raw sockets are very slow
    transport = TTransport.TBufferedTransport(transport)
    # Wrap in a protocol
    protocol = TBinaryProtocol.TBinaryProtocol(transport)
    # Create a client to use the protocol encoder
    client = UserService.Client(protocol)
    # Connect!
    transport.open()
    result = client.getById(1)
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    计算机毕业设计(附源码)python疫情期间的校园防控管理系统
    Linux随记(四)
    iwebsec靶场 代码执行关卡通关笔记
    性能优化之详解各种指标
    LINUX-VIM编辑器常用命令大全(超全)
    计算机网络-第2章物理层
    高可用集群HA、LVS+Keepalived、健康检测
    d3力导向图
    主控制文件(项目的开始)食用顺序_3
    vue实战入门后台篇十:springboot+mybatis实现网站后台-项目整合发布测试
  • 原文地址:https://blog.csdn.net/qq_33873431/article/details/125414486