自己动手写RPC-Thrift协议

本文介绍了Thrift作为RPC框架的基本使用,包括在Mac环境下安装Thrift,理解SOA架构,以及通过Thrift创建简单RPC服务的步骤。从接口定义、服务端实现到客户端调用,展示了Thrift如何实现语言无关的远程过程调用。同时,文中提到了Thrift与RMI的区别,并强调了服务治理在SOA架构中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

RPC其实在开发中十分的常用。RPC现在有很多种,比如dubbo,thrift等。首先来学习一下thrift
开发工具:Idea+macos

环境准备

安装一下thrift,其实这是一个工具,有点类似于编译器。在mac上比较简单

brew install thrift

安装完了之后执行一下命令,看看是不是安装好了。

thrift --version

如果能正确输出版本就是正常,如果不行就需要查看原因。如果是linux系统可以下载源码自己编译一个二进制文件出来(这个方式特别的费劲,我编译了一半放弃了。编译的时候依赖一个组件bison,这个组件在mac上自带,但是版本不符合,所以你要安装一个符合的版本覆盖掉这个东西)

SOA架构的理解

其实thrift实现的rpc是一种soa架构体系,就是面向服务的架构。这个东西我在大二的时候就听说过很多遍,知道今天我突然醒悟,才明白什么叫做SOA。其实现在的rpc框架,基本都是SOA的思想。SOA的核心思想是面向服务,所以就有了服务的治理,比如服务发现,服务注册,负载均衡等等。之所以有这些东西,是因为人们开发的模式改变了,大家把注意力转到了服务上,或者再直白点点就是面向某些函数,某些类做治理。

QuickStart

使用thrift做个简单的rpc

依赖

我看很多人写博客,直接代码就贴上去了。搞得其他人很难复线,依赖也没说。。。这里我说明一下:
开发环境:IDEA+jdk1.8+macOs
构建方式:maven
依赖pom:

   <dependencies>
        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.5</version>
        </dependency>
    </dependencies>

接口定义

通信接口是服务端和客户端的核心,这就是个协议,对于客户端来说,他拿到了这个协议就知道了服务端提供的服务是什么,需要传递什么参数,返回什么。至于怎么实现的不用管。对于服务端,有了这些协议他就能限制客户端的参数传递,必须是合法参数才能发起调用。有关thrift协议的写法,可以参考其他资料。

namespace java com.yg.demo
service Hello{
    string helloWorld(1:string para)
}

生成视图

thrift -r -gen java Hello.thrift

通过thrift工具生成一个Java类,这个类的名字和接口的名字一样。这个类里面定义了一个接口:

public class Hello {

  public interface Iface {

    public java.lang.String helloWorld(java.lang.String para) throws org.apache.thrift.TException;

  }
}

这个接口是服务端和客户端通信的关键,所以这里就体现了SOA的思想。其实这个接口是我们关心的服务。
然后服务端需要提供这个接口的实现,也就是具体的处理逻辑。

服务端处理逻辑

注意,上面你已经生成了一个名字叫做Hello的java类,这个类里面定义了一个接口。这个接口有两个含义:
(1)对于客户端来说,它通过这个接口知道自己需要传递什么参数,服务端返回什么参数
(2)对于服务端来说,自己需要实现这个接口,来处理客户端传递来的参数。
所以这里就是实现这个接口。

public class HelloImpl implements Hello.Iface {
    @Override
    public String helloWorld(String para) throws TException {
        System.out.println("hello" + para);
        return "hello" + para;
    }
}

服务端启动

有了处理逻辑还是不够,因为客户端和服务点事需要通过socket连接的。所以服务端需要启动一个Event Loop来接受客户端连接,这里其实可以用Netty实现,这个以后再做,暂时先做个简单的,就使用基本的实现。

public class HelloServiceServer {
    public static void main(String[] args) throws TTransportException {
        System.out.println("服务端开启......");
        TProcessor tProcessor = new Hello.Processor<Hello.Iface>(new HelloImpl());
        TServerSocket serverSocket = new TServerSocket(8999);
        TServer.Args tArgs = new TServer.Args(serverSocket);
        tArgs.processor(tProcessor);
        tArgs.protocolFactory(new TBinaryProtocol.Factory());
        TServer server = new TSimpleServer(tArgs);
        server.serve();
    }
}

这里其实有点像Java的RMI,启动类的作用就是把某个方法发布到端口。但是其实这里和RMI还是有区别的,首先最大的区别就是RMI是虚拟机到虚拟机的过程调用,也就是强制了两两端必须都是Java程序,但是thrift不要求这个。这也是thrift最大的特点:语言无关

客户端调用

public class Client {
    public static void main(String[] args) throws TException {
        System.out.println("客户端启动.....");
        TTransport transport =new TSocket("localhost", 8999, 30000);
        // 协议要和服务端一致
        TProtocol protocol = new TBinaryProtocol(transport);
        Hello.Client client = new Hello.Client(protocol);
        transport.open();
        String result = client.helloWorld("TOM");
        System.out.println(result);
    }
}

客户端调用就比较简单了,客户端依赖一个Hello的Client,然后通过这个Client发起请求。这里可以发现:client依赖了一个叫做TProtocl的东西,首先这个东西就是网络传输协议,它不仅包含了两端的序列化方式,还包含了transport信息。我们这里的transport信息是直接通过ip找到了,但是真实的业务场景我们是通过服务发现找到的,服务发现的时候又可以负载均更,所以这里就都串起来了。这个以后再做。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值