前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Thrift快速入门和简单示例

Thrift快速入门和简单示例

作者头像
lovelife110
发布2022-06-27 09:51:01
8640
发布2022-06-27 09:51:01
举报
文章被收录于专栏:爱生活爱编程爱生活爱编程

文章目录

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

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

代码语言:javascript
复制
#可以通过以下命令查看生成命令的格式
thrift -help

创建Thrift IDL文件

代码语言:javascript
复制
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)
}

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

代码语言:javascript
复制
# 编译user.thrift
thrift -gen java user.thrift

生成UserService.java、User.java

User.java:

代码语言:javascript
复制
@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();
  ...

UserService.java:

代码语言:javascript
复制
@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;

  }
...

实现UserServiceService.Iface的定义方法

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

代码语言:javascript
复制
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;
    }
}

服务器端程序编写

代码语言:javascript
复制
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();
        }

    }
}

python客户端代码编写

  1. 通过编译器编译user.thrift文件,生成python代码然后将生成的 python 代码 和 文件,放到新建的 python 项目中
代码语言:javascript
复制
thrift -gen py user.thrift
  1. python中使用thrift需要安装thrift模块
代码语言:javascript
复制
pip install thrift
  1. 创建python客户端程序
代码语言:javascript
复制
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)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-06-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • Thrift介绍
  • Thrift的架构
  • Thrift的特性
    • 开发速度快
      • 接口维护简单
        • 学习成本低
          • 多语言/跨语言支持
            • 稳定/广泛使用
            • 快速入门例子
              • 编译安装
                • 创建Thrift IDL文件
                  • 通过编译器编译user.thrift文件,生成java接口类文件
                    • 实现UserServiceService.Iface的定义方法
                      • 服务器端程序编写
                        • python客户端代码编写
                        相关产品与服务
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档