- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
Netty 是由 JBOSS 开源的一款 NIO 网络编程框架,可用于快速开发网络应用。netty.io 官网中对 Netty 的介绍是“Netty 是一个异步的、基于事件驱动的网络应用框架,用于快速开发高性能的服务端和客户端”。
总的来说,Netty 是一个基于 NIO 和可扩展的事件模型的客户端和服务端框架,可以极大地简化基于 TCP、UDP 等协议的网络服务。并且 Netty 对于各种传输类型(阻塞或非阻塞式 Socket)及通信方式(HTTP 或 WebSocket)都提供了统一的 API 接口,提供了灵活的可扩展性,高度可自定义的线程模型(单线程、线程池等 ),支持使用无连接的数据报(UDP)进行通信,具有高吞吐量、低延迟、资源消耗低、最低限度的内存复制等特性。除了优越的性能外,Netty 还完整地支持 SSL/TLS 和 StartTLS 等加密传输协议,保证了数据传输的安全性。
在实际使用时,Netty 可作为 Socket 编程的中间件:也可以和 Protobuf 等技术结合使用,实现一个 RPC 框架,实现远程过程调用;或者作为一个机遇 WebSocket 的厂连接服务器,实现客户端与服务端的长连接通信。
Netty 程序可以按以下“套路”编写:依次是主程序类,自定义初始化器、自定义处理器。
这里介绍一个简单的服务端开发案例。
a 通过 serverBootStrap 注册 bossGroup 和 workerGroup 两个事件循环组,其中 bossGroup 用于获取客户端连接,workerGroup 用于处理客户端连接,类似常见 Master-Slave 结构。
b 将 Channel 类型指定为 NioServerSocketChannel,并在服务启动时关联自定义初始化器 MyNettyServerInitializer,从而进行初始化操作。
MyNettyServerInitializer,继承自 Netty 提供的初始化器 ChannelInitializer。
Netty 封装了各种各样的内置处理器,用于实现各种功能。并且 ChannelInitializer 的 initChannel() 方法会在某个连接注册到 Channel 后立即被触发调用。因此,可以根据业务需求,在 initChannel() 中添加若干个 Netty 内置处理器,利用 Netty 强大的类库直接处理大部分业务。最后再在 initChannel() 中添加一个自定义处理器,用于实现特定业务的具体功能。
MyNettyServerHandler,继承自 SimpleChannelInboundHandler,该父类的 channelRead0() 方法可以接收客户端的所有请求,并作出响应。
package netty.http;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class MyNettyServerTest {
public static void main(String[] args) {
/*
EventLoopGroup:事件循环组,是一个线程池,也是一个死循环,用于不断的接收用户请求
bossGroup:用于监听及建立连接,并把每一个连接抽象为一个 channel ,最后将连接再交给 workerGroup 处理
workerGroup:真正的处理连接
*/
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// ServerBootstrap:服务端启动时的初始化操作
ServerBootstrap serverBootstrap = new ServerBootstrap();
// 将 bossGroup 和 workerGroup 注册到服务端的 Channel 上,并注册一个服务端的初始化器NettyServerInitializer(该初始化器中的initChannel()方法,会在连接被注册后立刻执行);最后将端口号绑定到8888
ChannelFuture channelFuture = serverBootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new MyNettyServerInitializer()).bind(8888).sync();
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
package netty.http;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
public class MyNettyServerInitializer extends ChannelInitializer<SocketChannel> {
// 连接被注册后,立刻执行此方法
protected void initChannel(SocketChannel sc) throws Exception {
ChannelPipeline pipeline = sc.pipeline();
// 加入 netty 提供的处理器。
// 语法:pipeline.addLast(定义处理器的名字,处理器);
// HttpServerCodec:对请求和响应进行编码、解码
pipeline.addLast("HttpServerCodec", new HttpServerCodec());
// 增加自定义处理器 NettyServerHandler,用于实际处理请求,并给出响应
pipeline.addLast("MyNettySocketServerHandler", new MyNettyServerHandler());
}
}
package netty.http;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
import java.net.URI;
// 自定义处理器:用于输出 hello netty
public class MyNettyServerHandler extends SimpleChannelInboundHandler<HttpObject> {
// channelRead0() 方法:接收客户端请求,并且作出响应;类似于 Servlet 中的 doGet()、doPost()等方法
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof HttpRequest) {
HttpRequest httpRequest = (HttpRequest) msg;
URI uri = new URI(httpRequest.uri());
if (!"/favicon.ico".equals(uri.getPath())) {
System.out.println("channelRead0 invoke...");
// ByteBuf对象:定义响应的内容
ByteBuf content = Unpooled.copiedBuffer("Hello Netty", CharsetUtil.UTF_8);
// FullHttpResponse 对象:响应对象,定义响应的具体信息
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
// content.readableBytes() :响应内容的长度
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
// 将响应 返回给客户端
ctx.writeAndFlush(response);
}
}
}
// 当增加新的处理器时,触发此方法
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("1.handlerAdded(),增加了新的处理器...");
super.handlerAdded(ctx);
}
// 当通道被注册到一个事件循环组EventLoop上时,执行此方法
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("2.channelRegistered(),通道被注册...");
super.channelRegistered(ctx);
}
// 当通道处于活跃状态(连接到某个远端,可以收发数据)时,执行此方法
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("3.channelActive(),通道连接到了远端,处于活跃状态...");
super.channelActive(ctx);
}
// 当通道处于非活跃状态(与远端断开了连接)时,执行此方法
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("4.channelInactive(),通道远端断开了连接,处于非活跃状态... ");
super.channelInactive(ctx);
}
// 当通道被取消注册时,执行此方法
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("5.channelUnregistered(),通道被取消了注册...");
super.channelUnregistered(ctx);
}
// 当程序发生异常时,执行此方法
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
1.handlerAdded(),增加了新的处理器...
1.handlerAdded(),增加了新的处理器...
2.channelRegistered(),通道被注册...
2.channelRegistered(),通道被注册...
3.channelActive(),通道连接到了远端,处于活跃状态...
3.channelActive(),通道连接到了远端,处于活跃状态...
channelRead0 invoke...
4.channelInactive(),通道远端断开了连接,处于非活跃状态...
5.channelUnregistered(),通道被取消了注册...
4.channelInactive(),通道远端断开了连接,处于非活跃状态...
5.channelUnregistered(),通道被取消了注册...
我们正在创建一个 n 层 Silverlight LOB 应用程序,并且正在考虑使用 .NET RIA 服务。我们不清楚这与我们当前的 WCF 服务 API 的关系在哪里。我们当前的架构是: 银光
上下文:我在celery + rabbitmq堆栈上有一个主工作系统。 系统已docker化(此处未提供worker服务) version: '2' services: rabbit:
我是 Windows Azure 新手,我正在尝试将我的 Web 应用程序部署到 Windows Azure。在我的应用程序中,我使用了一些 Web 服务,现在我想知道如何在 Windows Azur
因此,根据我对服务的了解,自定义对象似乎是写入服务以返回数据的方式。如果我正在编写将用于 1) 填充数据库或 2) 为网站提供信息的服务,是否有返回数据集/数据表而不是包含所有这些的自定义对象列表的用
我在 google 和 stackoverflow 上都找过答案,但似乎找不到。我正在尝试将 azure 实验的输出获取到应用程序。我使用 ibuildapp 和谷歌表单制作了该应用程序。如何使用 g
我不小心删除了 kubernetes svc: service "kubernetes" deleted 使用: kubectl delete svc --all 我该怎么办?我只是想删除服务,以便
我正在努力确定解决网络服务问题的最有效方法。 我的情况:我正在开发一个 Android 应用程序,它通过 Web 服务从 mysql 数据库(在我自己的服务器 PC 上)存储和检索数据。用户按下提交按
我一直在翻阅 Android 文档,我很好奇。什么时候绑定(bind)服务而不是不绑定(bind)服务?它提供了哪些优点/限制? 最佳答案 When would you bind a service
我试图从架构的角度理解 hive,我指的是 Tom White 关于 Hadoop 的书。 我遇到了以下关于配置单元的术语:Hive Services、hiveserver2、metastore 等。
我的问题:安装服务后我无法导航到基地址,因为服务不会继续运行(立即停止)。我需要在服务器或我的机器上做些什么才能使 baseAddress 有效吗? 背景:我正在尝试学习如何使用 Windows 服务
我正在努力就 Web 服务的正确组织做出决定。我应该有多个 ASMX 来代表 Web 服务中的不同功能,还是应该有一个 ASMX? 如果我有多个 ASMX,这不构成多个 Web 服务吗? 如果我只有一
我正在从事一个在 azure 平台上提供休息服务的项目。该服务由 iPhone 客户端使用,这是选择其余方法的重要原因之一。 我们希望通过 AccessControlService(ACS) 并使用
我是 Ionic 新手,正在使用 Ionic 3.9.2 我有几个终端命令来为我的 ionic 应用程序提供服务,但是,我没有发现这两个命令之间有任何区别。 ionic serve 和 ionic s
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
作为项目的一部分,我期待着问这个问题。我过去有开发和使用 Web 服务的经验,并且非常熟悉这些服务。但是,有人告诉我,作为下一个项目的一部分,我将需要使用“安全”的 Web 服务。您能否提供一些见解,
我浏览了很多关于这个问题的信息,但找不到解决方案。这里的问题是,我想使用 Apache Cordova 和 Visual Studio 连接到 wcf。因此,如果有人找到合适的工作解决方案,请发布链接
我在 Windows 服务中托管了一个 WCF(从 MS 网站示例中选取),我可以使用 SOAP UI 访问和调用方法。但是,当我尝试使用 jquery 从 Web 应用程序调用相同的方法时,我不断收
我们构建了一个 Android 应用程序,它从 Android 向我的 PHP 服务器发送 HTTP 请求。作为响应,Web 服务将 JSON 对象发送到 Android 应用程序以显示结果。 就像其
我想在 android 应用程序中调用 soap web 服务,它需要一个枚举值作为参数,它是一个标志枚举。如何从 Android 应用程序将一些值作为标志枚举传递给此 Web 服务方法? 我使用 K
我尝试在模拟器上安装 Google Play。我已按照 Google Dev Site 中的说明进行操作. 使用 ADV 管理器似乎没问题,设备的目标是 Google API 版本 22,但是当我运行
我是一名优秀的程序员,十分优秀!