专栏首页大猪的笔记grpc 检测客户端连接是否存在

grpc 检测客户端连接是否存在

默认情况下,服务端是没有检测客户端连接是否存活的。 如果因为网络抖动,客户端退出,此时客户端会向服务端发送一个Fin_wait2的消息。但这个消息如果丢失,服务端将长期认为客户端“仍然存在”,即使此时客户端已经退出。 为了解决这个问题,grpc服务端在启动的时候,可以传入keepalive参数,原理是:每隔N秒ping客户端,当客户端无法ping通的时候,服务端会主动断开连接。代码如下:

var kasp = keepalive.ServerParameters{
            Time:    5 * time.Second, // Ping the client if it is idle for 5 seconds to ensure the connection is still active
            Timeout: 1 * time.Second, // Wait 1 second for the ping ack before assuming the connection is dead
        }

lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
    log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer(grpc.KeepaliveParams(kasp))

pb.RegisterHelloServer(s, &svc{})
if err := s.Serve(lis); err != nil {
    log.Fatalf("failed to serve: %v", err)
}

上面的代码表明,每隔5s ping一次客户端,并且回包必须在1s内返回。否则连接将被回收。 服务端的处理代码可以写成这样:

func (s *svc) HelloStream(stream pb.Hello_HelloStreamServer) error {
    now := time.Now().Unix()
    log.Println("enter stream", now)

    req, err := stream.Recv()
    if err != nil {
        return err
    }
    name := req.Greetings

loop:
    for {
        out := new(pb.HelloRsp)
        out.Resp = fmt.Sprintf("hello,%v", name)
        sendctx, sendcancel := context.WithCancel(context.Background())
        go func() {
            err := stream.Send(out) // 在协程中send,使得context.Done响应能被处理
            if err != nil {
                log.Println(err)
            }
            sendcancel()
        }()

        select {
        case <-sendctx.Done():
        case <-stream.Context().Done()://当keepalive连接超时,这里的逻辑被执行,服务端退出
            log.Println("client closed")
            break loop
        }
        time.Sleep(time.Second)
    }
    log.Println("exit stream")
    return nil
}

真的隐蔽啊。真的坑啊。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • go:文件按行读取

    超级大猪
  • go: 插件系统

    参考文章: https://toutiao.io/posts/adjoci/preview

    超级大猪
  • 容器:namespace文件隔离实现

    参考资料: 自己动手写docker-4 https://juejin.im/post/5c2b495af265da6134388142 使用golang理...

    超级大猪
  • SaaS-常见的认证机制

    HTTP Basic Auth简单点说明就是每次请求API时都提供用户的username和password,简言之,Basic Auth是配合RESTful A...

    cwl_java
  • ICLR 2020 | 告别死记硬背,元学习才能学会学习

    本文介绍的是 ICLR 2020 spotlight 论文《Meta-Learning without Memorization》(无记忆的元学习),来自德克萨...

    AI科技评论
  • 随着全球运营商围绕开源网络展开合作, LF Networking持续发展

    2018年5月30日,在旧金山举办的促进开放网络项目的协作和卓越运营的LF网络基金会(LF Networking Fund,LFN)今天宣布,主流电信服务提供商...

    SDNLAB
  • 网络——Wireshark工具

    官网下载安装:https://www.wireshark.org/download.html 基础抓包: 效果查看:

    瑞新
  • 一个开源的营销自动化软件——Mautic

    营销自动化这个东西已经出现了有十多年来,最近两年又不断被提起,大部分是厂家的内容,可以看看近几年的百度指数:

    GA小站
  • ApiBoot Logging忽略路径不进行采集日志

    ApiBoot Logging支持排除指定路径不参与日志的采集,当我们的服务集成actuator时,会不断的重复调用内置的路径导致大量采集到一些无关业务的日志信...

    恒宇少年
  • JS魔法堂:LINK元素深入详解

    一、前言                               我们一般使用方式为 <link type="text/css" rel="styleshe...

    ^_^肥仔John

扫码关注云+社区

领取腾讯云代金券