《一个 Go 程序系统线程暴涨的问题》结论
2016-09-18 20:39
211 查看
原文地址:https://zhuanlan.zhihu.com/p/22474724
作者的结论没写好,我来说两句。。
结论:
Docker swarm自己有个函数,叫setTcpUserTimeout,这个函数调用了conn.File()方法,将tcp的fd变成了blocking,而且没有关闭对应的fd。相当于每次设定tcpUserTimeout参数,再去read一下fd,都会产生一个新的线程。因为老的线程在读fd,而fd被设置成blocking了,于是golang的运行时只好再开一个新的。
解决方法:
不要用swarm的这个方法,或者提交到上游让swarm fixed掉,或者自己调用SetsockoptInt……
好奇八卦了一下TCP_USER_TIMEOUT是什么:根据RFC 5482,这个选项是用来跟对端沟通TCP超时时间的。顺带看了一下,有关TCP超时的RFC还包括:[RFC0793] [RFC1122]。之前,TCP有类似的超时选项TCP Keepalive。但是,TCP Keepalive是一个不建议打开的选项。因为委员会觉得这样会浪费带宽,引起不必要的网络中断。说白了,TCP是一组计时器组成的状态机,设计者是希望中间的电路中断、重新路由之类的变动,不会影响到两端的TCP状态。
在游戏开发这块,一般都会做心跳机制。目的是为了让服务器的资源尽早释放,以支撑更多玩家。TCP Keepalive和上述的TCP_USER_TIMEOUT,勉强能完成任务。但是,不是所有平台都支持keepalive,所以只好放在应用层来做。目前用的心跳包是30秒一个的。太频繁的心跳,只会浪费流量,没有意义。同时,不断发送小数据包,会让手机的芯片持续处于高功率状态,游戏变得更加耗电。如果游戏本身能允许一定时间内的不一致,网络部分就能够更加灵活了。
比如有玩家在地铁里进行游戏,列车行驶在站与站之间的时候,网络信号是非常弱的。如果能够将协议都变成异步的,游戏不需要等待上一条协议结果,就能继续进行。那么就可以定时上传操作日志,甚至可以模仿安卓的doze机制,发送超时就先睡眠一下,过一段时间再尝试。这样对电池的使用会更加友好,对地铁信号的适应性也会增强。只是游戏需要制定一个硬性同步的点,到了这个点一定要将所有日志同步到服务器,不然就暂时禁止玩家操作,直到同步成功为止。这个点处理的好,体验会提升不少。
作者的结论没写好,我来说两句。。
结论:
Docker swarm自己有个函数,叫setTcpUserTimeout,这个函数调用了conn.File()方法,将tcp的fd变成了blocking,而且没有关闭对应的fd。相当于每次设定tcpUserTimeout参数,再去read一下fd,都会产生一个新的线程。因为老的线程在读fd,而fd被设置成blocking了,于是golang的运行时只好再开一个新的。
解决方法:
不要用swarm的这个方法,或者提交到上游让swarm fixed掉,或者自己调用SetsockoptInt……
好奇八卦了一下TCP_USER_TIMEOUT是什么:根据RFC 5482,这个选项是用来跟对端沟通TCP超时时间的。顺带看了一下,有关TCP超时的RFC还包括:[RFC0793] [RFC1122]。之前,TCP有类似的超时选项TCP Keepalive。但是,TCP Keepalive是一个不建议打开的选项。因为委员会觉得这样会浪费带宽,引起不必要的网络中断。说白了,TCP是一组计时器组成的状态机,设计者是希望中间的电路中断、重新路由之类的变动,不会影响到两端的TCP状态。
在游戏开发这块,一般都会做心跳机制。目的是为了让服务器的资源尽早释放,以支撑更多玩家。TCP Keepalive和上述的TCP_USER_TIMEOUT,勉强能完成任务。但是,不是所有平台都支持keepalive,所以只好放在应用层来做。目前用的心跳包是30秒一个的。太频繁的心跳,只会浪费流量,没有意义。同时,不断发送小数据包,会让手机的芯片持续处于高功率状态,游戏变得更加耗电。如果游戏本身能允许一定时间内的不一致,网络部分就能够更加灵活了。
比如有玩家在地铁里进行游戏,列车行驶在站与站之间的时候,网络信号是非常弱的。如果能够将协议都变成异步的,游戏不需要等待上一条协议结果,就能继续进行。那么就可以定时上传操作日志,甚至可以模仿安卓的doze机制,发送超时就先睡眠一下,过一段时间再尝试。这样对电池的使用会更加友好,对地铁信号的适应性也会增强。只是游戏需要制定一个硬性同步的点,到了这个点一定要将所有日志同步到服务器,不然就暂时禁止玩家操作,直到同步成功为止。这个点处理的好,体验会提升不少。
相关文章推荐
- Python:通过自定义系统级快捷键来控制程序开始或停止记录日志(使用小技巧解决一个貌似无解的问题)
- 设计一个模块,功能是列出系统中所有内核线程的程序名、PID号和进程状态。
- Python:通过自定义系统级快捷键来控制程序开始或停止记录日志(使用小技巧解决一个貌似无解的问题)
- 问题阐述: 本人使用mini6410开发了一个sqlite数据库的程序,在mini6410的linux系统下已经能够成功运行了。因为Android使用的也是linux内核,所以我想当然的认为按照同样
- 【笔记】unix系统下,多个静态库链接到一个可执行程序后,执行时出现莫名奇妙的问题
- 程序退到后台的时候,所有线程被挂起,系统回收所有的socket资源问题及解决方案
- 问题: 写一个多线程程序实现铁路卖票系统,4个窗口同时售票,线程同步
- G-Share 1.5beta3:一个php脚本的程序,可以把你gmail做为文档共享系统(下载系统)
- 解决一个以前写的VB程序的安装问题
- asp文章系统的一个小问题
- 如何把一个程序注册成系统服务
- 有关终止线程的一个问题
- 这个问题让我疯掉!用oledbcommand执行一个插入一条记录的程序,到现在也没有解决!
- 编写一个生产者,消费者多线程程序,一个线程随机产生数据,另一个线程显示所产生的数据.
- weblogic程序移植到jboss上的一个问题解决方法,j2ee,原创
- 保证系统中只运行一个程序实例
- VS2005多线程程序在IDE下调试的一个问题
- 如何解决ASP.NET程序安装到繁体系统上的乱码问题
- 一个解决Jsp/serlvet中的中文问题的程序
- 一个NT系统下的DOS命令运行程序