grpc component of go microservice

grpc use

If you want to know grpc, first understand rpc (These are my own in the article, and the small notes in the study are not detailed. If you want to know more, please Baidu, there are a lot of information.)

What is rpc?

definition:

The remote procedure call protocol is similar to the http request, but the protocol is different. Most of the rpc uses TCP, and the http request uses the HTTP protocol.

It can be simply understood as a node calling another node.

composition:

  • Client: Client, service caller.
  • Client Stub: Client Stub, which stores the server address information, packages the client's request parameter data information into a network message, and then sends it to the server through network transmission
  • Network transmission module: Network Service, underlying transmission, which can be TC or HTTP
  • Server Stub: Server Stub, which receives the request message sent by the client and unpacks it, and then calls the local service for processing.
  • Server, etc.: The real provider of server services.

Implementation process:

  • Client The client invokes the service through local invocation.
  • After receiving the call request, the client stub is responsible for serializing (assembling) information such as methods and input parameters into a message body capable of network transmission.
  • The Client Stub finds the remote service address and sends the message to the server through the network.
  • network transmission
  • The server stub decodes the message after receiving it (deserialization operation).
  • Server Stub calls local services for related processing based on the decoding results
  • Server (Server) local service business processing.
  • The processing result is returned to the Server Stub.
  • Server Stub serialization result.
  • The Server Stub sends the result to the consumer over the network.
  • The Client Stub receives the message and decodes it (deserialization).
  • The client gets the final result.

What is grpc

definition:

  • It is a high-performance, open source, and universal RPC framework.
  • HTTP2 protocol is used in gRPC
  • Google products
  • gRPC uses protoBuf by default

Composition: similar to rpc

Execution process: similar to rpc

note:

To learn more about rpc and grpc, please search
on Baidu . If there is an error in the article, please contact me.

go implement rpc

Server:

rpc_sample/go_rpc_server.go

package main

import (
	"fmt"
	"net"
	"net/http"
	"net/rpc"
)

type Say struct{
    
    }

/*
注意:对外暴露的服务方法定义
1、对外暴露的方法有且只能有两个参数,这两个参数只能是输出类型或内建类型,两种类型中的一种。
2、方法的第二个参数必须是指针类型。
3、方法的返回类型为error。
*/
func (s *Say) Hello(inputArg string, outputArg *string) error {
    
    
	*outputArg = "hello " + inputArg
	return nil
}

func main() {
    
    
	// new一个对象
	say := new(Say)

	// 将对象注册到rpc服务中
	rpc.Register(say)

	// 把say中的服务注册到HTTP协议上,方便调用者可以利用http的方式进行数据传递
	rpc.HandleHTTP()
	listen, err := net.Listen("tcp", "127.0.0.1:8080")
	if err != nil {
    
    
		fmt.Printf("net.Listen failed ,%v\n", err)
		return
	}

	http.Serve(listen, nil)
}

运行:go run go_rpc_server.go

Client:

rpc_sample/go_rpc_client.go

package main

import (
	"fmt"
	"net/rpc"
)

func main() {
    
    
	// DialHTTP:使用http去拨号,与服务端创建连接
	client, err := rpc.DialHTTP("tcp", "127.0.0.1:8080")
	if err != nil {
    
    
		fmt.Printf("rpc.DialHTTP failed ,%v\n", err)
		return
	}
	// 返回值
	var say string

	/*
		远程调用函数:被调用的方法,传入值 ,返回值
	*/
	err = client.Call("Say.Hello", "world!", &say)
	if err != nil {
    
    
		fmt.Printf("client.Call failed ,%v\n", err)
		return
	}
	fmt.Println("结果为:", say)
}
/*
结果为: hello world!
*/

go run go_rpc_client.go

grpc use

grpc install

GO111MODULE=on
GOPROXY=https://goproxy.io,direct

# 设置GO111MODULE、GOPROXY下载无压力
go get google.golang.org/[email protected]
go get google.golang.org/genproto

proto content definition

grpc_sample/grpc_protoBuf_sample/say_hi_sample.proto

syntax = "proto3";
option go_package = ".;hello";
package hello;
// 上面跟rpc基本一样定义

