写点什么

Gateway 集成 Netty 服务

作者:知了一笑
  • 2023-02-28
    浙江
  • 本文字数:4695 字

    阅读完需:约 15 分钟

Gateway集成Netty服务

Gateway 和 Netty 都有盲区的感觉;

一、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(); } }}
复制代码

2、通道初始化

ChannelInitializer 特殊的通道处理器,提供一种简单的方法,对注册到 EventLoop 的通道进行初始化;比如此处设置的编码解码器,自定义处理器;


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 服务器端,启动之后在浏览器中模拟访问即可;


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
复制代码


发布于: 刚刚阅读数: 6
用户头像

知了一笑

关注

公众号:知了一笑 2020-04-08 加入

源码仓库:https://gitee.com/cicadasmile

评论

发布
暂无评论
Gateway集成Netty服务_Java_知了一笑_InfoQ写作社区