Gateway集成Netty服务 [复制链接]
发表于 2023-2-28 08:31:10 | 显示全部楼层 |阅读模式
目录

Gateway和Netty都有盲区的感觉;
一、Netty简介

Netty是一个异步的,事件驱动的网络应用框架,用以快速开发高可靠、高性能的网络应用程序。

传输服务:提供网络传输能力的管理;
协议支持:支持常见的数据传输协议;
核心模块:包括可扩展事件模型、通用的通信API、零拷贝字节缓冲;
二、Netty入门案例

1、服务端启动

配置Netty服务器端程序,引导相关核心组件的加载;
  1. public class NettyServer {
  2.     public static void main(String[] args) {
  3.         // EventLoop组,处理事件和IO
  4.         EventLoopGroup parentGroup = new NioEventLoopGroup();
  5.         EventLoopGroup childGroup = new NioEventLoopGroup();
  6.         try {
  7.             // 服务端启动引导类
  8.             ServerBootstrap serverBootstrap = new ServerBootstrap();
  9.             serverBootstrap.group(parentGroup, childGroup)
  10.                     .channel(NioServerSocketChannel.class).childHandler(new ChannelInit());
  11.             // 异步IO的结果
  12.             ChannelFuture channelFuture = serverBootstrap.bind(8082).sync();
  13.             channelFuture.channel().closeFuture().sync();
  14.         } catch (Exception e){
  15.             e.printStackTrace();
  16.         } finally {
  17.             parentGroup.shutdownGracefully();
  18.             childGroup.shutdownGracefully();
  19.         }
  20.     }
  21. }
复制代码
2、通道初始化

ChannelInitializer特殊的通道处理器,提供一种简单的方法,对注册到EventLoop的通道进行初始化;比如此处设置的编码解码器,自定义处理器;
  1. public class ChannelInit extends ChannelInitializer<SocketChannel> {
  2.     @Override
  3.     protected void initChannel(SocketChannel socketChannel) {
  4.         // 获取管道
  5.         ChannelPipeline pipeline = socketChannel.pipeline();
  6.         // Http编码、解码器
  7.         pipeline.addLast("DefHttpServerCodec",new HttpServerCodec());
  8.         // 添加自定义的handler
  9.         pipeline.addLast("DefHttpHandler", new DefHandler());
  10.     }
  11. }
复制代码
3、自定义处理器

处理对服务器端发起的访问,通常包括请求解析,具体的逻辑执行,请求响应等过程;
  1. public class DefHandler extends SimpleChannelInboundHandler<HttpObject> {
  2.     @Override
  3.     protected void channelRead0(ChannelHandlerContext ctx, HttpObject message) throws Exception {
  4.         if(message instanceof HttpRequest) {
  5.             // 请求解析
  6.             HttpRequest httpRequest = (HttpRequest) message;
  7.             String uri = httpRequest.uri();
  8.             String method = httpRequest.method().name();
  9.             log.info("【HttpRequest-URI:"+uri+"】");
  10.             log.info("【HttpRequest-method:"+method+"】");
  11.             Iterator<Map.Entry<String,String>> iterator = httpRequest.headers().iteratorAsString();
  12.             while (iterator.hasNext()){
  13.                 Map.Entry<String,String> entry = iterator.next();
  14.                 log.info("【Header-Key:"+entry.getKey()+";Header-Value:"+entry.getValue()+"】");
  15.             }
  16.             // 响应构建
  17.             ByteBuf content = Unpooled.copiedBuffer("Netty服务", CharsetUtil.UTF_8);
  18.             FullHttpResponse response = new DefaultFullHttpResponse
  19.                                         (HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
  20.             response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain;charset=utf-8");
  21.             response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
  22.             ctx.writeAndFlush(response);
  23.         }
  24.     }
  25. }
复制代码
4、测试请求

上面入门案例中,简单的配置了一个Netty服务器端,启动之后在浏览器中模拟访问即可;
  1. http://127.0.0.1:8082/?id=1&name=Spring
复制代码
三、Gateway集成

1、依赖层级

项目中Gateway网关依赖的版本为2.2.5.RELEASE,发现Netty依赖的版本为4.1.45.Final,是当下比较主流的版本
  1. <dependency>
  2.     <groupId>org.springframework.cloud</groupId>
  3.     <artifactId>spring-cloud-starter-gateway</artifactId>
  4.     <version>2.2.5.RELEASE</version>
  5. </dependency>
  6. <dependency>
  7.   <groupId>org.springframework.boot</groupId>
  8.   <artifactId>spring-boot-starter-webflux</artifactId>
  9.   <version>2.3.2.RELEASE</version>
  10. </dependency>
  11. <dependency>
  12.   <groupId>org.springframework.boot</groupId>
  13.   <artifactId>spring-boot-starter-reactor-netty</artifactId>
  14.   <version>2.3.2.RELEASE</version>
  15. </dependency>
复制代码
2、自动化配置

在Gateway网关的自动化配置配置类中,提供了Netty配置的管理;
  1. @AutoConfigureBefore({ HttpHandlerAutoConfiguration.class,WebFluxAutoConfiguration.class })
  2. @ConditionalOnClass(DispatcherHandler.class)
  3. public class GatewayAutoConfiguration {
  4.     @Configuration(proxyBeanMethods = false)
  5.     @ConditionalOnClass(HttpClient.class)
  6.     protected static class NettyConfiguration {
  7.         @Bean
  8.         @ConditionalOnProperty(name = "spring.cloud.gateway.httpserver.wiretap")
  9.         public NettyWebServerFactoryCustomizer nettyServerWiretapCustomizer(
  10.                 Environment environment, ServerProperties serverProperties) {
  11.             return new NettyWebServerFactoryCustomizer(environment, serverProperties) {
  12.                 @Override
  13.                 public void customize(NettyReactiveWebServerFactory factory) {
  14.                     factory.addServerCustomizers(httpServer -> httpServer.wiretap(true));
  15.                     super.customize(factory);
  16.                 }
  17.             };
  18.         }
  19.     }
  20. }
复制代码
四、配置加载

1、基础配置

在工程的配置文件中,简单做一些基础性的设置;
  1. server:
  2.   port: 8081                  # 端口号
  3.   netty:                      # Netty组件
  4.     connection-timeout: 3000  # 连接超时
复制代码
2、属性配置类

在ServerProperties类中,并没有提供很多显式的Netty配置参数,更多信息需要参考工厂类;
  1. @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
  2. public class ServerProperties {
  3.     private Integer port;
  4.     public static class Netty {
  5.         private Duration connectionTimeout;
  6.     }
  7. }
复制代码
3、配置加载分析



  • 基于配置的属性,定制化管理Netty服务的信息;
  1. public class NettyWebServerFactoryCustomizer
  2.         implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory>{
  3.     private final Environment environment;
  4.     private final ServerProperties serverProperties;
  5.     @Override
  6.     public void customize(NettyReactiveWebServerFactory factory) {
  7.         PropertyMapper propertyMapper = PropertyMapper.get().alwaysApplyingWhenNonNull();
  8.         ServerProperties.Netty nettyProperties = this.serverProperties.getNetty();
  9.         propertyMapper.from(nettyProperties::getConnectionTimeout).whenNonNull()
  10.                 .to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout));
  11.     }
  12. }
