本文包括两方面:
1,grpc如何设置连接存活时间
2,如何在服务端检测连接是否存活
目录
你不希望这个连接一直存活下去,到了一定时间想让其强制关闭
或者是担心客户端异常退出但服务端无法感知时,服务端会认为客户端依旧存在,这时候就需要服务端主动持续进行健康检查。
源码中有这样一个结构体:
- // ServerParameters is used to set keepalive and max-age parameters on the
- // server-side.
- type ServerParameters struct {
- // MaxConnectionIdle is a duration for the amount of time after which an
- // idle connection would be closed by sending a GoAway. Idleness duration is
- // defined since the most recent time the number of outstanding RPCs became
- // zero or the connection establishment.
- MaxConnectionIdle time.Duration // The current default value is infinity.
- // MaxConnectionAge is a duration for the maximum amount of time a
- // connection may exist before it will be closed by sending a GoAway. A
- // random jitter of +/-10% will be added to MaxConnectionAge to spread out
- // connection storms.
- MaxConnectionAge time.Duration // The current default value is infinity.
- // MaxConnectionAgeGrace is an additive period after MaxConnectionAge after
- // which the connection will be forcibly closed.
- MaxConnectionAgeGrace time.Duration // The current default value is infinity.
- // After a duration of this time if the server doesn't see any activity it
- // pings the client to see if the transport is still alive.
- // If set below 1s, a minimum value of 1s will be used instead.
- Time time.Duration // The current default value is 2 hours.
- // After having pinged for keepalive check, the server waits for a duration
- // of Timeout and if no activity is seen even after that the connection is
- // closed.
- Timeout time.Duration // The current default value is 20 seconds.
- }
其中defaultMaxConnectionIdle、MaxConnectionAge、MaxConnectionAgeGrace默认均为无穷大
defaultMaxConnectionIdle:默认的最大空闲连接数
MaxConnectionAge:默认的连接最大年龄
MaxConnectionAgeGrace:MaxConnectionAgeGrace是 MaxConnectionAge之后的一个附加时间段,之后连接将被强制关闭。
可以看出来MaxConnectionAge和MaxConnectionAgeGrace是一组同类型参数;
那么无穷大到底是多少呢?
- defaultMaxConnectionIdle = infinity
- defaultMaxConnectionAge = infinity
infinity是什么?
- infinity = time.Duration(math.MaxInt64)
- MaxInt64 = 1<<63 - 1
也就是说如果你不人为的设置,且连接没有因外界因素被迫中断,正常情况下将一直无限存在;
Time:会ping客户端以查看传输是否仍然存在,如果设置的值低于1s,则将使用最小值1s,不设置也是无穷大,无穷大意味着一直不会ping。
Timeout:在ping进行keepalive检查后,服务器会等待一段时间Timeout,即使在连接关闭之后也没有看到任何活动。默认值是2小时。
那么问题就可以解决了,只需设置最后两个参数即可。
如何设置?
如果你用过grpc,你一定见过grpc.NewServer()
可以看看它的参数:
func NewServer(opt ...ServerOption) *Server {}
那么ServerOption都可以设置哪些功能?作者已经抠出来了,如下
- type serverOptions struct {
- creds credentials.TransportCredentials
- codec baseCodec
- cp Compressor
- dc Decompressor
- unaryInt UnaryServerInterceptor
- streamInt StreamServerInterceptor
- chainUnaryInts []UnaryServerInterceptor
- chainStreamInts []StreamServerInterceptor
- inTapHandle tap.ServerInHandle
- statsHandler stats.Handler
- maxConcurrentStreams uint32
- maxReceiveMessageSize int
- maxSendMessageSize int
- unknownStreamDesc *StreamDesc
- keepaliveParams keepalive.ServerParameters
- keepalivePolicy keepalive.EnforcementPolicy
- initialWindowSize int32
- initialConnWindowSize int32
- writeBufferSize int
- readBufferSize int
- connectionTimeout time.Duration
- maxHeaderListSize *uint32
- headerTableSize *uint32
- numServerWorkers uint32
- }
我们经常用到的比如creds可以实现TLS认证、streamInt实现拦截器、keepaliveParams就是用来健康检查的;
经过一系列先分析观察,最终这样即可(grpc.Creds(creds)为增加的认证操作,可忽略):
- grpc.NewServer(grpc.Creds(creds), grpc.KeepaliveParams(keepalive.ServerParameters{
- Time: 20 * time.Second, // 每隔10秒ping一次客户端
- Timeout: 5 * time.Second, // 等待5秒ping再次确认,则认为连接已死
- })), nil
含义如下:每隔20秒ping一次客户端,若回包在5s内返回则认为正常,否则连接将被回收。
那么如何监听检查结果呢?
case <-stream.Context().Done()
该通道如读到值则立即停止当前逻辑即可。
也一样哦,提供了ClientParameters参数:
- conn, err := grpc.Dial(target, grpc.WithTransportCredentials(cert), grpc.WithKeepaliveParams(keepalive.ClientParameters{
- Time: 20 * time.Second,
- Timeout: 5 * time.Second,
- PermitWithoutStream: false,
- }))