RPC框架实践之:Apache Thrift

简介:

我的桌面

这是我的桌面之一


一、概述

RPC(Remote Procedure Call)即 远程过程调用,说的这么抽象,其实简化理解就是一个节点如何请求另一节点所提供的服务。在文章 微服务调用链追踪中心搭建 一文中模拟出来的调用链:ServiceA ---> ServiceB ---> ServiceC 就是一个远程调用的例子,只不过这篇文章里是通过RestTemplate这种 同步调用方式,利用的是HTTP协议在应用层完成的,这种方法虽然奏效,但有时效率并不高。而RPC可以不依赖于应用层协议,可以直接基于TCP进行远程调用,在传输层中即可完成通信,因此更适于某些对效率要求更高的场景。由于RPC调用方式依赖于客户端与服务端之间建立Socket连接来实现二进制数据通信,底层会比较复杂,所以一些RPC框架应运而生来封装这种复杂性,让开发者将精力聚焦于业务之上。常见的RPC框架包括:Thrift、gRPC、Finagle、Dubbo等等,从本文开始作者将选一些实践一下,本文主要记录作者对于Thrift框架的实践过程。

Thrift是Apache的项目,它结合了功能强大的软件堆栈和代码生成引擎,可以在诸多语言之间提供无缝支持。

心动不如行动吧!


二、实验环境

  • Mac OS X 10.13.2
  • SpringBoot 2.0.1
  • Thrift 0.11.0
  • IDE:IntelliJ IDEA 2018.01

为了便于读者理解,我先将下文内容总结一下,包含7点:

  • Thrift环境搭建
  • IDEA中Thrift插件配置
  • 创建 Thrift 项目并编译(目的:定义RPC接口)
  • 开发Thrift API接口
  • 开发RPC服务端
  • 开发RPC客户端
  • RPC通信实际实验

三、Thrift环境搭建

  • 方法一:原生安装方式,通过官方提供的步骤一步一步来安装