复制代码

  • NettyReactiveWeb服务工厂,基于上述入门案例,创建WebServer时,部分参数信息出自LoopResources接口;
  1. public class NettyReactiveWebServerFactory extends AbstractReactiveWebServerFactory {
  2.     private ReactorResourceFactory resourceFactory;
  3.     @Override
  4.     public WebServer getWebServer(HttpHandler httpHandler) {
  5.         HttpServer httpServer = createHttpServer();
  6.         ReactorHttpHandlerAdapter handlerAdapter = new ReactorHttpHandlerAdapter(httpHandler);
  7.         NettyWebServer webServer = new NettyWebServer(httpServer, handlerAdapter, this.lifecycleTimeout);
  8.         webServer.setRouteProviders(this.routeProviders);
  9.         return webServer;
  10.     }
  11.    
  12.     private HttpServer createHttpServer() {
  13.                 HttpServer server = HttpServer.create();
  14.                 if (this.resourceFactory != null) {
  15.                 LoopResources resources = this.resourceFactory.getLoopResources();
  16.                 server = server.tcpConfiguration(
  17.                                 (tcpServer) -> tcpServer.runOn(resources).addressSupplier(this::getListenAddress));
  18.         }
  19.         return applyCustomizers(server);
  20.         }
  21.        
  22. }
复制代码
五、周期管理方法

1、控制类


Gateway项目中,Netty服务核心控制类,通过NettyReactiveWebServerFactory工厂类创建,对Netty生命周期的管理提供了一层包装;
  1. public class NettyWebServer implements WebServer {
  2.     private final HttpServer httpServer;
  3.     private final ReactorHttpHandlerAdapter handlerAdapter;
  4.     /**
  5.      * 启动方法
  6.      */
  7.     @Override
  8.     public void start() throws WebServerException {
  9.         if (this.disposableServer == null) {
  10.             this.disposableServer = startHttpServer();
  11.             // 控制台日志日志
  12.             logger.info("Netty started on port(s): " + getPort());
  13.             startDaemonAwaitThread(this.disposableServer);
  14.         }
  15.     }
  16.     private DisposableServer startHttpServer() {
  17.         HttpServer server = this.httpServer;
  18.         if (this.routeProviders.isEmpty()) {
  19.             server = server.handle(this.handlerAdapter);
  20.         }
  21.         return server.bindNow();
  22.     }
  23.     /**
  24.      * 停止方法
  25.      */
  26.     @Override
  27.     public void stop() throws WebServerException {
  28.         if (this.disposableServer != null) {
  29.             // 释放资源
  30.             if (this.lifecycleTimeout != null) {
  31.                 this.disposableServer.disposeNow(this.lifecycleTimeout);
  32.             }
  33.             else {
  34.                 this.disposableServer.disposeNow();
  35.             }
  36.             // 对象销毁
  37.             this.disposableServer = null;
  38.         }
  39.     }
  40. }
复制代码
2、管理类

Netty组件中抽象管理类,以安全的方式构建Http服务;
[code]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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表