现在需要在 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
1
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 ,代价略高 |
2
hao123yinlong 2015-12-04 10:59:36 +08:00
心跳机制的两个目的:
1. 保活 2.检测断连 所以你的第一个问题本身就是个问题,为了保持当前连接,创建一个新的连接? 从你的问题描述还没搞明白你是客户端开发人员仅想知道如何开发心跳流程,还是作为整个心跳机制流程的设计者如何来设计 |
3
odirus 2015-12-04 11:20:44 +08:00
要不你简单点?在 server 端加个很简单的 HTTP 服务?
|
5
SparkMan OP @hao123yinlong 做的是类似 负载均衡的一个东西,需要检测代理的 server 列表是不是有的挂了,挂了就从轮询列表中移除
|
7
odirus 2015-12-04 11:36:09 +08:00
@SparkMan 看你自己吧,想要客户端检测服务端就开始造轮子吧。
以下是废话,可以不看。 不过还是推荐一个服务端软件 haproxy ,检测到某台服务器不可用之后,自动移除。这样的软件很多,自己找。 为啥我不推荐在客户端检测,( 1 )集群没法统一调度( 2 )客户端检测毕竟是有一个检测间隔的,容易造成这一小段时间间隙内的大量连接失败。 |
10
nicktogo 2015-12-04 11:47:42 +08:00 via Android
不知道 mqtt 这类消息服务适不适合?(我就随手回复下
|
11
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 代码的前提下是不可能的。
|
12
hao123yinlong 2015-12-04 12:19:01 +08:00
@SparkMan ” 只想简单检测这个 server 在某个端口是不是还活着 “
个人理解你是要开发类似 zk 这类的注册中心,需要维护 server 列表 。 推荐策略: zk - server 长连接, server 主动连接 zk 。 zk 主动向 server 发心跳数据包 , server 接受到心跳后 回复心跳 数据包 zk 监测读超时 ,读超时事件触发后移除该 server ,关闭连接。 推荐 netty 框架 ,有相关读、写、读写超时监测 及事件回调可以满足 |
13
mcfog 2015-12-04 12:42:59 +08:00
服务端改不了如果客户端能改的话也好办,做个中心节点(配合本地 agent 做 cache),客户端每次连接通过业务代码向中心节点请求服务器的 IP 端口,连接以后跑业务逻辑,如果连接/业务逻辑失败就上报失败给中心,如果成功也上报成功 /耗时,然后中心节点就可以统计、负载均衡、故障告警什么的了。发现谁慢就少分配活给他,失败率高过阈值就认为倒了 告警+踢出,也可以对被踢出的节点偶尔试一下来实现自动恢复什么的
这套东西中心节点压力大(或者靠 agent 缓存的话, agent 和中心之间的逻辑复杂),但优点正是无视 server 到底是什么,无论是数据库, redis , mq ,还是自己的 server ,只要是拿 IP 端口去连的东西都一样用 |
15
SparkMan OP @hao123yinlong 恩, zk 、 netty 都在用。你是指 new IdleStateHandler(0, 0, 0) 这个吗?
|
16
hao123yinlong 2015-12-04 13:51:50 +08:00
@SparkMan 恩额
|