# spider **Repository Path**: archx/spider ## Basic Information - **Project Name**: spider - **Description**: Netty 集群聊天服务 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 20 - **Forks**: 8 - **Created**: 2017-04-07 - **Last Updated**: 2023-09-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spider > Netty 聊天系统集群架构 ## 集群原理 在集群环境下,系统由若干个组成部分。 ```text NettyServer: 即时通讯服务器 NettyClient:服务器间通讯组件 LoadBalance:负载平衡 ZooKeeper:服务器健壮性监测 ``` ### Zookeeper 集群监控 Zookeeper是一个开源的分布式协同工作平台,基于Java语言。可以在任意应用服务器中部署。在本系统中主要用于检测即时通讯服务器的健壮性。 在集群架构中,有一个Zookeeper的服务可以允许多个ZookeeperClient接入,并且注册或者读取相关信息。其中有一个ZookeeperClient作为监视器,用于监听其他Client的变化。整个机制基于Zookeeper自己维护的一课树桩结构来运行。 ## 负载均衡算法 由于服务器间通讯会带来一定的开销和延时,目前采用最高效的做法是,尽量使连接集中在一台NettyServer。 大体上采用算法为: 每一台服务器有一个忙标志,当有用户登录服务器,则会连接数加1。 每台服务器设一个连接的阈值threshold,当连接数超过这个threshold,则NodeManager会往Zookeeper服务器写一个busy的节点,比如/busy/ns1。ClusterMonitor通过Zookeeper同步机制,会更新存活服务器列表,并且将该服务器标示为“忙”,当有新的连接请求进入到ClusterMonitor的时候,则该服务器标示为“暂时”不可用。 依次轮循下一个可用服务器。在最坏情况下,所有服务器可能都处于“忙”的状态,ClusterMonitor还是会为新的请求连接分配服务器,这时候连接的等待开销就交由NettyServer自行处理。 当客户端关闭连接时,NodeManager会做相反操作,删除/busy节点。ClusterMonitor会同步服务器列表,去掉相应的忙标志。 ## Redis 服务器 Redis服务器主要是一个分布式缓存服务器,需要使用linux环境部署。该服务器主要的作用是存储,用户与nettyserver之间的映射关系。 在下列场景,系统会从redis读取信息。 当用户A给B发消息,A和B分别连接在不同的服务器上,这时候,连接A的nettyserver就需要从redis或取B所在的服务器Ip,并且进行服务器间转发。 ## 集群模式开发事项 在集群模式下,客户端的连接不能直接走netty服务器,必须先到ClusterMonitor的web服务找到对应的服务器节点。 当Zookeeper启动完成后,就可以启动Zookeeper的监视器ClusterMonitor。 用户连接时,注册用户。保存用户和通道的映射关系,同时更新Netty服务器的`/busy`繁忙节点。 同理,用户离线时也更新`/busy`节点 在发送消息时,如果发送对象不存在本NettyServer,则系统会从Redis服务器上获取发送对象所在的NettyServer的ip地址建立连接,服务器端的WebSocket发送数据。否则则返回客户端一消息,告知该对象离线。 ## 项目演示 演示项目基于`spring-boot`,依次启动以下模块 ### spider-cluster > 集群监控,以及ui展示模块,启动 `SpiderClusterApplication` ### spider-netty > Netty服务端和客服端实现,启动 `SpringNettyApplication` 修改Netty端口,启动多个Netty服务端 ### 跨服务端通信 ![assets/cluster_server.jpg](assets/cluster_server.jpg) ![redis](assets/redis.png) ### 广播和单聊 ![](assets/3_a.jpg) ![](assets/3_b.png)