参考这里:Mac上Thrift官方安装教程

  • 方法二:使用 brew 工具(推荐

brew install thrift

brew install thrift


四、IDEA中Thrift插件配置

方法一:直接在IDEA界面中配置

打开IDEA的插件中心,搜索 Thrift 即可安装

利用插件中心安装Thrift

方法二:手动下载Thrift插件安装

就像文章 SpringBoot优雅编码之:Lombok加持 一文中在IDEA中安装Lombok插件一样,有时由于网络原因,方法一不奏效时插件装不上,此时可以手动下载插件并安装。

可以去如下地址下载Thrift插件:http://plugins.jetbrains.com/plugin/7331-thrift-support

手动下载Thrift插件

然后去IDEA中 Install plugin from disk... 选择下载的zip包安装,然后重启IDE即可

Install plugin from disk

安装完成的成功标志是 Compiler 中出现了 Thrift编译器!如下图所示:

成功安装Thrift插件


五、创建 Thrift 项目并编译(定义RPC接口)

  • 第一步:创建Thrift项目并配置

IDE 很智能地在 New Project 时提供 Thrift项目创建选项:

Thrift项目创建选项

项目创建完成以后,在 Project Settings 中设置好 Facets 的 Thrift配置,如下图所示,这里我们添加一个 Java的Generator

添加一个Java的Generator

在弹出的对话框中配置好 Output folder 路径,该路径用于存放由 thrift文件 转化而成的 java源文件

配置好Output folder

OK,Thrift项目就绪了!

  • 第二步:创建thrift接口文件

这里创建一个thrift接口文件:RPCDateService.thrift

thrift文件的写法我不赘述,跟gRPC一样有其自己的语法,namespace是最后生成的接口文件的包名

namespace java com.hansonwang99.thrift.interface
service RPCDateService{
    string getDate(1:string userName)
}

在该接口文件中,我们定义了一个 提供日期的Service,让客户端能通过该接口查询到服务器当前的时间

  • 第三步:编译Thrift源文件生成Java接口类

右击.thrift源文件,点击 Recompile 'xxx.thrift' 即可完成 thrift接口文件 ---> java接口文件 的转换

Recompile 'xxx.thrift'

输出的Java接口文件生成于上文中配置的 output 中,其 包结构=上文.thrift文件中的namespace ,其包结构如下图所示,该Java接口十分重要,后续会用于实现Client和Server之间的RPC调用。

输出的.java文件


六、开发Thrift API接口

我们创建一个Maven项目:ThriftAPI,其包含的的就是上文由自定义Thrift接口生成的Java接口:RPCDateService.java 文件,该文件将用于后面的RPC服务端和RPC客户端的代码实现!

  • pom.xml中添加thrift依赖
    <dependencies>
        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.11.0</version>
        </dependency>
    </dependencies>
  • 添加RPCDateService.java

将上文 第五步RPCDateService.thrift 生成的 RPCDateService.java 原样拷贝到该Maven项目中即可,代码结构如下:

ThriftAPI代码结构

再次强调,该 ThriftAPI项目 会服务于下文即将要创建的RPC服务端和RPC客户端


七、开发RPC服务端

我们是利用SpringBoot来实现RPC服务端

  • pom.xml中添加依赖

这里除了自动添加好的SpringBoot依赖外,需要额外添加的就是上文的 ThriftAPI依赖

<dependency>
        <groupId>com.hansonwang99</groupId>
        <artifactId>ThriftAPI</artifactId>
         <version>1.0-SNAPSHOT</version>
</dependency>
  • 创建Controller并实现RPC接口
@Controller
public class RPCDateServiceImpl implements RPCDateService.Iface {
    @Override
    public String getDate(String userName) throws TException {
        Date now=new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("今天是"+"yyyy年MM月dd日 E kk点mm分");
        String nowTime = simpleDateFormat.format( now );
        return "Hello " + userName + "\n" + nowTime;
    }
}

这里将服务器当前时间以字符串形式返回给调用端!

  • 编写RPCThriftServer:用于启动RPC服务器
@Component
public class RPCThriftServer {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Value("${thrift.port}")
    private int port;
    @Value("${thrift.minWorkerThreads}")
    private int minThreads;
    @Value("${thrift.maxWorkerThreads}")
    private int maxThreads;

    private TBinaryProtocol.Factory protocolFactory;
    private TTransportFactory transportFactory;

    @Autowired
    private RPCDateServiceImpl rpcDateService;

    public void init() {
        protocolFactory = new TBinaryProtocol.Factory();
        transportFactory = new TTransportFactory();
    }

    public void start() {
        RPCDateService.Processor processor = new RPCDateService.Processor<RPCDateService.Iface>( rpcDateService );
        init();
        try {
            TServerTransport transport = new TServerSocket(port);
            TThreadPoolServer.Args tArgs = new TThreadPoolServer.Args(transport);
            tArgs.processor(processor);
            tArgs.protocolFactory(protocolFactory);
            tArgs.transportFactory(transportFactory);
            tArgs.minWorkerThreads(minThreads);
            tArgs.maxWorkerThreads(maxThreads);
            TServer server = new TThreadPoolServer(tArgs);
            logger.info("thrift服务启动成功, 端口={}", port);
            server.serve();
        } catch (Exception e) {
            logger.error("thrift服务启动失败", e);
        }
    }
}
  • 创建SpringBootApplication
@SpringBootApplication
public class RPCThriftServerApplication {
    private static RPCThriftServer rpcThriftServer;
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(RPCThriftServerApplication.class, args);
        try {
            rpcThriftServer = context.getBean(RPCThriftServer.class);
            rpcThriftServer.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 添加配置文件application.properties
thrift.port=6666
thrift.minWorkerThreads=10
thrift.maxWorkerThreads=100

我们让thrift服务起在6666端口!

  • 启动RPC服务端服务

RPC服务端启动成功


八、开发RPC客户端

这里同样用SpringBoot来实现RPC客户端!

  • pom.xml中添加依赖

     此处同RPC服务端依赖,不赘述
    
  • 编写RPCThriftClient:用于发出RPC调用

这里包含两个文件:RPCThriftClient.javaRPCThriftClientConfig.java

RPCThriftClient.java如下:

public class RPCThriftClient {
    private RPCDateService.Client client;
    private TBinaryProtocol protocol;
    private TSocket transport;
    private String host;
    private int port;

    public String getHost() {
        return host;
    }
    public void setHost(String host) {
        this.host = host;
    }
    public int getPort() {
        return port;
    }
    public void setPort(int port) {
        this.port = port;
    }

    public void init() {
        transport = new TSocket(host, port);
        protocol = new TBinaryProtocol(transport);
        client = new RPCDateService.Client(protocol);
    }

    public RPCDateService.Client getRPCThriftService() {
        return client;
    }

    public void open() throws TTransportException {
        transport.open();
    }

    public void close() {
        transport.close();
    }
}

RPCThriftClientConfig.java是利用config生成bean

@Configuration
public class RPCThriftClientConfig {
    @Value("${thrift.host}")
    private String host;
    @Value("${thrift.port}")
    private int port;

    @Bean(initMethod = "init")
    public RPCThriftClient rpcThriftClient() {
        RPCThriftClient rpcThriftClient = new RPCThriftClient();
        rpcThriftClient.setHost(host);
        rpcThriftClient.setPort(port);
        return rpcThriftClient;
    }
}
  • 编写Restful的Controller作为调用入口
@RestController
@RequestMapping("/hansonwang99")
public class RPCThriftContoller {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private RPCThriftClient rpcThriftClient;

    @RequestMapping(value = "/thrift", method = RequestMethod.GET)
    public String thriftTest(HttpServletRequest request, HttpServletResponse response) {
        try {
            rpcThriftClient.open();
            return rpcThriftClient.getRPCThriftService().getDate("hansonwang99");
        } catch (Exception e) {
            logger.error("RPC调用失败", e);
            return "error";
        } finally {
            rpcThriftClient.close();
        }
    }
}
  • 创建SpringBootApplication
@SpringBootApplication
public class RPCThriftClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(RPCThriftClientApplication.class, args);
    }
}
  • 添加配置文件application.properties
thrift.host=localhost
thrift.port=6666
server.port=9999
  • 启动RPC客户端服务

RPC客户端启动成功


九、RPC通信实验

我们浏览器输入:localhost:9999/hansonwang99/thrift 即可查看客户端从服务端取回的服务器当前时间,说明RPC通信过程打通!

客户端成功从服务端取回结果


十、后记

本文实验代码已开源,点击获取

作者更多的原创文章:在云栖社区

作者一些其他容器化、微服务化方面的文章:


目录
相关文章
|
28天前
|
Dubbo 安全 应用服务中间件
Apache Dubbo 正式发布 HTTP/3 版本 RPC 协议,弱网效率提升 6 倍
在 Apache Dubbo 3.3.0 版本之后,官方推出了全新升级的 Triple X 协议,全面支持 HTTP/1、HTTP/2 和 HTTP/3 协议。本文将围绕 Triple 协议对 HTTP/3 的支持进行详细阐述,包括其设计目标、实际应用案例、性能测试结果以及源码架构分析等内容。
|
1月前
|
Java Apache C++
别再手写RPC了,Apache Thrift帮你自动生成RPC客户端及服务端代码
Thrift 是一个轻量级、跨语言的远程服务调用框架,由 Facebook 开发并贡献给 Apache。它通过 IDL 生成多种语言的 RPC 服务端和客户端代码,支持 C++、Java、Python 等。Thrift 的主要特点包括开发速度快、接口维护简单、学习成本低和多语言支持。广泛应用于 Cassandra、Hadoop 等开源项目及 Facebook、百度等公司。
别再手写RPC了,Apache Thrift帮你自动生成RPC客户端及服务端代码
|
1月前
|
自然语言处理 负载均衡 API
gRPC 一种现代、开源、高性能的远程过程调用 (RPC) 可以在任何地方运行的框架
gRPC 是一种现代开源高性能远程过程调用(RPC)框架,支持多种编程语言,可在任何环境中运行。它通过高效的连接方式,支持负载平衡、跟踪、健康检查和身份验证,适用于微服务架构、移动设备和浏览器客户端连接后端服务等场景。gRPC 使用 Protocol Buffers 作为接口定义语言,支持四种服务方法:一元 RPC、服务器流式处理、客户端流式处理和双向流式处理。
|
2月前
|
存储 数据挖掘 数据处理
Apache Paimon 是一款高性能的数据湖框架,支持流式和批处理,适用于实时数据分析
【10月更文挑战第8天】随着数据湖技术的发展,越来越多企业开始利用这一技术优化数据处理。Apache Paimon 是一款高性能的数据湖框架,支持流式和批处理,适用于实时数据分析。本文分享了巴别时代在构建基于 Paimon 的 Streaming Lakehouse 的探索和实践经验,包括示例代码和实际应用中的优势与挑战。
117 1
|
2月前
|
数据挖掘 物联网 数据处理
深入探讨Apache Flink:实时数据流处理的强大框架
在数据驱动时代,企业需高效处理实时数据流。Apache Flink作为开源流处理框架,以其高性能和灵活性成为首选平台。本文详细介绍Flink的核心特性和应用场景,包括实时流处理、强大的状态管理、灵活的窗口机制及批处理兼容性。无论在实时数据分析、金融服务、物联网还是广告技术领域,Flink均展现出巨大潜力,是企业实时数据处理的理想选择。随着大数据需求增长,Flink将继续在数据处理领域发挥重要作用。
173 0
|
4月前
|
Dubbo 网络协议 Java
RPC框架:一文带你搞懂RPC
这篇文章全面介绍了RPC(远程过程调用)的概念、原理和应用场景,解释了RPC如何工作以及为什么在分布式系统中广泛使用,并探讨了几种常用的RPC框架如Thrift、gRPC、Dubbo和Spring Cloud,同时详细阐述了RPC调用流程和实现透明化远程服务调用的关键技术,包括动态代理和消息的编码解码过程。
RPC框架:一文带你搞懂RPC
|
3月前
|
前端开发 JavaScript Java
Apache Wicket 框架:踏上从新手到英雄的逆袭之路,成就你的编程传奇!
【9月更文挑战第4天】Apache Wicket是一款基于Java的开源Web应用框架,以简洁、易维护及强大功能著称。它采用组件化设计,让页面开发更为模块化。Wicket的简洁编程模型、丰富的组件库、良好的可维护性以及对Ajax的支持,使其成为高效开发Web应用的理想选择。下文将通过解析Wicket的基本概念与特性,帮助读者深入了解这一框架的优势。
178 1
|
3月前
|
XML 负载均衡 监控
分布式-dubbo-简易版的RPC框架
分布式-dubbo-简易版的RPC框架
|
4月前
|
分布式计算 Hadoop 大数据
大数据处理框架在零售业的应用:Apache Hadoop与Apache Spark
【8月更文挑战第20天】Apache Hadoop和Apache Spark为处理海量零售户数据提供了强大的支持
77 0
|
11天前
|
存储 人工智能 大数据
The Past, Present and Future of Apache Flink
本文整理自阿里云开源大数据负责人王峰(莫问)在 Flink Forward Asia 2024 上海站主论坛开场的分享,今年正值 Flink 开源项目诞生的第 10 周年,借此时机,王峰回顾了 Flink 在过去 10 年的发展历程以及 Flink社区当前最新的技术成果,最后展望下一个十年 Flink 路向何方。
289 33
The Past, Present and Future of Apache Flink

推荐镜像

更多