Gateway集成Netty服务

news2024/11/14 19:19:03

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);
    }
}

E N D END END

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/377339.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python调用百度AI实现文字识别

目录标题 前沿实战演示重中之重(开玩笑)前沿 今天我们也来高大上一下,玩一把人工智能。那就是免费调用百度AI实现图片上面的文字识别。相对于Python的第三方库,百度人工智能要更强大,毕竟人工智能不是那么容易搞的。要调用,其实很简单,关键的代码只需要三行。但需要先注…

使用cmake在win10编译yolov5+tensorRT+cuda+cudnn+protobuf代码进行混合编译

这里进行之前需要把protobuf在win10下编译&#xff0c;可以参考这篇文章从Linux下载下来的工程代码&#xff0c;这里建议直接使用vs系列打开不要用vscode打开&#xff0c;vscode对win下的cmake不友好&#xff0c;主要体现在报错机制无法直接定位&#xff0c;题主的环境是vs2022…

Kubernetes07:Service

Kubernetes07:Service 1、service存在的意义 因为Pod的IP是不断变化的&#xff0c;所以需要注册service防止pod失联 1&#xff09;为了防止Pod失联&#xff08;服务发现&#xff09; 2、定义一组Pod访问策略&#xff08;负载均衡&#xff09; 2、Pod和Service的关系-------通…

为什么要学习C++软件调试技术?掌握这类技术都有哪些好处?

目录 1、为什么要学习C软件调试技术&#xff1f; 1.1、IDE调试手段虽必不可少&#xff0c;但还不够 1.2、通过查看日志和代码去排查异常崩溃问题&#xff0c;费时费力&#xff0c;很难定位问题 1.3、有的问题很难复现&#xff0c;可能只在客户的环境才能复现 1.4、为了应对…

主打的就是I/O流,顺便把File复习了

文章目录1. File类1.1 预备知识1.2 创建文件1.3 文件的常用方法2. IO流2.1 InputStream2.2 OutputStream2.3 Reader2.4 Writer2.5 缓冲流2.6 转换流2.7 对象流2.8 打印流1. File类 1.1 预备知识 文件分隔符 Windows&#xff1a;D:\Soft\QQ\PluginLinux&#xff1a;D:/Soft/QQ…

SpringMVC使用 redis 实现缓存

简介 SpringMVC 中也可以将缓存标签和 redis 结合起来使用&#xff0c;其实此时缓存没有起作用&#xff0c;只是通过缓存的那几个注解来操作 redis 而已&#xff1b;SpringMVC 中整合 redis 比较麻烦的是注意版本冲突的问题&#xff0c;如下是官网有关于版本的要求 https://d…

【人脸识别】DDL:数据分布知识蒸馏思想,提升困难样本(遮挡、低分辨率等)识别效果

论文题目&#xff1a;《Improving Face Recognition from Hard Samples via Distribution Distillation Loss》 论文地址&#xff1a;https://arxiv.org/pdf/2002.03662v3.pdf 代码地址&#xff1a;https://github.com/HuangYG123/DDL 1.前言及相关工作 Large facial variatio…

秒懂算法 | 基于图神经网络的推荐算法

图神经网络(Graph Neural Networks,GNN)是近几年兴起的学科,用来作推荐算法自然效果也相当好,但是要学会基于图神经网络的推荐算法之前,需要对图神经网络自身有个了解。 图卷积网络(Graph Convolutional Networks,GCN)提出于2017年。GCN 的出现标志着图神经网络的出现。深度学习…

大家一起来找茬,新手第一次layout到底能挑出多少毛病?

有一个新手工程师在论坛上发了一篇帖子&#xff0c;把自己的处女PCB布线图贴出来。 如果不看其他网友的评论&#xff0c;你能看出多少问题呢&#xff1f;可以在留言区和我们互动哦~ 帖子里他还提出了自己的小见解&#xff1a;问一下&#xff0c;我觉得自动布线挺好用的啊&#…

汽车标定知识整理(一):标定简介与CCP报文协议简介

目录 一、什么是标定 二、XCP与CCP 三、CCP报文协议简介 1、CCP报文协议简介 &#xff08;1&#xff09;CRO&#xff1a;Command Receive Object &#xff0c;命令接收对象&#xff08;由Master -> Slave&#xff09; &#xff08;2&#xff09;DTO&#xff1a;Data T…

