gRpc-go流模式中,服务端如何主动关闭stream

在使用gRpc流模式的过程中会发现,官方API只提供了客户端关闭stream的方法。

1
2
3
4
// CloseSend closes the send direction of the stream. It closes the stream
// when non-nil error is met. It is also not safe to call CloseSend
// concurrently with SendMsg.
CloseSend() error

那么在开发过程中我们是不是需要从服务端主动断开stream,如果需要,该怎么断开?

如果你知道gRpc的底层原理,其实很好理解为什么官方不提供服务端断开的API。因为gRpc底层是通过TCP实现的 [事实上,基本上所有RPC框架默认都是使用TCP,因为RPC常用在业务系统之间进行数据交换,需要保证可靠性] ,TCP的连接建立 [三次握手] 与释放 [四次挥手] 都是由客户端发起的,所以这就是为什么服务端不支持主动断开API的原因。

但是在实际开发过程中,我们经常会遇到需要服务端主动断开的策略,如果客户端出现连接泄漏的问题,通过TCP一直连接服务端,那么势必会造成服务端的连接过多无法释放,内存上升甚至出现服务宕机的危险。

那么在开发过程中就要考虑到避免因为客户端的bug导致服务器不可用,服务端就需要有保护机制。

设计

服务端流式的设计,需要在发送给客户端响应时告知客户端,服务端已经处理完了,就是最后一帧的概念,多久以后服务端还没有收到客户端断开的标志,那么服务断就主动发起断开。所以一般服务端流式要做到以下两点:

  1. 流结束标志
  2. 定时器(最重要)

实现

Talk is cheap, Show me the code.

proto协议设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
syntax = "proto3";

package protocol;

message Request {
string msg = 1;
int32 times = 2;
bool last = 3;
}

message Response {
string reply = 1;
int32 index = 2;
bool last = 3;
}

service KeJiInterface {
rpc Say(stream Request) returns (stream Response) {}
rpc ServerStream(Request) returns (stream Response) {}
rpc ClientStream(stream Request) returns (Response) {}
}
双向流
1
2


服务端单向流式
----------本文结束感谢您的阅读----------
xiaolong wechat
一只程序猿对世界的不完全理解