如上篇的架构图所示,我们netty集群基于springboot服务部署三个节点。下面我们通过伪代码加注释的方式,给大家详细分析。
1、核心jar引入:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
2、配置文件简单配置:
spring.application.name=tim-server
# web port
server.port=8082
# tim netty服务端口
tim.server.port=9002
logging.level.root=info
# 是否注册 zk
app.zk.switch=true
# zk 地址
app.zk.addr=192.168.65.60:2181
# zk 连接超时时限
app.zk.connect.timeout=15000
# zk 注册根节点
app.zk.root=/route
# gateway url suggested that this is Nginx address
tim.gateway.url=http://localhost:8090/
# 检测多少秒没有收到客户端心跳后服务端关闭连接 单位秒
tim.heartbeat.time=30
3、boot通用启动类:
@SpringBootApplication
public class TIMServerApplication implements CommandLineRunner {
private final static Logger LOGGER = LoggerFactory.getLogger(TIMServerApplication.class);
@Autowired
private AppConfiguration appConfiguration;
@Value("${server.port}")
private int httpPort;
public static void main(String[] args) {
SpringApplication.run(TIMServerApplication.class, args);
LOGGER.info("Start tim server success!!!");
}
@Override
public void run(String... args) throws Exception {
//获得本机IP
String addr = InetAddress.getLocalHost().getHostAddress();
Thread thread = new Thread(new RegistryZK(addr, appConfiguration.getTimServerPort(), httpPort));
thread.setName("registry-zk");
thread.start();
}
}
本服务注册到ZK
public class RegistryZK implements Runnable {
private static Logger logger = LoggerFactory.getLogger(RegistryZK.class);
private ZKit zKit;
private AppConfiguration appConfiguration ;
private String ip;
private int timServerPort;
private int httpPort;
public RegistryZK(String ip, int timServerPort,int httpPort) {
this.ip = ip;
this.timServerPort = timServerPort;
this.httpPort = httpPort ;
zKit = SpringBeanFactory.getBean(ZKit.class) ;
appConfiguration = SpringBeanFactory.getBean(AppConfiguration.class) ;
}
@Override
public void run() {
//创建父节点
zKit.createRootNode();
//是否要将自己注册到 ZK
if (appConfiguration.isZkSwitch()){
String path = appConfiguration.getZkRoot() + "/ip-" + ip + ":" + timServerPort + ":" + httpPort;
zKit.createNode(path);
logger.info("Registry zookeeper success, msg=[{}]", path);
}
}
}
ZK的工具类
@Component
public class ZKit {
private static Logger logger = LoggerFactory.getLogger(ZKit.class);
@Autowired
private ZkClient zkClient;
@Autowired
private AppConfiguration appConfiguration;
/**
* 创建父级节点
*/
public void createRootNode() {
boolean exists = zkClient.exists(appConfiguration.getZkRoot());
if (exists) {
return;
}
//创建 root
zkClient.createPersistent(appConfiguration.getZkRoot());
}
/**
* 写入指定节点 临时目录
*
* @param path
*/
public void createNode(String path) {
zkClient.createEphemeral(path);
}
}
4、netty核心启动类
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetSocketAddress;
/**
* @since JDK 1.8
*/
&