推拉结合实现(准)实时推送

Rocketmq
consumer从broker的consumerQueue中拉取未消费的消息时,采用长轮询机制(push模式),即如果存在直接返回,如果不存在未消费的消息,broker端会hold住此请求30s,在hold期间如果ReputMessageService往ConsumerQueue推送了新消息,则释放hold,给consumer返回数据。
因此本质上rocketmq的push模式也是一种pull,通过长轮询达成准实时,给人一种push的感觉

--------------------------

Apollo 3
Apollo采用定时+长轮询的机制拉取配置。客户端不停请求configServer的配置变化通知接口,如果配置有变更,就会返回变更信息。ConfigServer使用了Servlet 3的异步特性,没有配置变更时,将hold住连接30,等到有通知时立刻返回,实现一个基于http的长连接。
同时Apollo也采用了一种兜底策略,默认每5min拉取一次最新配置,来覆盖本地的缓存配置。


乐视配置中心(只支持xml)
客户端每隔3s到配置中心拉取最新配置,通过version或md5判断是否有变化,有则将配置解析为对象,重置缓存,当对象实现了自定义的接口时,则触发与该对象关联的处理器,执行相关逻辑。因此配置的更改是有延时的,无法实时感知。


---------------------------

nginx应用
nginx作负载均衡: 应用下线时,通过nginx注销域名,以保证流量不会打到相应的机器上。应用上线完成后(健康检测成功),将此结点注册到nginx上,实现负载均衡。实际工作中,发现有在健康检测中做应用预热的,这是很不合理的。应该在spring应用上下文refresh事件中实现预热。
上下线基本上是实时的,上线过程中请求不可用可降低到最低(失败的请求通过客户端的重试机制来重试)。


dubbo服务发现和治理
以zk实现服务注册和发现为例。当provider启动完成时,会通知zk创建临时结点,然后通过心跳机制,保证此provider可用(临时结点不会被删除)。当provider下线时,会通知zk删除临时结点,以说明此服务不可用。
                            当consumer启动时,会从zk拉取需要的服务注册信息,缓存到本地,同时利用zk的watcher机制来监听provider的变化。当监听到变化时,更新本地缓存。当consumer调用服务中,根据本地缓存中的服务注册信息构建调用请求,并根据负载均衡策略转发请求。
因此,dubbo的服务发现接近准实时,上下线过程请求不可用可降低到最低(重试机制).


spring cloud
以Euraka 1.x版本为例,服务提供者在启动的时候通过发送REST请求的方式将自己注册到EurakaSever上,同时带上自身元数据。测试完成后每隔30s发送一次心跳,服务端超过90s未收到心跳,则下线此服务。服务下线时,也会通知EurakaSever服务下线。
                      服务消费者启动的时候会发送一个REST请求给注册中心,获取已注册的服务清单。为了性能考虑,EurakaServer会维护一份只读的服务清单来返回给客户端,这份缓存清单会隔30s刷新一次。消费者获取清单之后,就可以获得服务者的实例名和元数据信息。Ribbon默认使用轮询的方式调用,从而实现客户端负载均衡。
                     


目前来看spring cloud消费端对服务的上下线感知是最差的,直观的表现就是下上线期间会产生大量的无效请求(重试机制可以降低些损失),同时负载均衡的有效利用率最低。当拆解的微服务数量比较少时,euraka的压力不大时,可以关闭euraka server的多级缓存,同时降低consumer的拉取频率(每3s拉取)。


 

猜你喜欢

转载自blog.csdn.net/qian_348840260/article/details/107931066