RPC远程过程调用,传输层完成通信,TCP Socket进行控制。
常见的RPC框架包括:Thrift、gRPC、Finagle、Dubbo等等。

1 thrift简介

1.1 thrift定义

Thrift是Apache的项目。Thrift是一种接口描述语言和二进制通讯协议,它被用来定义和创建跨语言的服务。

1.2 thrift下载

如下图,这里下载最新的window环境下 0.17.0是版本。

springboot 基础fastdfs springboot thrift_User

下载后修改为thrift.exe文件,方便输入。控制台环境,输入命令:thrift –version 验证版本。

springboot 基础fastdfs springboot thrift_java_02

1.3 thrift 类型

thrift基本类型:

  1. string, 字符串类型,注意是全部小写形式;例如:string aString
  2. i16, 16位整形类型,例如:i16 aI16Val;
  3. i32,32位整形类型,对应C/C++/java中的int类型;例如: I32 aIntVal
  4. i64,64位整形,对应C/C++/java中的long类型;例如:I64 aLongVal
  5. byte,8位的字符类型,对应C/C++中的char,java中的byte类型;例如:byte aByteVal
  6. bool, 布尔类型,对应C/C++中的bool,java中的boolean类型; 例如:bool aBoolVal
  7. double,双精度浮点类型,对应C/C++/java中的double类型;例如:double aDoubleVal
  8. void,空类型,对应C/C++/java中的void类型;该类型主要用作函数的返回值,例如:void testVoid(),

容器有:

  1. ]list,链表类型,例如,定义一个list对象:list aList;
  2. set,集合类型,例如,定义set对象:set aSet;
  3. map,map类型,例如,定义一个map对象:map<i32, i32> newmap;

支持两种自定义类型:

  1. enum, 枚举类型,例如,定义一个枚举类型:
    enum Kind
    {
    ONE = 1,
    TWO,
    THREE,
    FIVE = 5,
    SIX,
    EIGHT = 8
    }
  2. struct,自定义结构体类型,在IDL中可以自己定义结构体,对应C中的struct,c++中的struct和class,java中的class。例如:
    struct User{
    1: i32 begin_in_both,
    3: string old_string,
    12: i32 end_in_both
    }

Exception:是一个继承于本地语言的exception基类

2 Springboot集成thrift

2.1 开发thrift接口

第1步:开发Thrift API接口;这里API接口是IDL文件。当然可以借助idea或其他编辑器的插件会更方便。这里手动编写。

这里定义user.thrift文件如下:

namespace java com.feidao.service

struct User
{
	1:i32 userId;	    #Id
	2:string userName;	#用户名
	3:string passWord;	#密码
	4:string telephone	#手机号
}

exception UserException
{
	1:string message 
}

service UserService
{
	string ping() throws (1:UserException ex);
	list<User> getUserList();
}

将user.thrift文件与thrift.exe放在同一目录下,输入命令:

thrift -gen java user.thrift

进入gen-java文件夹,可以看到生成的java文件。

springboot 基础fastdfs springboot thrift_User_03

2.2 springboot开发thrift server

第1步:POM文件引入

<dependency>
  <groupId>org.apache.thrift</groupId>
  <artifactId>libthrift</artifactId>
  <version>0.17.0</version>
</dependency>

第2步:工程中引入java接口文件。

第3步:定义UserServiceImpl.java文件实现接口文件。

package org.feidao.chapter71.service;

import com.feidao.service.User;
import com.feidao.service.UserException;
import com.feidao.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public class UserServiceImpl implements UserService.Iface {
    @Override
    public String ping() throws UserException, TException {
        return "pong";
    }

    @Override
    public List<User> getUserList() throws TException {
        List<User> userList = new ArrayList<>();

        User user1 = new User();
        user1.setUserName("曹操");
        userList.add(user1);

        User user2 = new User();
        user2.setUserName("刘备");
        userList.add(user2);

        User user3 = new User();
        user3.setUserName("孙权");
        userList.add(user3);

        return userList;
    }
}

第4步:定义 TCP socket server。

package org.feidao.chapter71;

import com.feidao.service.UserService;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.feidao.chapter71.service.UserServiceImpl;

//thrift server service的管理
public class UserServiceManager {
    //thrift service端口
    public final static int SERVER_USER_PORT = 8888;


    public UserServiceManager(){

    }

    public void server(){
        try {
            //创建TServer.Args
            TProcessor tProcessor = new UserService.Processor<UserService.Iface>(new UserServiceImpl());
            TServerSocket tServerSocket = new TServerSocket(SERVER_USER_PORT);
            TServer.Args args = new TServer.Args(tServerSocket);
            args.processor(tProcessor);
            args.protocolFactory(new TBinaryProtocol.Factory());

            //单线程服务模型,创建TServer
            TServer tServer = new TSimpleServer(args);

            //启动server
            tServer.serve();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

第5步:Application中启动Socket server。

2.3 springboot开发thrift client

第1步:POM文件引入

<dependency>
  <groupId>org.apache.thrift</groupId>
  <artifactId>libthrift</artifactId>
  <version>0.17.0</version>
</dependency>

第2步:工程中引入java接口文件。

第3步:定义client连接和调用服务:

package org.feidao.chapter72;

import com.feidao.service.User;
import com.feidao.service.UserService;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;

import java.util.List;

//thrift client service的管理
public class UserServiceManager {
    //thrift service端口
    public final static int SERVER_USER_PORT = 8888;
    //延时
    public final static int SERVER_TIME_DELAY = 30000;
    //server host
    private String host = "localhost";

    private TTransport tTransport = null;
    private UserService.Client client;

    public UserServiceManager(){

        try {
            tTransport = new TSocket(host,SERVER_USER_PORT,SERVER_TIME_DELAY);

            //定义协议
            TProtocol tProtocol = new TBinaryProtocol(tTransport);
            //创建client
            client = new UserService.Client(tProtocol);
            //打开通道
            tTransport.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void destroy(){
        if(tTransport!=null){
            tTransport.close();
        }
    }

    //测试与server端的通信
    public void testCommunication(){
        System.out.println("send ping....");
        try {
            String str = client.ping();
            if(!str.isEmpty()){
                System.out.println("receive:" + str);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public void getService(){
        try {
            List<User> userList = client.getUserList();
            if(userList!=null&& userList.size()>0){
                for(int i=0;i< userList.size();i++){
                    User user = userList.get(i);
                    System.out.println("user:" + user.userName);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

第4步:Application中连接server socket,调用thrift服务。

2.4 测试验证

第1步: 两个springboot项目启动端口分别为8081、8082:thrift服务端口为8888;

第2步:Server启动thrift服务:

springboot 基础fastdfs springboot thrift_java_04

第3步:client调用thrift服务:

springboot 基础fastdfs springboot thrift_spring boot_05


可以确认thrift服务远程调用成功。