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

Gateway集成Netty服务的更多相关文章

  1. asp.net中关于Microsoft 信息完整性、隐私性等集成信息安全服务服务 integrated security=SSPI

    string strConn=@"server=(local)\SQLExpress;database=AdventureWorks;integrated security=SSPI&quo ...

  2. Redola.Rpc 集成 Consul 服务发现

    Redola.Rpc 解决了什么问题? Redola.Rpc 是一个使用 C# 开发的 RPC 框架,代码开源在 GitHub 上.目前版本仅支持 .NET Framework 4.6 以上版本,未来 ...

  3. idea/eclipse下Maven工程集成web服务(tomcat、jetty)

     idea/eclipse下Maven工程集成web服务 转载请注明出处:http://www.cnblogs.com/funnyzpc/p/8093554.html 应用服务器最常用的一般有这哥仨: ...

  4. 【Netty源码分析】Netty服务端bind端口过程

    这一篇博客我们介绍一下Netty服务端绑定端口的过程,我们通过跟踪代码一直到NIO原生绑定端口的操作. 绑定端口操作 ChannelFuture future = serverBootstrap.bi ...

  5. Netty 服务端启动过程

    在 Netty 中创建 1 个 NioServerSocketChannel 在指定的端口监听客户端连接,这个过程主要有以下  个步骤: 创建 NioServerSocketChannel 初始化并注 ...

  6. Http 调用netty 服务,服务调用客户端,伪同步响应.ProtoBuf 解决粘包,半包问题.

    实际情况是: 公司需要开发一个接口给新产品使用,需求如下 1.有一款硬件设备,客户用usb接上电脑就可以,但是此设备功能比较单一,所以开发一个服务器程序,辅助此设备业务功能 2.解决方案,使用Sock ...

  7. 7.4 服务远程暴露 - 创建Exporter与启动netty服务端

    为了安全:服务启动的ip全部使用10.10.10.10 远程服务的暴露总体步骤: 将ref封装为invoker 将invoker转换为exporter 启动netty 注册服务到zookeeper 订 ...

  8. Netty 服务端创建

    参考:http://blog.csdn.net/suifeng3051/article/details/28861883?utm_source=tuicool&utm_medium=refer ...

  9. 如何通过 AAR 形式集成 leakcanary-android 服务

    如何通过 AAR 形式集成 leakcanary-android 服务 如何通过在线引用的方式拿到所有相关的依赖项文件? #1.禁用 Gradle 离线模式 #2.按照文档要求添加项目依赖 #3.Sy ...

  10. 2、Dubbo源码解析--服务发布原理(Netty服务暴露)

    一.服务发布 - 原理: 首先看Dubbo日志,截取重要部分: 1)暴露本地服务 Export dubbo service com.alibaba.dubbo.demo.DemoService to ...

随机推荐

  1. JavaScript入门⑥-WEB浏览器API

    JavaScript入门系列目录 JavaScript入门①-基础知识筑基 JavaScript入门②-函数(1)基础{浅出} JavaScript入门③-函数(2)原理{深入}执行上下文 JavaS ...

  2. whistle证书过期或不信任

    1. 安卓设备 , whistle抓包https安装证书后无法访问网络,报证书过期或不信任 2. 查看证书日期是到2030年,没有过期 3. 删除证书 重新安装时候证书选择 "VPN或应用& ...

  3. Sqlserver分布式跨数据库查询、Join,以及分布式事务

    简言: 这篇文章我要谈一谈SQL Server分布式跨服务器查询,多表Join,以及分布式事务的处理 SqlServer跨服务器查询的方式 以往自己才疏学浅,学习了一波之后,在这记录下来. 1. 使用 ...

  4. 使用pip命令安装库时提示Could not build wheels for six, since package 'wheel' is not installed

    在使用pip命令安装库时提示Could not build wheels for six, since package 'wheel' is not installed 解决以上问题可用 pip in ...

  5. MySQL中这14个牛逼的功能,惊艳到我了!!!

    前言 我最近几年用MYSQL数据库挺多的,发现了一些非常有用的小玩意,今天拿出来分享到大家,希望对你会有所帮助. 1.group_concat 在我们平常的工作中,使用group by进行分组的场景, ...

  6. nuxt之vuex的使用

    先来了解一下官网:https://www.nuxtjs.cn/guide/vuex-store 一.首先在 store 文件下新建一个index.js文件 const state = () => ...

  7. JavaScript:控制跳转:break、continue与标签

    在循环结构中,经常需要使用关键字break和continue来控制跳转: 遇到break,就会跳出循环结构,执行循环体后面的代码: 遇到continue,就会跳出本次循环,进入下一次循环: 那么,假如 ...

  8. 10、比较Bigdecimal类型是否相等的方法

    一.Bigdecimal.equals()详解: Bigdecimal的equals方法不仅仅比较值的大小是否相等,首先比较的是scale(scale是bigdecimal的保留小数点位数),也就是说 ...

  9. [R语言] 基于R语言实现树形图的绘制

    树状图(或树形图)是一种网络结构.它由一个根节点组成,根节点产生由边或分支连接的多个节点.层次结构的最后一个节点称为叶.本文主要基于R语言实现树形图的绘制.关于python实现树形图的绘制见:基于ma ...

  10. 通过Docker启动Solace,并在Spring Boot通过JMS整合Solace

    1 简介 Solace是一个强大的实时性的事件驱动消息队列.本文将介绍如何在Spring中使用,虽然代码使用的是Spring Boot,但并没有使用相关starter,跟Spring的整合一样,可通用 ...