问一个心跳检测的问题

2015-12-04 10:41:19 +08:00
 SparkMan

现在需要在 client 和 server 间做心跳检测,常见的方法是 server 提供一个方法, client 每隔一定时间去 call 一下,看返回状态,如果正常返回则说明成功。
但是,假设我现在不能在 server 提供这个方法,我只能用 socket 去检测 server 是否还活着, 那么现在我用的是每次创建一个 socket ,然后发送 socket.sendUrgentData(0xff); 没报错我就认为 server 活着。
我想问一下, 1 、如果每次都创建一个新的 socket ,性能有多大消耗?会不会每次都占用 server 的连接数活着端口? 2 、大家一般这种情况下的心跳是怎么做的? 3 、如果维持一个长连接的 socket ,即设置 keepliave 为 true ,但是会报错 Broken pipe at java.net.PlainSocketImpl.socketSendUrgentData

4263 次点击
所在节点    Java
16 条回复
xiamx
2015-12-04 10:51:11 +08:00
可以选择用一个成熟的 failure detection library ,省去造轮子的过程

如果你需要去造这个轮子...那可以默认为 scalability 和 performence 不重要。创建 socket 性能消耗很小,反正你又不是每秒钟创建 100 个。
> 会不会每次都占用 server 的连接数
肯定会
> 大家一般这种情况下的心跳是怎么做的
用成熟的库
> 如果维持一个长连接的 socket ,即设置 keepliave 为 true ,但是会报错 Broken pipe at java.net.PlainSocketImpl.socketSendUrgentData
不建议单独维持一个 tcp connection 只用来做 heartbeat ,代价略高
hao123yinlong
2015-12-04 10:59:36 +08:00
心跳机制的两个目的:

1. 保活
2.检测断连

所以你的第一个问题本身就是个问题,为了保持当前连接,创建一个新的连接?

从你的问题描述还没搞明白你是客户端开发人员仅想知道如何开发心跳流程,还是作为整个心跳机制流程的设计者如何来设计
odirus
2015-12-04 11:20:44 +08:00
要不你简单点?在 server 端加个很简单的 HTTP 服务?
SparkMan
2015-12-04 11:22:43 +08:00
@xiamx 求推荐一个成熟的库
SparkMan
2015-12-04 11:24:10 +08:00
@hao123yinlong 做的是类似 负载均衡的一个东西,需要检测代理的 server 列表是不是有的挂了,挂了就从轮询列表中移除
SparkMan
2015-12-04 11:25:35 +08:00
@odirus 已经说过,不方便在 server 端加代码,我只想简单检测这个 server 在某个端口是不是还活着
odirus
2015-12-04 11:36:09 +08:00
@SparkMan 看你自己吧,想要客户端检测服务端就开始造轮子吧。

以下是废话,可以不看。

不过还是推荐一个服务端软件 haproxy ,检测到某台服务器不可用之后,自动移除。这样的软件很多,自己找。
为啥我不推荐在客户端检测,( 1 )集群没法统一调度( 2 )客户端检测毕竟是有一个检测间隔的,容易造成这一小段时间间隙内的大量连接失败。
sunjiayao
2015-12-04 11:42:37 +08:00
@odirus haproxy 我们也在用。。 可惜的是只能检测是否存活 无法检测可用性
odirus
2015-12-04 11:45:04 +08:00
@sunjiayao 恩。。。不错,头像很有个性
nicktogo
2015-12-04 11:47:42 +08:00
不知道 mqtt 这类消息服务适不适合?(我就随手回复下
xiamx
2015-12-04 12:17:34 +08:00
客户端检查主要问题就是 not scalable (1 个客户端会每 N 秒发 1 个消息,那 100000 个客户端就是 100000 个消息)不过按照楼主目前的考虑,真的是可以用 socket.sendUrgentData(0xff)来 hack 出简单的 failure detection 。 Scalable failure detection 普遍的做法是用 gossip protocol ( https://www.cs.cornell.edu/~asdas/research/dsn02-swim.pdf),这样来说在不改变 server 代码的前提下是不可能的。
hao123yinlong
2015-12-04 12:19:01 +08:00
@SparkMan ” 只想简单检测这个 server 在某个端口是不是还活着 “

个人理解你是要开发类似 zk 这类的注册中心,需要维护 server 列表 。

推荐策略:

zk - server 长连接, server 主动连接 zk 。
zk 主动向 server 发心跳数据包 , server 接受到心跳后 回复心跳 数据包
zk 监测读超时 ,读超时事件触发后移除该 server ,关闭连接。

推荐 netty 框架 ,有相关读、写、读写超时监测 及事件回调可以满足
mcfog
2015-12-04 12:42:59 +08:00
服务端改不了如果客户端能改的话也好办,做个中心节点(配合本地 agent 做 cache),客户端每次连接通过业务代码向中心节点请求服务器的 IP 端口,连接以后跑业务逻辑,如果连接/业务逻辑失败就上报失败给中心,如果成功也上报成功 /耗时,然后中心节点就可以统计、负载均衡、故障告警什么的了。发现谁慢就少分配活给他,失败率高过阈值就认为倒了 告警+踢出,也可以对被踢出的节点偶尔试一下来实现自动恢复什么的

这套东西中心节点压力大(或者靠 agent 缓存的话, agent 和中心之间的逻辑复杂),但优点正是无视 server 到底是什么,无论是数据库, redis , mq ,还是自己的 server ,只要是拿 IP 端口去连的东西都一样用
SparkMan
2015-12-04 13:06:00 +08:00
@xiamx 可能是我没表述清楚,我所说的 clinet 其实是另外一个服务,并不是真的客户端,数量很少,只有几个
SparkMan
2015-12-04 13:07:06 +08:00
@hao123yinlong 恩, zk 、 netty 都在用。你是指 new IdleStateHandler(0, 0, 0) 这个吗?
hao123yinlong
2015-12-04 13:51:50 +08:00
@SparkMan 恩额

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/241067

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX