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)
	}
}

你可能感兴趣的:(Go大法,go,rpc)