/*
	grpc + protobuf
	定义一个service类型
	SayHi暴露函数名
	可以定义多个服务,每个服务内可以定义多个接口
*/
service TestService {
  // 定义接口 (结构体可以复用)
  // 方法 (请求消息结构体) returns (返回消息结构体) {}
  //rpc 服务端对外的函数名(传入参数)returns(返回参数)
  rpc SayHi (HiRequest) returns (HiResponse){}
}

// 定义HiRequest消息结构
message HiRequest {
  string name = 1;
}

// 定义HiResponse消息结构
message HiResponse {
  string ret = 1;
}

proto generates go language files (grpc)

Note: grpc uses grpc plugin

# 直接到say_hi_sample.proto文件目录执行
protoc --go_out=plugins=grpc:. say_hi_sample.proto

# 会生成say_hi_sample.pb.go文件

grpc server (server)

grpc_sample/go_grpc_server.go

package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"net"
	hello "sample/grpc_sample/grpc_protoBuf_sample"
)

type Server struct{
    
    } //服务对象

/*
	SayHi实现在proto中定义的TestServiceServer interface接口
	
	type TestServiceServer interface {
	//rpc 服务端对外的函数名(传入参数)returns(返回参数)
	SayHi(context.Context, *HiRequest) (*HiResponse, error)
	}
	
	TestServiceServer接口是如何来的?
	1.grpc_sample/grpc_protoBuf_sample/say_hi_sample.proto
	  proto文件中定义service类型的名为:TestService

	2.proto转成go文件就会生成2个接口:
    生成规律也很明显,就是proto文件中定义service类型的名后面加Client、Server
		TestServiceClient
		TestServiceServer
		看名称很明显肯定关于客户端、服务端
*/
func (s *Server) SayHi(ctx context.Context, in *hello.HiRequest) (*hello.HiResponse, error) {
    
    
	res := &hello.HiResponse{
    
    Ret: "hello " + in.Name}
	return res, nil
}

// name  -->   "hello name"
func main() {
    
    
	// 创建grpc服务
	server := grpc.NewServer()

	/*
		**注册接口服务:
		 * 以定义proto时的service为单位注册,服务中可以有多个方法
		 * (proto编译时会为每个service生成Register***Server方法)
		 * 包.注册服务方法(gRpc服务实例,包含接口方法的结构体[指针])
			hello.RegisterTestServiceServer
			grpc注册服务:
				1.hello是包名
				2.RegisterTestServiceServer注册服务一个方法
			RegisterTestServiceServer:
				1.参数一:grpc服务
				2.参数二:服务对象
	*/
	hello.RegisterTestServiceServer(server, &Server{
    
    })

	listen, err := net.Listen("tcp", "127.0.0.1:8080")
	if err != nil {
    
    
		fmt.Printf("监听失败: %v\n", err)
	}
	fmt.Println("监听8080端口...")

	// 用grpc服务启动
	server.Serve(listen)
}

运行:go run go_grpc_server.go

grpc client (client)

grpc_sample/go_grpc_client.go

package main

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	hello "sample/grpc_sample/grpc_protoBuf_sample"
)

func main() {
    
    
	/*
		**建立连接到gRPC服务:
		 * WithInsecure:跳过证书的验证
	*/
	conn, err := grpc.Dial("127.0.0.1:8080", grpc.WithInsecure())
	if err != nil {
    
    
		fmt.Printf("grpc.Dial failed, :%v\n", err)
	}

	// 结束时关闭连接
	defer conn.Close()

	// 创建TestService服务的客户端
	client := hello.NewTestServiceClient(conn)

	// 调用gRPC接口
	rep, err1 := client.SayHi(context.Background(), &hello.HiRequest{
    
    Name: "world!"})
	if err1 != nil {
    
    
		fmt.Printf("client.SayHi failed, :%v\n", err1)
		return
	}
	fmt.Println(rep.Ret)
}

/* 运行结果:
hello wrold!
*/

运行:go run go_grpc_client.go

note:

开启go module
用GoLand创建项目会有个go.mod,没有go mod init。详细go mod自行百度
grpc演示中hello "sample/grpc_sample/grpc_protoBuf_sample"
我这个go.mod中module sample是sample,引入同项目不同目录下包就是sample/...
后面使用micro会使用go module导入不同项目下包。前面先了解下,大神可以略过。

再次说明:这些都是我自己学习过程中小笔记,如有错误望告知。还有就是一些相关介绍少,想详细了解请自行百度。

Guess you like

Origin blog.csdn.net/Maggie_up/article/details/108702287