thrift协议(golang)

thrift 最初是 facebook 开发使用的 rpc 通信框架,后来贡献给了 apache 基金会,出来得比较早,几乎支持所有的后端语言,使用非常广泛,是不可不知的一个网络框架。
和 grpc 一样,需要先定义通信协议,然后实现自己业务逻辑。

  1. 安装golang的thrift协议包
go get git.apache.org/thrift.git/lib/go/thrift
  1. 定义协议文件
    文件名为RpcService.thrift
namespace go demo.rpc
// 测试服务
service RpcService {
    // 发起远程调用
    list<string> funCall(1:i64 callTime, 2:string funCode, 3:map<string, string> paramMap),

}

当函数funCall的参数总想包含自己设计的结构时,需要自己提前设计,例如

namespace go demo.rpc
struct EchoReq {
    1: string msg;
}
// 测试服务
service RpcService {
    // 发起远程调用
    list<string> funCall(1: EchoReq req),
}
  1. 生成开发库
    在.thrift文件路径下执行命令
    thrift -gen go RpcService.thrift
    生成
    在这里插入图片描述
    在这里插入图片描述
    其中 constants.go、rpc_service.go、ttypes.go 是协议库(自行参考),编写程序需要用到。rpc_service-remote.go 是自动生成的例程,可以不用。

ttypes.go 文件是结构体类型协议
rpcservice.go 文件是函数类型协议
constants.go 文件是常量类型协议(未使用)

  1. 服务端实现
package main
import (
	"fmt"
	"gen-go/demo/rpc"
	"git.apache.org/thrift.git/lib/go/thrift"
	"os"
)

const (
	NetworkAddr = "127.0.0.1:19090"
)

type RpcServiceImpl struct {
}

func (this *RpcServiceImpl) FunCall(callTime int64, funCode string, paramMap map[string]string) (r []string, err error) {
	fmt.Println("-->FunCall:", callTime, funCode, paramMap)

	for k, v := range paramMap {
		r = append(r, k+v)
	}
	return
}
func main() {
	transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
	protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
	serverTransport, err := thrift.NewTServerSocket(NetworkAddr)
	if err != nil {
		fmt.Println("Error!", err)
		os.Exit(1)
	}

	handler := &RpcServiceImpl{}
	processor := rpc.NewRpcServiceProcessor(handler)

	server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
	fmt.Println("thrift server in", NetworkAddr)
	server.Serve()
}

注意导入包的路径
transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
serverTransport, err := thrift.NewTServerSocket(NetworkAddr)
server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
以上函数都是由thrift库提供的函数

func NewRpcServiceProcessor(handler RpcService) *RpcServiceProcessor {
	self2 := &RpcServiceProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
	self2.processorMap["funCall"] = &rpcServiceProcessorFunCall{handler: handler}
	return self2
}

thrift通过key-value保存了我们实际将要运行的函数,最终通过handler来执行。
server.Serve()启动服务
监听并处理

func (p *TSimpleServer) Serve() error {
	err := p.Listen()
	if err != nil {
		return err
	}
	p.AcceptLoop()
	return nil
}
func (p *TSimpleServer) AcceptLoop() error {
		p.processRequests(client)
}

processor.Process(inputProtocol, outputProtocol)//接受信息和输出信息
利用go语言的接口实现多态执行对应函数
在这里插入图片描述
return processor.Process(seqId, iprot, oprot)
在这里插入图片描述
retval, err2 = p.handler.FunCall(args.CallTime, args.FunCode, args.ParamMap);
调用服务端接口
在这里插入图片描述
执行

func (this *RpcServiceImpl) FunCall(callTime int64, funCode string, paramMap map[string]string) (r []string, err error) {
	fmt.Println("-->FunCall:", callTime, funCode, paramMap)
	for k, v := range paramMap {
		r = append(r, k+v)
	}
	time.Sleep(10*time.Second)
	return
}
  1. 客户端实现
package main

import (
	"fmt"
	"gen-go/demo/rpc"
	"git.apache.org/thrift.git/lib/go/thrift"
	"net"
	"os"
	"time"
)

func main() {
	startTime := currentTimeMillis()
	transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
	protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()

	transport, err := thrift.NewTSocket(net.JoinHostPort("127.0.0.1", "19090"))
	if err != nil {
		fmt.Fprintln(os.Stderr, "error resolving address:", err)
		os.Exit(1)
	}

	useTransport := transportFactory.GetTransport(transport)
	client := rpc.NewRpcServiceClientFactory(useTransport, protocolFactory)
	if err := transport.Open(); err != nil {
		fmt.Fprintln(os.Stderr, "Error opening socket to 127.0.0.1:19090", " ", err)
		os.Exit(1)
	}
	defer transport.Close()

	for i := 0; i < 1000; i++ {
		paramMap := make(map[string]string)
		paramMap["name"] = "qinerg"
		paramMap["passwd"] = "123456"
		r1, e1 := client.FunCall(currentTimeMillis(), "login", paramMap)
		fmt.Println(i, "Call->", r1, e1)
	}

	endTime := currentTimeMillis()
	fmt.Println("Program exit. time->", endTime, startTime, (endTime - startTime))
}

// 转换成毫秒
func currentTimeMillis() int64 {
	return time.Now().UnixNano() / 1000000
}

r1, e1 := client.FunCall(currentTimeMillis(), “login”, paramMap)
rpcservice.go 中

func (p *RpcServiceClient) FunCall(callTime int64, funCode string, paramMap map[string]string) (r []string, err error) {
	if err = p.sendFunCall(callTime, funCode, paramMap); err != nil {
		return
	}
	return p.recvFunCall()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用 Line thrift 协议的示例代码: ```thrift namespace java com.example struct Person { 1: required string name; 2: optional i32 age; } service PersonService { Person getPerson(1: string name); } ``` 通过上述 thrift 定义文件,可以生成对应的 Java 类和接口代码。假设生成的 Java 代码包名为 `com.example`,则 `Person` 类和 `PersonService` 接口的代码如下: ```java package com.example; import org.apache.thrift.TException; 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 org.apache.thrift.transport.TTransportException; public class Person { private String name; private Integer age; public Person() {} public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } public interface PersonService { public Person getPerson(String name) throws TException; } public class PersonServiceClient implements PersonService { private TTransport transport; private TProtocol protocol; private PersonService.Client client; public PersonServiceClient() throws TTransportException { transport = new TSocket("localhost", 9090); protocol = new TBinaryProtocol(transport); client = new PersonService.Client(protocol); transport.open(); } public void close() { transport.close(); } public Person getPerson(String name) throws TException { return client.getPerson(name); } } public class PersonServiceHandler implements PersonService.Iface { public Person getPerson(String name) throws TException { // TODO: implement the logic to retrieve the person data return new Person(name, 30); } } ``` 在上述代码中,`Person` 类表示一个人的信息,包括姓名和年龄。`PersonService` 接口定义了一个获取人员信息的方法 `getPerson`。`PersonServiceClient` 类是一个 thrift 客户端,用于调用 `getPerson` 方法。`PersonServiceHandler` 类是一个 thrift 服务端,实现了 `getPerson` 方法的具体逻辑。这些类的代码都是根据上述 thrift 定义文件自动生成的。同时,代码中也包含了使用 thrift 进行网络通信的相关代码,如 `TTransport`、`TProtocol` 和 `TSocket` 等类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值