spring2.x集成netty4.x

正文

添加依赖

maven 添加如下依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<netty.version>4.1.22.Final</netty.version>
</properties>

<dependencies>
<!-- Netty -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${netty.version}</version>
</dependency>
<!-- Netty -->
</dependencies>

添加配置

application.properties 配置文件添加如下配置

1
2
3
4
5
netty.host=0.0.0.0
netty.port=12268
netty.bossNum=2
netty.workerNum=4
netty.backlog=4096

添加配置类和启动服务类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package com.utstar.filemonitoring.netty;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
* FileName: NettyConf
* Author: creambing
* Date: 2019-09-17 11:13
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
@ConfigurationProperties(prefix = "netty")
@Component
@Data
public class NettyConf {
private String host;
private int port;
private int bossNum;
private int workerNum;
private int backlog;
private Long idleTime;

@Value("${netty.host:127.0.0.1}")
public void setNettyHost(String nettyHost) {
NETTY_HOST = nettyHost;
}

@Value("${netty.port:8888}")
public void setNettyPort(Integer nettyPort) {
NETTY_PORT = nettyPort;
}

@Value("${netty.bossNum:1}")
public void setNettyBossnum(Integer nettyBossnum) {
NETTY_BOSSNUM = nettyBossnum;
}

@Value("${netty.workerNum:2}")
public void setNettyWorkernum(Integer nettyWorkernum) {
NETTY_WORKERNUM = nettyWorkernum;
}

@Value("${netty.backlog:1024}")
public void setNettyBacklog(Integer nettyBacklog) {
NETTY_BACKLOG = nettyBacklog;
}

@Value("${netty.idleTime:60}")
public void setNettyIdletime(Long nettyIdletime) {
NETTY_IDLETIME = nettyIdletime;
}

public static String NETTY_HOST;
public static Integer NETTY_PORT;
public static Integer NETTY_BOSSNUM;
public static Integer NETTY_WORKERNUM;
public static Integer NETTY_BACKLOG;
public static Long NETTY_IDLETIME;
}

package com.creambing.netty.server.thread;

import com.creambing.netty.server.handler.*;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

import java.io.PrintWriter;
import java.io.StringWriter;

import static com.creambing.netty.server.conf.NettyConf.*;
import static com.creambing.netty.server.constants.NettyConstants.*;

/**
* FileName: NettyThread
* Author: creambing
* Date: 2019-09-17 13:19
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
@DependsOn("nettyConf")
@Component
@Slf4j
public class NettyThread implements Runnable {

private final EventLoopGroup bossGroup = new NioEventLoopGroup(NETTY_BOSSNUM);
private final EventLoopGroup workerGroup = new NioEventLoopGroup(NETTY_WORKERNUM);

@Override
public void run() {
try {
ServerBootstrap b = new ServerBootstrap();
b.option(ChannelOption.SO_BACKLOG, NETTY_BACKLOG)
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.TCP_NODELAY, true)
.childOption(ChannelOption.SO_REUSEADDR, true) //重用地址
.childOption(ChannelOption.SO_RCVBUF, 65536)
.childOption(ChannelOption.SO_SNDBUF, 65536);
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {//每连上一个链接调用一次
@Override
protected void initChannel(SocketChannel ch) {
log.info("Accept new connection: " + ch);
// 设定读空闲时间,在这段时间内如果没有数据读到,就表示连接假死;
ch.pipeline().addLast("idle-state-handler", new NettyIdleStateHandler());
ch.pipeline().addLast(new AcceptorIdleStateTrigger());
ch.pipeline().addLast("decoder", new NewLengthFieldBasedFrameDecoder(MAX_FRAME_LENGTH, LENGTH_FIELD_LENGTH, LENGTH_FIELD_OFFSET, LENGTH_ADJUSTMENT, INITIAL_BYTES_TO_STRIP, false));
ch.pipeline().addLast("new-encoder", new NewEncoder());
ch.pipeline().addLast("heartbeat", new HeartBeatReceiveHandler());
ch.pipeline().addLast("process", new NettyBusinessHandler());
}
});
// 开始真正绑定端口进行监听
ChannelFuture future = b.bind(NETTY_HOST, NETTY_PORT).sync();
Channel channel = future.channel();
log.info("listening on [{}] at [{}] and ready for connection ...", NETTY_HOST, NETTY_PORT);
if (future.isSuccess()) {
log.info("netty server start success");
}
channel.closeFuture().sync();
} catch (Exception e) {
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
log.error("start netty server has exception,caused by[{}]", stringWriter.toString());
}
}

/**
* 销毁
*/
@PreDestroy
public void stop() {
bossGroup.shutdownGracefully().syncUninterruptibly();
bossGroup.shutdownGracefully().syncUninterruptibly();
log.info("stop netty server success");
}
}

package com.creambing.netty.server;

import com.creambing.netty.server.thread.NettyThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

@Slf4j
@SpringBootApplication
public class ServerApplication {

public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}


@Resource
NettyThread nettyThread;

@PostConstruct
public void startCsServer() {
log.info("start netty server ...");
Thread t = new Thread(nettyThread);
t.start();
}

}

参考资料

Cream Bing wechat
subscribe to my blog by scanning my public wechat account