C# udp如何对多用户进行心跳检测

C# udp如何对多用户进行心跳检测,第1张

udp的广播形式吧

既然是心跳检测,个人认为是服务器以广播的形式向客户端发送心跳报文之类的,然后收到客户端的回复,如果有回复,客户端正常,没回复,则不正常。

或者客户端定时向服务器发送心跳包,如果服务器长时间没有收到则客户端不正常。

希望对你有帮助。

一、服务注册中心的由来

假如没有服务注册中心,我们会干些什么事情呢?

在传统行业的项目架构中以下的方案最为常见了:

这种架构开发、部署都是最简单的,一般适用于中小企业访问量并不是太多的情况下,各个系统服务一台机器就搞定了。系统之间的调用也是拿到对方的IP+PORT直接连接。

接下来可能因为应用B开始访问量大了,单台机器已经不能满足我们的需求,于是一些反向代理工具应运而出,其中比较常见的有Apache、Nigix,架构演变为:

相比之前的应用B的单台机器访问,这种nginx代理的方式减轻了服务器的压力,但是可能会出现Nginx挂了,那么整个服务也不可用,于是又来了这么一套架构:

这样看方案算是完美了吧。然后事情并不是想象的那么一帆风顺,这还只是应用A调用一个应用B,如果应用A调用的可能是应用B、C、D、E,这种完全就不知道他后面到底还想干嘛,这种架构看似可以,但是绝对会累死运维的(nginx的配置将会非常混乱,直接导致运维不干了)。

服务注册中心干些什么事情呢?

上面提到的那种靠人力(主要是运维干的事情)比较繁琐,还不好维护,有这么几点不方便:应用服务的地址变了、双十一搞活动服务器新增等等。那么我们可以有这么的一种架构:

    服务注册中心主要是维护各个应用服务的ip+port列表,并保持与各应用服务的通讯,在一定时间间隔内进行心跳检测,如果心跳不能到达则对服务IP列表进行剔除,并同时通知给其它应用服务进行更新。同样要是有新增的服务进来,应用服务会向注册中心进行注册,服务注册中心将通知给其它应用进行更新。每个应用都有需要调用对应应用服务的地址列表,这样在进行调用时只要处理客户负载杂均衡即可。

二、微服务注册中心

1Zookeeper

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

上面的话直接摘抄的内容,国内很多公司做分布式开发最初的选型大部分都是采用dubbo框架。dubbo框架注册中心主要使用zookeeper。zookeeper服务端与客户端的底层通讯为netty。zookeeper采用CAP理论中的CP,一般集群部署最少需要3台机器。

2Euraka

先来看一下euraka的架构图:

Register:服务注册

当Eureka客户端向Eureka Server注册时,它提供自身的元数据,比如IP地址、端口,运行状况指示符URL,主页等。

Renew:服务续约

Eureka客户会每隔30秒发送一次心跳来续约。 通过续约来告知Eureka Server该Eureka客户仍然存在,没有出现问题。 正常情况下,如果Eureka Server在90秒没有收到Eureka客户的续约,它会将实例从其注册表中删除。 建议不要更改续约间隔。

Fetch Registries:获取注册列表信息

Eureka客户端从服务器获取注册表信息,并将其缓存在本地。客户端会使用该信息查找其他服务,从而进行远程调用。该注册列表信息定期(每30秒钟)更新一次。每次返回注册列表信息可能与Eureka客户端的缓存信息不同, Eureka客户端自动处理。如果由于某种原因导致注册列表信息不能及时匹配,Eureka客户端则会重新获取整个注册表信息。 Eureka服务器缓存注册列表信息,整个注册表以及每个应用程序的信息进行了压缩,压缩内容和没有压缩的内容完全相同。Eureka客户端和Eureka 服务器可以使用JSON / XML格式进行通讯。在默认的情况下Eureka客户端使用压缩JSON格式来获取注册列表的信息。

Cancel:服务下线

Eureka客户端在程序关闭时向Eureka服务器发送取消请求。 发送请求后,该客户端实例信息将从服务器的实例注册表中删除。该下线请求不会自动完成,它需要调用以下内容:

DiscoveryManagergetInstance()shutdownComponent();

Eviction 服务剔除

在默认的情况下,当Eureka客户端连续90秒没有向Eureka服务器发送服务续约,即心跳,Eureka服务器会将该服务实例从服务注册列表删除,即服务剔除。

自我保护机制:

既然Eureka Server会定时剔除超时没有续约的服务,那就有可能出现一种场景,网络一段时间内发生了 异常,所有的服务都没能够进行续约,Eureka Server就把所有的服务都剔除了,这样显然不太合理。所以,就有了 自我保护机制,当短时间内,统计续约失败的比例,如果达到一定阈值,则会触发自我保护的机制,在该机制下, Eureka Server不会剔除任何的微服务,等到正常后,再退出自我保护机制。自我保护开关(eurekaserverenableself-preservation: false)

3Consul

consul推荐的架构图:

Consul不像Euraka的部署那么简单,他是go语言开发的,需要运维单独部署,有提供java的客户端连接,采用的是CAP的CP。

4Nacos

    Euraka是Spring Cloud Netflix早期版本中推荐使用的,后来euraka10版本不再维护,euraka20已经闭源,导致很多新项目基于Spring Cloud Netflix 开发的选型变迁为Consul

Nacos是阿里开源的服务注册中心,它可以与spring cloud aliaba集成使用。

Nacos的官方介绍:

    Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您实现动态服务发现、服务配置管理、服务及流量管理。

    Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构(例如微服务范式、云原生范式)的服务基础设施。

Nacos 地图

Nacos 生态图

如 Nacos 全景图所示,Nacos 无缝支持一些主流的开源生态,例如

Spring Cloud

Apache Dubbo and Dubbo Mesh TODO

Kubernetes and CNCF TODO

三、服务注册与发现技术选型

以下是来自网上的一个分享:

除了上述的几种以外,笔者更推荐使用Nacos作为服务注册中心。

推荐理由:

Nacos服务注册表结构Map<namespace, Map<group::serviceName, Service>>采用多层次Map结构,控制的颗粒度更细,支持金丝雀模式发布,心跳同步机制也更快速,服务更新更及时。

心跳包,通常是客户端每隔一小段时间向服务器发送的一个数据包,通知服务器自己仍然在线,并传输一些可能有必要的数据。因按照一定的时间间隔发送,类似于心跳,所以叫做心跳包。事实上为了保持长连接,至于包的内容,是没有特别规定的,不过一般都是很小的包,或者只是包含包头的一个空包。

在TCP协议的机制里面,本身是存在有心跳包机制的,也就是TCP协议中的SO_KEEPALIVE,系统默认是设置2小时的心跳频率。需要用要用setsockopt将SOL_SOCKETSO_KEEPALIVE设置为1才是打开,并且可以设置三个参数tcp_keepalive_time/tcp_keepalive_probes/tcp_keepalive_intvl,分别表示连接闲置多久开始发keepalive的ACK包、发几个ACK包不回复才当对方死了、两个ACK包之间间隔多长。

TCP协议会向对方发一个带有ACK标志的空数据包(KeepAlive探针),对方在收到ACK包以后,如果连接一切正常,应该回复一个ACK;如果连接出现错误了(例如对方重启了,连接状态丢失),则应当回复一个RST;如果对方没有回复,服务器每隔多少时间再发ACK,如果连续多个包都被无视了,说明连接被断开了。

“心跳检测包”是属于TCP协议底层的检测机制,上位机软件只是解析显示网口的有用数据包,收到心跳包报文属于TCP协议层的数据,一般软件不会将它直接在应用层显示出来,所以看不到。以太网中的“心跳包”可以通过“以太网抓包软件”分析TCP/IP协议层的数据流看到。报文名称”TCP Keep-Alive”。

一些比较可靠的以太网转串口模块,都有心跳包的检测,比如致远电子的ZNE-100TL模块,配置“心跳包检测”间隔时间设为“10”秒,使用一款”wireshark”的抓包软件来实际查看下TCP/IP协议层“心跳包”数据。

Feign 是一个声明式的伪 HTTP 客户端,它使得写 HTTP 客户端变得更简单。使用 Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用 Feign 注解和 JAX-RS 注解。Feign 支持可插拔的编码器和解码器。Feign 默认集成了 Ribbon,Nacos 也很好的兼容了 Feign,默认实现了负载均衡的效果

在 hello-spring-cloud-alibaba-consumer 项目中增加 orgspringframeworkcloud:spring-cloud-starter-openfeign 依赖

通过 @EnableFeignClients 注解开启 Feign 功能

创建业务结构,通过 @FeignClient("服务名") 注解来指定调用哪个服务

通过浏览器访问 http://localhost:8080/feign/echo/hi

负载主机可以提供很多种负载均衡方法,也就是我们常说的调度方法或算法

