Netty框架进阶篇 - 分析和实战内置的编解码器及ChannelHandler

本文详细介绍了如何基于Netty构建HTTP/HTTPS应用程序,探讨了HTTP协议的编解码器,包括HTTP聚合消息、压缩、SSL配置,并通过实战示例展示了使用。同时,文章讨论了空闲连接和超时的处理,以及Protocol Buffers序列化的实现,包括消息对象模型构建和实战应用。
摘要由CSDN通过智能技术生成


前言

Netty为许多通用协议提供了编解码器和处理器,几乎可以开箱即用,这减少了你在那些相当繁琐的事务上本来会花费的时间与精力,本文会结合一些案例进行分析和应用内置的编解码器

基于Netty构建HTTP/HTTPS应用程序

Netty内置的一系列编解码器和ChannelHandler,其中就有可以支持用来处理HTTP和HTTPS协议的

HTTP协议相关编解码器

HTTP是基于请求/响应模式的:客户端向服务器发送一个 HTTP 请求,然后服务器将会返回一个 HTTP 响应。Netty提供了多种编码器和解码器以简化对这个协议的使用

HTTP请求的组成部分:
在这里插入图片描述
HTTP响应的组成部分:
在这里插入图片描述
从上面的图可以看出,一个HTTP 请求/响应可能由多个数据部分组成,并且总是以一个LastHttpContent部分作为结束。其中FullHttpRequest和FullHttpResponse 消息是特殊的子类型,分别代表了完整的请求和响应。所有类型的 HTTP 消息(FullHttpRequest、 LastHttpContent 等等)都实现了 HttpObject 接口

HTTP解码器和编码器:

名称 描述
HttpRequestEncoder 将 HttpRequest、HttpContent 和 LastHttpContent 消息编码为字节
HttpResponseEncoder 将 HttpResponse、HttpContent 和 LastHttpContent 消息编码为字节
HttpRequestDecoder 将字节解码为 HttpRequest、HttpContent 和 LastHttpContent 消息
HttpResponseDecoder 将字节解码为 HttpResponse、HttpContent 和 LastHttpContent 消息
HttpClientCodec 将客户端请求和响应做一个组合
HttpServerCodec 将服务端请求和响应做一个组合

HTTP聚合消息

由于HTTP的请求和响应可能由许多部分组成,因此你需要聚合它们以形成完整的消息。为了消除这项繁琐的任务,Netty 提供了一个聚合器HttpObjectAggregator,它可以将多个消息部分合并为 FullHttpRequest 或者 FullHttpResponse 消息。通过这样的方式,你将总是看到完整的消息内容

由于消息分段需要被缓存,直到可以转发一个完整的消息给下一个ChannelInboundHandler,所以这个操作有轻微的开销,其所带来的好处便是你不必关心消息碎片了

HTTP压缩

当使用 HTTP 时,都会建议开启压缩功能以尽可能多地减小传输数据的大小。虽然压缩会带来一些 CPU 时钟周期上的开销,但是通常来说它都是一个好主意,特别是对于文本数据来说

Netty 为压缩提供了一个HttpContentCompressor处理器,为解压缩提供了一个HttpContentDecompressor处理器,它们同时支持gzip和deflate编码

注意:如果你使用的JDK为1.6或者更早的版本,那么需要将JZlib (www.jcraft.com/jzlib/ ) 添加到CLASSPATH中以支持压缩功能。在Maven中,需要加入依赖:

<dependency>
       <groupId>com.jcraft</groupId>
       <artifactId>jzlib</artifactId>
       <version>1.1.3</version>
</dependency>

配置SSL,启用HTTPS

Netty通过一个名为SslHandler的ChannelHandler来支持SSL/TLS,其内部使用SSLEngine来完成实际的工作。而启用HTTPS只需要将 SslHandler 添加到 ChannelPipeline 的 ChannelHandler 组合中即可

实战

自定义HTTP Server

/**
 * 通过Netty自定义Http Server
 */
public class MyHTTPServer {
   

	private static EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
	private static ServerBootstrap bootstrap = new ServerBootstrap();
	
	private static final int PORT = 8761;
	private static final boolean IS_SSL = false; //是否开启SSL认证
	
	public static void startServer() throws SSLException, CertificateException{
   
		SslContext sslContext = null;
		if(IS_SSL){
   
			//签名认证
			SelfSignedCertificate selfSignedCertificate= new SelfSignedCertificate();
			sslContext = SslContextBuilder.forServer(selfSignedCertificate.certificate(),selfSignedCertificate.privateKey()).build();
		}
		try {
   
			bootstrap.group(eventLoopGroup).
			  channel(NioServerSocketChannel.class).
			  localAddress(PORT).childHandler(new HttpInitHandler(sslContext));
			
			ChannelFuture future=bootstrap.bind().sync();
			future.channel().closeFuture().sync();
		} catch (Exception e) {
   
			e.printStackTrace();
		}finally{
   
			eventLoopGroup.shutdownGracefully();
		}
	}
	
	public static void main(String[] args) {
   
		//启动服务
		try {
   
			startServer();
		} catch (SSLException e) {
   
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (CertificateException e) {
   
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

服务端添加相关的ChannelHandler

public class HttpInitHandler extends ChannelInitializer<SocketChannel>{
   

	private SslContext sslContext;
	
	public HttpInitHandler(SslContext sslContext) {
   
		super();
		this.sslContext = sslContext;
	}
	@Override
	protected void initChannel(SocketChannel ch) throws Exception {
   
		if(null!=sslContext){
   
			SSLEngine engine=sslContext.newEngine(ch.alloc());
			//将SslHandler添加到ChannelPipeline中以使用HTTPS
			ch.pipeline().addFirst(new SslHandler(engine));
		}
		//添加HTTP请求的解码器
		ch.pipeline
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值