GO语言的三种RPC使用方式

本文栗子,服务端实现对字符串的md5加密。客户端传递字符串通过rpc方式调用服务端,获得 md5 加密后的密文。 共通过三种方式实现,(1)go 语言 原生 RPC方式 (2) go语言原生 RPC + protobuff 实现 (3) GRPC 框架实现

1.go原生 rpc

#server.go
package main

import (
	"crypto/md5"
	"encoding/hex"
	"net"
	"net/http"
	"net/rpc"
)
// 加密工具类
type EncryptionUtil struct {
}

// 加密方法
func (eu *EncryptionUtil) Encryption(req string, resp *string) error {
	*resp = ToMd5(req)
	return nil
}
// 封装 md5 方法
func ToMd5(s string) string{
	m := md5.New()
	m.Write([]byte (s))
	return hex.EncodeToString(m.Sum(nil))
}

func main() {
	// 功能对象注册
	encryption :=  new(EncryptionUtil)
	err := rpc.Register(encryption)  //rpc.RegisterName("自定义服务名",encryption)
	if err != nil {
		panic(err.Error())
	}
	// HTTP注册
	rpc.HandleHTTP()

	// 端口监听
	listen, err := net.Listen("tcp", ":8081")
	if err != nil {
		panic(err.Error())
	}
	// 启动服务
	_ = http.Serve(listen, nil)

}

#client.go
package main

import (
	"fmt"
	"net/rpc"
)

func main()  {
	// 建立连接
	client, err := rpc.DialHTTP("tcp", "localhost:8081")
	if err != nil {
		panic(err.Error())
	}
	// 参数
	req := "mclink"
	var resp *string
	// 同步调用
	err = client.Call("EncryptionUtil.Encryption", req, &resp)
	if err!= nil {
		panic(err.Error())
	}
	fmt.Println(*resp)

	// 异步调用
	syncCall := client.Go("EncryptionUtil.Encryption", req, &resp, nil)
	// 阻塞,异步调用成功后解除阻塞
	replayDone := <-syncCall.Done
	fmt.Println(replayDone)
	fmt.Println(*resp)

}

2.rpc 结合 protobuf

2.1 mac 安装 grpc 环境

需要先安装 grpc 命令和对应的相关包

brew tap grpc/grpc
brew install protobuf
go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
2.2 编写 proto 文件
#message.proto
syntax = "proto3";

package message;
option go_package = "./;message";

// 加密请求
message  EncryptionRequest{
  string str = 1;
}
// 加密返回值
message EncryptionResult{
  string result = 1;
}

2.3 编译proto文件
protoc ./message.proto --go_out=./ 


# 得到的目录结构
.
├── client_test.go
├── message
│   ├── message.pb.go
│   └── message.proto
└── server.go

2.4 编写程序
#server.go
// 加密服务
type EncryptionService struct {
}

// 加密程序, 这里和原生的不同是,参数类型都使用了生成的 pb 文件里面的类
func (es *EncryptionService) Encryption(request *message.EncryptionRequest, response *message.EncryptionResult) error{
	md5Str := ToMd5(request.GetStr())
	response.Result = md5Str
	return nil
}

// 简单封装的 md5
func ToMd5(s string) string{
	m := md5.New()
	m.Write([]byte (s))
	return hex.EncodeToString(m.Sum(nil))
}


func main() {
	// 功能对象注册
	encryption :=  new(EncryptionService)
	err := rpc.Register(encryption)  //rpc.RegisterName("自定义服务名",encryption)
	if err != nil {
		panic(err.Error())
	}
	// HTTP注册
	rpc.HandleHTTP()

	// 端口监听
	listen, err := net.Listen("tcp", ":8081")
	if err != nil {
		panic(err.Error())
	}
	_ = http.Serve(listen, nil)
}

#client_test.go
func TestClient(t *testing.T)  {
	// 建立连接
	client, err := rpc.DialHTTP("tcp", "localhost:8081")
	if err != nil {
		panic(err.Error())
	}

	req := message.EncryptionRequest{Str: "mclink"}
	resp := message.EncryptionResult{}
	// 同步调用
	err = client.Call("EncryptionService.Encryption", &req, &resp)
	if err!= nil {
		panic(err.Error())
	}
	fmt.Println(resp.GetResult())

}

3.GRPC 实现

3.1 编写 proto 文件
syntax = "proto3";

package message;
option go_package = "./;message";

// 加密请求
message  EncryptionRequest{
  string str = 1;
}
// 加密返回值
message EncryptionResult{
  string result = 1;
}

// 加密service定义, 服务注册
service EncryptionService {
  rpc Encryption(EncryptionRequest) returns (EncryptionResult);
}
2.3 编译proto文件
go get -u google.golang.org/grpc

protoc ./message.proto --go_out=plugins=grpc:./ 


# 得到的目录结构
.
├── client_test.go
├── message
│   ├── message.pb.go
│   └── message.proto
└── server.go

2.4 编写程序
#server.go
// 加密服务实现类
type EncryptionServiceImpl struct {
}

// 加密程序
func (es *EncryptionServiceImpl) Encryption(ctx context.Context, request *message.EncryptionRequest) (*message.EncryptionResult, error){
	md5Str := ToMd5(request.GetStr())
	res := message.EncryptionResult{Result:md5Str}
	return &res,nil
}

// 简单封装的 md5
func ToMd5(s string) string{
	m := md5.New()
	m.Write([]byte (s))
	return hex.EncodeToString(m.Sum(nil))
}


func main() {
	// 创建一个 grpc server
	server := grpc.NewServer()

	message.RegisterEncryptionServiceServer(server, new(EncryptionServiceImpl))

	lis, err := net.Listen("tcp", ":8081")
	if err != nil {
		panic(err.Error())
	}
	_ = server.Serve(lis)
}

#client_test.go
func TestClient(t *testing.T)  {
	//1、Dail连接
	conn, err := grpc.Dial("localhost:8081", grpc.WithInsecure())
	if err != nil {
		panic(err.Error())
	}
	defer conn.Close()
	encryptionServiceClient := message.NewEncryptionServiceClient(conn)

	orderRequest := &message.EncryptionRequest{Str: "mclink"}
	result, err := encryptionServiceClient.Encryption(context.Background(), orderRequest)
	if result != nil {
		fmt.Println(result.Result)
	}
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MClink

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值