Kotlin 39. Dependency Injection依赖注入以及Hilt在Kotlin中的使用,系列2:手动依赖注入

一起来学Kotlin&#xff1a;概念&#xff1a;26. Dependency Injection依赖注入以及Hilt在Kotlin中的使用&#xff0c;系列2&#xff1a;手动依赖注入 此系列博客中&#xff0c;我们将主要介绍&#xff1a; Dependency Injection&#xff08;依赖注入&#xff09; 概念介绍。…

当IDEA加载一个MAVEN新项目时,加载不成功,无法加载依赖的解决方法

当IDEA加载一个MAVEN新项目时&#xff0c;加载不成功&#xff0c;无法加载依赖的解决方法 此文为练习项目时的错误记录 当使用IDEA引入一个MAVEN新项目时&#xff0c;点击Reload maven按钮加载不成功&#xff0c;显示如下图界面&#xff1a; 在项目中的代码显示报红&#xff0c…

urllib之ProxyHandler代理以及CookieJar的cookie内存传递和本地保存与读取的使用详解

处理更高级操作时(Cookies处理&#xff0c;代理设置)&#xff0c;需要一个强大的工具Handler&#xff0c;可以理解成各种处理器&#xff0c;有处理登录认证的、有处理Cookies的、有处理代理设置的。利用这些几乎可以做到HTTP请求中所有事情。当中urllib.request模块里的 BaseHa…

机器学习:基于朴素贝叶斯对花瓣花萼的宽度和长度分类预测

机器学习&#xff1a;基于朴素贝叶斯对花瓣花萼的宽度和长度分类预测 作者&#xff1a;AOAIYI 作者简介&#xff1a;Python领域新星作者、多项比赛获奖者&#xff1a;AOAIYI首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞…

MySQL实战解析底层---基础架构:一条SQL查询语句是如何执行的?

目录 前言 连接器 查询缓存 分析器 优化器 执行器 前言 平时使用数据库&#xff0c;看到的通常都是一个整体比如&#xff0c;有个最简单的表&#xff0c;表里只有一个 ID 字段&#xff0c;在执行下面这个查询语句时&#xff1a; 看到的只是输入一条语句&#xff0c;返回…

微电影广告的内容突破方案

微电影作为新媒体时代背景的产物&#xff0c;深受大众的欢迎&#xff0c;同时&#xff0c;微电影广告在微电影模式环境下应运而生&#xff0c;以自己独特的传播优势&#xff0c;俘获了大量企业主的青睐&#xff0c;也获得了广大青年群体的喜爱。微电影广告欲确保可持续发展&…

Android App异常崩溃处理详解

异常崩溃是Android项目中一个棘手的问题&#xff0c;即使你做了很多的try - catch处理&#xff0c;也不能保证不崩溃&#xff0c;一旦崩溃就会出现下图的弹窗&#xff0c;xx应用就会停止运行这种体验对于用户来说是很差的&#xff0c;所以很明显我们做的app已经崩溃了。 像现在…

社科院与杜兰大学金融管理硕士项目——在这里共同改变,一起前行

人这一生&#xff0c;要走很长的路&#xff0c;才能确定前行的方向&#xff0c;在路上遇到很多的人&#xff0c;才知道与谁同行。在人生旅程中&#xff0c;保持怎样的姿态前行&#xff0c;往往与身边的人有很大关系。身边的人都很努力&#xff0c;你也会跟着努力上进。怀揣着在…

Synchronized,我要一层一层剥开你的心

三种应用方式 修饰实例方法&#xff0c;作用于当前实例加锁&#xff0c;进入同步代码前要获得当前实例的锁。修饰静态方法&#xff0c;作用于当前类对象加锁&#xff0c;进入同步代码前要获得当前类对象的锁。修饰代码块&#xff0c;指定加锁对象&#xff0c;对给定对象加锁&a…

TypeScript 使用 ES6 解构骚操作

TypeScript 使用 ES6 解构骚操作 文章目录TypeScript 使用 ES6 解构骚操作一、TypeScript 对象解构二、TypeScript 函数参数解构四、参考资料&#x1f498;五、推荐博文&#x1f357;一、TypeScript 对象解构 我们都知道 ES6 的数据解构功能很强大&#xff0c;一行命令就能够声…