关于golang socket 编程的 连接池和长连接问题

cyxr001 · 2020-05-09 10:47:25 · 1390 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2020-05-09 10:47:25 的主题,其中的信息可能已经有所发展或是发生改变。

我在客户端维护一个tcp连接池,用channel实现的,并每一个设置超时时间,如果当超时时间过了,我客户端调用close 关闭这个连接,服务端的这个连接还存在吗?还是说要等服务端的超时,系统自动回收?

服务端是否要发心跳?如果发心跳怎么处理?我客户端的连接都保存在channel当中,发心跳字段的话,好像没办法处理吧? 不发的话会停止长连接?


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1390 次点击  
加入收藏 微博
6 回复  |  直到 2020-05-09 16:48:04
mlzhou
mlzhou · #1 · 5年之前

可以先看看网络编程 tcp的握手,服务端的桥看看这个应该就明白了。

每个连接都是独立处理 你的桥都断了,怎么发心跳包过去。 你遍历另外的连接,通过这个桥告诉客户端,你有一个桥Id断了,让它重建。 或者你客户端设置一个断连重连过程。

cyxr001
cyxr001 · #2 · 5年之前
mlzhoumlzhou #1 回复

可以先看看网络编程 tcp的握手,服务端的桥看看这个应该就明白了。 每个连接都是独立处理 你的桥都断了,怎么发心跳包过去。 你遍历另外的连接,通过这个桥告诉客户端,你有一个桥Id断了,让它重建。 或者你客户端设置一个断连重连过程。

谢谢你的回答,我可能没说清楚。我再描述下问题。主要是不太清楚需不需要发送心跳包,以及哪边发送

1.golang的tcp编程里面,对于每一个conn,两边都有close方法,我是不是需要两边都调用close方法,才能正常挥手? 如果我只调用了client的close,服务端的这个conn是否正常关闭了,还是说长期保有占用资源?

2.心跳是在两边都不关闭的时候的发送,但是如果我服务端发送的话,客户端的conn都在channel里面,无法处理收到消息吧? 我应该定时遍历channel去处理心跳包吗?还是说不需要发心跳包?

3.还有一个方法,client 从channel获取conn的时候就发送心跳包检测,有反应才返回,无反应的话就重新建立个连接返回?这样好像代价比较大

求大佬看看。。。

mlzhou
mlzhou · #3 · 5年之前

1.一般来说,是客户端发起连接建立,客户端结束连接,除非服务端看你不爽,想要踢掉你,不然服务端不应该设计为主动close. 资源问题要看你服务端是如何保留这个连接的,例如有一个连接对象专门存储tcpConn,那你要处理掉这个对象,另外你可以在收到客户端close的时候服务端的调用服务端的tcpconn.close()也是没有问题,至于net.TCPConn这个对象应该是由gc处理掉了。 2.你这个chan的连接池不应该就直接是net.TCPConn这个类型吧,每一条连接不是有for循环的read么。 另外你心跳包的作用是什么,对应的是一条连接?还是连接池?
3.一般连接池 不应该是 get一条连接发送,超时,换一条么

cyxr001
cyxr001 · #4 · 5年之前
mlzhoumlzhou #3 回复

1.一般来说,是客户端发起连接建立,客户端结束连接,除非服务端看你不爽,想要踢掉你,不然服务端不应该设计为主动close. 资源问题要看你服务端是如何保留这个连接的,例如有一个连接对象专门存储tcpConn,那你要处理掉这个对象,另外你可以在收到客户端close的时候服务端的调用服务端的tcpconn.close()也是没有问题,至于*net.TCPConn这个对象应该是由gc处理掉了。 2.你这个chan的连接池不应该就直接是*net.TCPConn这个类型吧,每一条连接不是有for循环的read么。 另外你心跳包的作用是什么,对应的是一条连接?还是连接池? 3.一般连接池 不应该是 get一条连接发送,超时,换一条么

有点明白了。

  1. 服务端没有封装net.Conn对象,客户端close的话,就算服务端不调用close,也会被gc处理掉,但是不知道这个gc会在多久回收服务端无用的net.Conn。 如果服务端封装net.Conn对象,将他储存了,那是不是应该由服务端定时发送请求,检测客户端对应conn是否关闭了,然后清理掉?

2.心跳包就是用来检测对面是不是还保留了连接,每一个连接都发送心跳。你的意思是不需要发送心跳,结合1,3说的,超时就关闭客户端,不需要管服务端掉不掉close,换一条连接就行的意思么?

mlzhou
mlzhou · #5 · 5年之前

你做连接池的目的不就是保证能和服务端的正常通信么,只要当前有一条可用就行吧。 只要连接断了,就把相应的封装对象从你的管理连接表里面移除就行,等着客户端新建连接,没必要再通知客户端,客户端有自己的检测机制,它是能识别到这个连接断的。由它自己处理相应的逻辑。 一般服务端肯定是要有一个管理连接的对象存在的。

心跳包一般来说就是看客户端能不能达到服务端,在服务端崩溃的情况下就收不到了,所以用来确认两端的状态。还有做连接池的目的可能是当前连接忙,需要选择另外一条连接。

cyxr001
cyxr001 · #6 · 5年之前

1.我刚才试了一下,好像还是得两边都关闭才行,我客户端生成连接池后,然后服务端重启,按理说原来的连接不能发东西了,但是我客户端用原来的连接write,不会返回error,但是服务端那边也不会返回值。就是说,服务端应该是处于close_wait的阶段,我不能靠write来判断这个连接可不可用,连着read一起判断才行。。。所以还是需要心跳检测?

2.服务端怎么管理连接对象? 客户端请求过来,我怎么快速取出对应的连接对象呢?

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传