1. GRPC keepalive 的相关知识
参照这个连接
// ClientParameters is used to set keepalive parameters on the client-side.
// These configure how the client will actively probe to notice when a
// connection is broken and send pings so intermediaries will be aware of the
// liveness of the connection. Make sure these parameters are set in
// coordination with the keepalive policy on the server, as incompatible
// settings can result in closing of connection.
type ClientParameters struct {
// After a duration of this time if the client doesn't see any activity it
// pings the server to see if the transport is still alive.
// If set below 10s, a minimum value of 10s will be used instead.
Time time.Duration // The current default value is infinity.
// After having pinged for keepalive check, the client 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.
// If true, client sends keepalive pings even with no active RPCs. If false,
// when there are no active RPCs, Time and Timeout will be ignored and no
// keepalive pings will be sent.
PermitWithoutStream bool // false by default.
}
// 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.
}
grpc client 的keepalive 用来检测 client 创建的grpc channel 连接是不是可用的,如果超时,就会关掉这个channel 的连接
grpc server 的keepalive 用来检测 server 创建的grpc channel 连接是不是可用的,如果超时,就会关掉这个channel 的连接
在这里还需要特别注意一个问题, grpc client 的keepalive 的 时间设定 需要在server 允许范围内,否则,server 会认为你是捣蛋的,给你发送一个GOAWAY 消息,把和client 的连接强制关掉
这部分,具体我们来看grpc-go的相关定义:
// EnforcementPolicy is used to set keepalive enforcement policy on the
// server-side. Server will close connection with a client that violates this
// policy.
type EnforcementPolicy struct {
// MinTime is the minimum amount of time a client should wait before sending
// a keepalive ping.
MinTime time.Duration // The current default value is 5 minutes.
// If true, server allows keepalive pings even when there are no active
// streams(RPCs). If false, and client sends ping when there are no active
// streams, server will send GOAWAY and close the connection.
PermitWithoutStream bool // false by default.
}
够清晰吧,所以在grpc server 端需要设置这个参数,来和client 端作匹配!
如果两者不匹配就会出现下面的错误
closing transport due to: connection error: desc = “error reading from server: EOF”, received prior goaway: code: ENHANCE_YOUR_CALM, debug data: “too_many_pings”
意思就是server 端说:”兄弟,你ping 的手速太快了,哥撑不住了,不带你玩了,滚吧!“。 说完就把连接诶给断了。
2. Java grpc server 的一些注意事项
如果要用java 写一个grpc server, 此时假定需要设定上面所述的匹配,应该要怎么做?
刚开始我们用的和官方demo一样的方式(io.grpc.ServerBuilder)创建server,但发现这个类io.grpc.ServerBuilder压根没有设置这个keepalive 参数的接口,后来在github 上看到这个issue:
https://github.com/grpc/grpc-java/issues/8991
NettyServerBuilder has the appropriate API. You’d need to use the APIs io.grpc.netty.NettyServerBuilder (and swap to grpc-netty) or the questionable io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder (to continue with grpc-netty). Neither option is great as grpc-netty-shaded is much preferred over grpc-netty but nominally it doesn’t really expose a public API.
As a short-term “get it working.” Using io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder is probably fair. But we need to add the keepalive methods to io.grpc.ServerBuilder.
确实NettyServerBuilder 有更丰富的接口,包含了许多设置keepalive 的api 接口。
其中就有限制client 的keepalive 的API, 让我们看下源码:
/**
* Specify the most aggressive keep-alive time clients are permitted to configure. The server will
* try to detect clients exceeding this rate and when detected will forcefully close the
* connection. The default is 5 minutes.
*
* <p>Even though a default is defined that allows some keep-alives, clients must not use
* keep-alive without approval from the service owner. Otherwise, they may experience failures in
* the future if the service becomes more restrictive. When unthrottled, keep-alives can cause a
* significant amount of traffic and CPU usage, so clients and servers should be conservative in
* what they use and accept.
*
* @see #permitKeepAliveWithoutCalls(boolean)
* @since 1.3.0
*/
public NettyServerBuilder permitKeepAliveTime(long keepAliveTime, TimeUnit timeUnit) {
checkArgument(keepAliveTime >= 0, "permit keepalive time must be non-negative: %s",
keepAliveTime);
permitKeepAliveTimeInNanos = timeUnit.toNanos(keepAliveTime);
return this;
}
Okay, 祝您好运!