# 3.2 gRPC

# 3.2.1 gRPC介绍

Jupiter微服务目前支持gRPCJupitergRPC服务提供了很多可观察性的手段。

内置了多个中间件,可以采集请求日志、采集trace、采集监控、采集慢日志,更加方便我们对gRPC服务的可观测。

通过govern的治理端口,能够查看监控、HTTP实时信息

# 3.2.2 配置规范

配置说明

# 3.2.3 直连的gRPC

参考gRPC直连示例

# 3.2.3.1 启动gRPC服务

配置项

[jupiter.server.grpc]
    port = 9091
1
2

代码

func main() {
	eng := NewEngine()
	eng.SetGovernor("127.0.0.1:9092")
	if err := eng.Run(); err != nil {
		xlog.Panic(err.Error())
	}
}

type Engine struct {
	jupiter.Application
}

func NewEngine() *Engine {
	eng := &Engine{}

	if err := eng.Startup(
		eng.serveGRPC,
	); err != nil {
		xlog.Panic("startup", xlog.Any("err", err))
	}
	return eng
}

func (eng *Engine) serveGRPC() error {
	server := xgrpc.StdConfig("grpc").Build()
	helloworld.RegisterGreeterServer(server.Server, new(Greeter))
	return eng.Serve(server)
}

type Greeter struct{}

func (g Greeter) SayHello(context context.Context, request *helloworld.HelloRequest) (*helloworld.HelloReply, error) {
	return &helloworld.HelloReply{
		Message: "Hello Jupiter",
	}, nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

运行指令go run main.go --config=config.toml,可以看到以下运行结果 image 从图中可以看到,我们启动了一个gRPC服务运行在9091端口,接下来我们启动客户端

# 3.2.3.2 启动gRPC客户端

配置项

[jupiter.client.directserver]
    address = "127.0.0.1:9091"
    balancerName = "round_robin" # 默认值
    block =  false # 默认值
    dialTimeout = "0s" # 默认值

1
2
3
4
5
6

代码


func main() {
	eng := NewEngine()
	if err := eng.Run(); err != nil {
		xlog.Error(err.Error())
	}
}

type Engine struct {
	jupiter.Application
}

func NewEngine() *Engine {
	eng := &Engine{}
	if err := eng.Startup(
		eng.consumer,
	); err != nil {
		xlog.Panic("startup", xlog.Any("err", err))
	}
	return eng
}

func (eng *Engine) consumer() error {
	conn := grpc.StdConfig("directserver").Build()
	client := helloworld.NewGreeterClient(conn)
	for {
		resp, err := client.SayHello(context.Background(), &helloworld.HelloRequest{
			Name: "jupiter",
		})
		if err != nil {
			xlog.Error(err.Error())
		} else {
			xlog.Info("receive response", xlog.String("resp", resp.Message))
		}
		time.Sleep(1 * time.Second)
	}
	return nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

我们的gRPC客户端通过配置里的地址和负载均衡算法,可以请求刚才我们启动的gRPC服务端。运行指令go run main.go --config=config.toml,可以看到以下运行结果 image 我们定时1s,发送hellogRPC服务端,可以收到服务端响应的Hello Jupiter

# 3.2.4 注册ETCD的gRPC服务

参考gRPC注册ETCD示例

# 3.2.4.2 启动gRPC服务

配置项

[jupiter.server.grpc]
    port = 9091
[jupiter.registry.wh]
    connectTimeout = "1s"
    endpoints=["127.0.0.1:2379"]
    secure = false
1
2
3
4
5
6

代码

func main() {
	eng := NewEngine()
	eng.SetRegistry(
		compound_registry.New(
			etcdv3_registry.StdConfig("wh").Build(),
		),
	)
	eng.SetGovernor("127.0.0.1:9092")
	if err := eng.Run(); err != nil {
		xlog.Error(err.Error())
	}
}

type Engine struct {
	jupiter.Application
}

func NewEngine() *Engine {
	eng := &Engine{}
	if err := eng.Startup(
		eng.serveGRPC,
	); err != nil {
		xlog.Panic("startup", xlog.Any("err", err))
	}
	return eng
}

func (eng *Engine) serveGRPC() error {
	server := xgrpc.StdConfig("grpc").Build()
	helloworld.RegisterGreeterServer(server.Server, new(Greeter))
	return eng.Serve(server)
}

type Greeter struct{}

func (g Greeter) SayHello(context context.Context, request *helloworld.HelloRequest) (*helloworld.HelloReply, error) {
	return &helloworld.HelloReply{
		Message: "Hello Jupiter",
	}, nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

运行指令go run main.go --config=config.toml,可以看到以下运行结果 image 从图中可以看到,我们启动了一个gRPC服务运行在9091端口,在命令行的第四行,展示了我们注册的keyvalue信息。接下来我们在启动客户端。

# 3.2.4.2 启动gRPC客户端

配置项

[jupiter.registry.wh]
    connectTimeout = "1s"
    endpoints=["127.0.0.1:2379"]
    secure = false
[jupiter.client.etcdserver]
    address = "etcd:///main"
    balancerName = "round_robin" # 默认值
    block =  false # 默认值
    dialTimeout = "0s" # 默认值
1
2
3
4
5
6
7
8
9

代码

func main() {
	eng := NewEngine()
	if err := eng.Run(); err != nil {
		xlog.Error(err.Error())
	}
}

type Engine struct {
	jupiter.Application
}

func NewEngine() *Engine {
	eng := &Engine{}
	if err := eng.Startup(
		eng.initResolver,
		eng.consumer,
	); err != nil {
		xlog.Panic("startup", xlog.Any("err", err))
	}
	return eng
}

func (eng *Engine) initResolver() error {
	resolver.Register(etcdv3_registry.StdConfig("wh").BuildResolver())
	return nil
}

func (eng *Engine) consumer() error {
	conn := grpc.StdConfig("etcdserver").Build()
	client := helloworld.NewGreeterClient(conn)
	for {
		resp, err := client.SayHello(context.Background(), &helloworld.HelloRequest{
			Name: "jupiter",
		})
		if err != nil {
			xlog.Error(err.Error())
		} else {
			xlog.Info("receive response", xlog.String("resp", resp.Message))
		}
		time.Sleep(1 * time.Second)
	}
	return nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

运行指令go run main.go --config=config.toml,可以看到以下运行结果 image 我们的gRPC客户端通过应用名称mainETCD中获取到服务地址,并监听了/jupiter/main,用于后续更新服务地址。

客户端会定时1s,发送hellogRPC服务端,可以收到服务端响应的Hello Jupiter