Round Robin: 这种方法会将收到的请求循环分配到服务器集群中的每台机器,即有效服务器。如果使用这种方式,所有的标记进入虚拟服务的服务器应该有相近的资源容量 以及负载形同的应用程序。如果所有的服务器有相同或者相近的性能那么选择这种方式会使服务器负载形同。基于这个前提,轮循调度是一个简单而有效的分配请求 的方式。然而对于服务器不同的情况,选择这种方式就意味着能力比较弱的服务器也会在下一轮循环中接受轮循,即使这个服务器已经不能再处理当前这个请求了。 这可能导致能力较弱的服务器超载。

Weighted Round Robin: 这种算法解决了简单轮循调度算法的缺点:传入的请求按顺序被分配到集群中服务器,但是会考虑提前为每台服务器分配的权重。管理员只是简单的通过服务 器的处理能力来定义各台服务器的权重。例如,能力最强的服务器 A 给的权重是 100,同时能力最低的服务器给的权重是 50。这意味着在服务器 B 接收到第一个 请求之前前,服务器 A 会连续的接受到 2 个请求,以此类推。

Least Connection: 以上两种方法都没有考虑的是系统不能识别在给定的时间里保持了多少连接。因此可能发生,服务器 B 服务器收到的连接比服务器 A 少但是它已经超载,因为 服务器 B 上的用户打开连接持续的时间更长。这就是说连接数即服务器的负载是累加的。这种潜在的问题可以通过 “最少连接数” 算法来避免:传入的请求是根据每 台服务器当前所打开的连接数来分配的。即活跃连接数最少的服务器会自动接收下一个传入的请求。接本上和简单轮询的原则相同:所有拥有虚拟服务的服务器资源 容量应该相近。值得注意的是,在流量率低的配置环境中,各服务器的流量并不是相同的,会优先考虑第一台服务器。这是因为,如果所有的服务器是相同的,那么 第一个服务器优先,直到第一台服务器有连续的活跃流量,否则总是会优先选择第一台服务器。

Source IP Hash: 这种方式通过生成请求源 IP 的哈希值,并通过这个哈希值来找到正确的真实服务器。这意味着对于同一主机来说他对应的服务器总是相同。使用这种方式,你不需要保存任何源 IP。但是需要注意,这种方式可能导致服务器负载不平衡。

Least Connection Slow Start Time: 对最少连接数和带权重的最小连接数调度方法来说,当一个服务器刚加入线上环境是,可以为其配置一个时间段,在这段时间内连接数是有限制的而且是缓慢 增加的。这为服务器提供了一个‘过渡时间’以保证这个服务器不会因为刚启动后因为分配的连接数过多而超载。这个值在 L7 配置界面设置。

Weighted Least Connection: 如果服务器的资源容量各不相同,那么 “加权最少连接” 方法更合适:由管理员根据服务器情况定制的权重所决定的活跃连接数一般提供了一种对服务器非常 平衡的利用,因为他它借鉴了最少连接和权重两者的优势。通常,这是一个非常公平的分配方式,因为它使用了连接数和服务器权重比例;集群中比例最低的服务器 自动接收下一个请求。但是请注意,在低流量情况中使用这种方法时,请参考 “最小连接数” 方法中的注意事项。

Agent Based Adaptive Balancing: 除了上述方法之外,负载主机包含一个自适用逻辑用来定时监测服务器状态和该服务器的权重。对于非常强大的 “基于代理的自适应负载均衡” 方法来说,负 载主机以这种方式来定时检测所有服务器负载情况:每台服务器都必须提供一个包含文件,这个文件包含一个 0~99 的数字用来标明改服务器的实际负载情况 (0 = 空前,99 = 超载,101 = 失败,102 = 管理员禁用),而服务器同构 http get 方法来获取这个文件;同时对集群中服务器来说,以二进制文件形式提供自身负载情况也是该服务器工作之一,然而,并没有限制服务器如何计算自身的负载 情况。根据服务器整体负载情况,有两种策略可以选择:在常规的操作中,调度算法通过收集的服务器负载值和分配给该服务器的连接数的比例计算出一个权重比 例。因此,如果一个服务器负载过大,权重会通过系统透明的作重新调整。和加权轮循调度方法一样,不正确的分配可以被记录下来使得可以有效的为不同服务器分 配不同的权重。然而,在流量非常低的环境下,服务器报上来的负载值将不能建立一个有代表性的样本;那么基于这些值来分配负载的话将导致失控以及指令震荡。 因此,在这种情况下更合理的做法是基于静态的权重比来计算负载分配。当所有服务器的负载低于管理员定义的下限时,负载主机就会自动切换为加权轮循方式来分 配请求;如果负载大于管理员定义的下限,那么负载主机又会切换回自适应方式。

