疯狂创客圈 Java 分布式聊天室【 亿级流量】实战系列之 -25【 博客园 总入口 】
1.写在前面
1.1 实战Netty集群的理由
Java基础练习中,一个重要的实战练习是: java的聊天程序。基本上,每一个java工程师,都有写过自己的聊天程序。
实现一个Java的分布式的聊天程序的分布式练习,同样非常重要的是。有以下几个方面的最重要作用:
1 体验高并发的程序的开发:从研究承载千、万QPS级的流量,拓展能够承载百万级、千万级、亿万级流量
2 有分布式、高并发的实战经验,面试谈薪水的时候,能提升不少
3 Netty集群的分布式原理,和大数据的分布式原理,elasticsearch 的分布式原理,和redis集群的分布式原理,和mongodb的分布式原理,很大程度上,都是想通。 Netty集群作为一个实战开发, 是一个非常好的分布式基础练习
4 更多的理由,请参考机械工业出版社的书籍 《Netty Zookeeper Redis 高并发实战》
1.2 Netty 集群 实战源码
本文的代码,来自于开源项目CrazyIm , 项目的地址为
https://gitee.com/crazymaker/crazy_tourist_circle__im.git源码 目前已经完成了基本的通信,在不断迭代中,不少的群友,通过疯狂创客圈的QQ群,沟通迭代过程中的问题。
2 Netty 集群中,服务节点的注册和发现
2.1 服务节点的注册和发现
zookeeper作为注册中心,每一个netty服务启动的时候,把节点的信息比如ip地址+端口号注册到zookeeper上。
具体的原理,请参见书籍《Netty Zookeeper Redis 高并发实战》。
2.2 节点的POJO
package com.crazymakercircle.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Objects;
/**
* IM节点的POJO类
* create by 尼恩 @ 疯狂创客圈
**/
@Data
public class ImNode implements Comparable<ImNode>, Serializable {
private static final long serialVersionUID = -499010884211304846L;
//worker 的Id,zookeeper负责生成
private long id;
//Netty 服务 的连接数
private Integer balance = 0;
//Netty 服务 IP
private String host;
//Netty 服务 端口
private Integer port;
public ImNode() {
}
public ImNode(String host, Integer port) {
this.host = host;
this.port = port;
}
@Override
public String toString() {
return "ImNode{" +
"id='" + id + '\'' +
"host='" + host + '\'' +
", port='" + port + '\'' +
",balance=" + balance +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ImNode node = (ImNode) o;
// return id == node.id &&
return Objects.equals(host, node.host) &&
Objects.equals(port, node.port);
}
@Override
public int hashCode() {
return Objects.hash(id, host, port);
}
/**
* 升序排列
*/
public int compareTo(ImNode o) {
int weight1 = this.balance;
int weight2 = o.balance;
if (weight1 > weight2) {
return 1;
} else if (weight1 < weight2) {
return -1;
}
return 0;
}
public void incrementBalance() {
balance++;
}
public void decrementBalance() {
balance--;
}
}
2.3 服务的发现
利用zk有一个监听机制,就是针对某个节点进行监听,一点这个节点发生了变化就会收到zk的通知。我们就是利用zk的这个watch来进行服务的上线和下线的通知,也就是我们的服务发现功能。
package com.crazymakercircle.imServer.distribut