Gateway集成Netty服務的配置加載詳解
一、Netty簡介
Gateway和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
以上就是Gateway集成Netty服務的配置加載詳解的詳細內容,更多關於Gateway集成Netty服務的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- gateway、webflux、reactor-netty請求日志輸出方式
- 深入剖析網關gateway原理
- springcloud gateway無法路由問題的解決
- Springboot中用 Netty 開啟UDP服務方式
- 基於Springboot+Netty實現rpc的方法 附demo