欢迎大家来到IT世界,在知识的湖畔探索吧!
一、Netty简介
Netty是一个异步的,事件驱动的网络应用框架,用以快速开发高可靠、高性能的网络应用程序。
传输服务:提供网络传输能力的管理;
协议支持:支持常见的数据传输协议;
核心模块:包括可扩展事件模型、通用的通信API、零拷贝字节缓冲;
二、Netty入门案例
1、服务端启动
配置Netty服务器端程序,引导相关核心组件的加载;
public class NettyServer {
public static void main(String[] args) {
// EventLoop组,处理事件和IO
EventLoopGroup parentGroup = new NioEventLoopGroup();
EventLoopGroup childGroup = new NioEventLoopGroup();
try {
// 服务端启动引导类
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(parentGroup, childGroup)
.channel(NioServerSocketChannel.class).childHandler(new ChannelInit());
// 异步IO的结果
ChannelFuture channelFuture = serverBootstrap.bind(8082).sync();
channelFuture.channel().closeFuture().sync();
} catch (Exception e){
e.printStackTrace();
} finally {
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
}
}
}
复制代码
欢迎大家来到IT世界,在知识的湖畔探索吧!
2、通道初始化
ChannelInitializer特殊的通道处理器,提供一种简单的方法,对注册到EventLoop的通道进行初始化;比如此处设置的编码解码器,自定义处理器;
欢迎大家来到IT世界,在知识的湖畔探索吧!public class ChannelInit extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) {
// 获取管道
ChannelPipeline pipeline = socketChannel.pipeline();
// Http编码、解码器
pipeline.addLast("DefHttpServerCodec",new HttpServerCodec());
// 添加自定义的handler
pipeline.addLast("DefHttpHandler", new DefHandler());
}
}
复制代码
3、自定义处理器
处理对服务器端发起的访问,通常包括请求解析,具体的逻辑执行,请求响应等过程;
public class DefHandler extends SimpleChannelInboundHandler<HttpObject> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject message) throws Exception {
if(message instanceof HttpRequest) {
// 请求解析
HttpRequest httpRequest = (HttpRequest) message;
String uri = httpRequest.uri();
String method = httpRequest.method().name();
log.info("【HttpRequest-URI:"+uri+"】");
log.info("【HttpRequest-method:"+method+"】");
Iterator<Map.Entry<String,String>> iterator = httpRequest.headers().iteratorAsString();
while (iterator.hasNext()){
Map.Entry<String,String> entry = iterator.next();
log.info("【Header-Key:"+entry.getKey()+";Header-Value:"+entry.getValue()+"】");
}
// 响应构建
ByteBuf content = Unpooled.copiedBuffer("Netty服务", CharsetUtil.UTF_8);
FullHttpResponse response = new DefaultFullHttpResponse
(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain;charset=utf-8");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
ctx.writeAndFlush(response);
}
}
}
复制代码
4、测试请求
上面入门案例中,简单的配置了一个Netty服务器端,启动之后在浏览器中模拟访问即可;
欢迎大家来到IT世界,在知识的湖畔探索吧!http://127.0.0.1:8082/?id=1&name=Spring
复制代码
三、Gateway集成
1、依赖层级
项目中Gateway网关依赖的版本为2.2.5.RELEASE,发现Netty依赖的版本为4.1.45.Final,是当下比较主流的版本;
<!-- 1、项目工程依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<!-- 2、starter-gateway依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
<!-- 3、starter-webflux依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-reactor-netty</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
复制代码
2、自动化配置
在Gateway网关的自动化配置配置类中,提供了Netty配置的管理;
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class,WebFluxAutoConfiguration.class })
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(HttpClient.class)
protected static class NettyConfiguration {
@Bean
@ConditionalOnProperty(name = "spring.cloud.gateway.httpserver.wiretap")
public NettyWebServerFactoryCustomizer nettyServerWiretapCustomizer(
Environment environment, ServerProperties serverProperties) {
return new NettyWebServerFactoryCustomizer(environment, serverProperties) {
@Override
public void customize(NettyReactiveWebServerFactory factory) {
factory.addServerCustomizers(httpServer -> httpServer.wiretap(true));
super.customize(factory);
}
};
}
}
}
复制代码
四、配置加载
1、基础配置
在工程的配置文件中,简单做一些基础性的设置;
server:
port: 8081 # 端口号
netty: # Netty组件
connection-timeout: 3000 # 连接超时
复制代码
2、属性配置类
在ServerProperties类中,并没有提供很多显式的Netty配置参数,更多信息需要参考工厂类;
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
private Integer port;
public static class Netty {
private Duration connectionTimeout;
}
}
复制代码
3、配置加载分析
- 基于配置的属性,定制化管理Netty服务的信息;
public class NettyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory>{ private final Environment environment; private final ServerProperties serverProperties; @Override public void customize(NettyReactiveWebServerFactory factory) { PropertyMapper propertyMapper = PropertyMapper.get().alwaysApplyingWhenNonNull(); ServerProperties.Netty nettyProperties = this.serverProperties.getNetty(); propertyMapper.from(nettyProperties::getConnectionTimeout).whenNonNull() .to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout)); }}复制代码
- NettyReactiveWeb服务工厂,基于上述入门案例,创建WebServer时,部分参数信息出自LoopResources接口;
public class NettyReactiveWebServerFactory extends AbstractReactiveWebServerFactory { private ReactorResourceFactory resourceFactory; @Override public WebServer getWebServer(HttpHandler httpHandler) { HttpServer httpServer = createHttpServer(); ReactorHttpHandlerAdapter handlerAdapter = new ReactorHttpHandlerAdapter(httpHandler); NettyWebServer webServer = new NettyWebServer(httpServer, handlerAdapter, this.lifecycleTimeout); webServer.setRouteProviders(this.routeProviders); return webServer; } private HttpServer createHttpServer() { HttpServer server = HttpServer.create(); if (this.resourceFactory != null) { LoopResources resources = this.resourceFactory.getLoopResources(); server = server.tcpConfiguration( (tcpServer) -> tcpServer.runOn(resources).addressSupplier(this::getListenAddress)); } return applyCustomizers(server); } }复制代码
五、周期管理方法
1、控制类
Gateway项目中,Netty服务核心控制类,通过NettyReactiveWebServerFactory工厂类创建,对Netty生命周期的管理提供了一层包装;
public class NettyWebServer implements WebServer {
private final HttpServer httpServer;
private final ReactorHttpHandlerAdapter handlerAdapter;
/**
* 启动方法
*/
@Override
public void start() throws WebServerException {
if (this.disposableServer == null) {
this.disposableServer = startHttpServer();
// 控制台日志
logger.info("Netty started on port(s): " + getPort());
startDaemonAwaitThread(this.disposableServer);
}
}
private DisposableServer startHttpServer() {
HttpServer server = this.httpServer;
if (this.routeProviders.isEmpty()) {
server = server.handle(this.handlerAdapter);
}
return server.bindNow();
}
/**
* 停止方法
*/
@Override
public void stop() throws WebServerException {
if (this.disposableServer != null) {
// 释放资源
if (this.lifecycleTimeout != null) {
this.disposableServer.disposeNow(this.lifecycleTimeout);
}
else {
this.disposableServer.disposeNow();
}
// 对象销毁
this.disposableServer = null;
}
}
}
复制代码
2、管理类
Netty组件中抽象管理类,以安全的方式构建Http服务;
public abstract class HttpServer {
public static HttpServer create() {
return HttpServerBind.INSTANCE;
}
public final DisposableServer bindNow() {
return bindNow(Duration.ofSeconds(45));
}
public final HttpServer handle(BiFunction<? super HttpServerRequest, ? super
HttpServerResponse, ? extends Publisher<Void>> handler) {
return new HttpServerHandle(this, handler);
}
}
复制代码
六、参考源码
编程文档:
https://gitee.com/cicadasmile/butte-java-note
应用仓库:
https://gitee.com/cicadasmile/butte-flyer-parent
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/37382.html