Fixed Weighted: 最高权重只有在其他服务器的权重值都很低时才使用。然而,如果最高权重的服务器下降,则下一个最高优先级的服务器将为客户端服务。这种方式中每个真实服务器的权重需要基于服务器优先级来配置。

Weighted Response: 流量的调度是通过加权轮循方式。加权轮循中所使用的权重是根据服务器有效性检测的响应时间来计算。每个有效性检测都会被计时,用来标记它响应成功花 了多长时间。但是需要注意的是,这种方式假定服务器心跳检测是基于机器的快慢,但是这种假设也许不总是能够成立。所有服务器在虚拟服务上的响应时间的总和 加在一起,通过这个值来计算单个服务物理服务器的权重;这个权重值大约每 15 秒计算一次。

要想实现这样的功能必须自己写心跳程序,一般是用socket实现,并且两台服务都必须是双网卡才有意义。

首先,将两台服务直连。

其次,建立心跳程序服务端和客户端,分别安装在主备服务上,主服务器一直发alive信息给备服务器,一单收不到信息,就停止主服务器,备用服务器启动。

最后,发警告信息。

故障现象

公司有两台关键的服务器,一个是主服务器,一个是备用服务器。中间通过心跳线连接,在某台主机一次重启后,网络设置没有任何改动,而心跳功能却不能实现了,两台机器不能同时心跳线互通。

诊断过程

这次事可闹大了,这可是公司关键业务的服务器,连老总都惊动了,他可不管你怎么处理,他只关心机器能否正常运转,现在已经是凌晨2点半了,留给我只有几个小时的时间了在明天早上上班前可一定要搞定,否则后果……

赶快抓紧时间,一步一步来,首先这次重启只是因为改动了几个配置文件, 要生效就必须要重启系统。不过幸好有备份、先不管三七二十一。恢复配置文件再重启。故障依旧两台机器都可正常运行,心跳线却依然有问题。再查看每台机器心跳线连接的网卡状态及配置 ,状态都是没有问题 ,网卡灯也是亮的。难道是网线没插好。或是有问题。重新用一根确认,网线是好的,可是两个服务器之间还是不通。奇怪,这是什么原因,排除物理问题,那肯定是设置问题。

没办法,只好将两台机器网卡状态一项一项的比较。这是怎么回事,突然我发现两个网卡的速率及状态不一样,一个是100Mb/s全双工,而另一个则是 10Mb/s半双工。比来比去只有这一项不同。难道是这个原因,不管了,死马当活马医了,把两台机器的网卡状态统一设置为10口Mb/s全双工RESET一下。我再Ping,问题解决了。再重新设置配置文件,这次强制网卡状态为100Mb/。全双工,重新启动机器 ,服务器工作一切正常。看看老总紧缩的眉头舒展开,我在想这个月的奖金是不是会……

排除心得

本次故障的原因其实非常简单,但表现出来的现象则稍微复杂一些。该服务器使用的是一个10/100 Mb/s的自适应以太网卡,设计速度为100Mb/s。机器重启后,网卡自动选择状态。由于两边网卡的工作状态不一致,导致网络不通。

现在网卡常见的有 10Mb/SI 00Mb/s和 10/100 Mb/s自适应网卡、当两个相同固定速车的网卡连接时一般不会产生什么大问题 可当使用10/100Mb/S的自适应以太网卡,有时会产生一些莫名的问题,建议大家在使用这类网卡时最好设置一个初始的速率,且最好两边速率相同。建议不要使用自适应,速率设置的问题常常会导致网络时通时不通。

另外还有一个全双工和半双工模式选择和是否匹配的问题。全双工模式发送者和接受者可以在连接线路上同时发送数据,发送的方向相反。发送和接受同时进行,需要两对电缆,这种连接被认为是点到点的连接,并且几乎是无冲突的。全双工的建立需要网卡有全双工的能力。半双工模式,在发送者和接受者之间同一时间只能沿同一个方向传输数据,存在着竞争和冲突。两种不同的传输模式在设置时需要注意,一定要相一致,否则由于模式不匹配往往会造成网络不通等问题。

何为心跳线

两台主机A、B ;其中A为工作机,B为备份机。它们之间通过一根心跳线采连接,这也称为“心跳检测”。心跳线主要利用一条RS 233检测链路来完成,采用Ping方式检测验证系统宕机检测的准确性。

安装在主机上的高可用软件通过心跳线来实时监测对方的运行状态。一旦正在工作的主机A 因为各种硬件故障,如电源失效、主要部件失效或者启动盘失效等导致系统发生故障,主机B 可以立即投入工作。这样可以在最大限度上保证网络地正常运行。

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » C# udp如何对多用户进行心跳检测

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情