简介

在之前的文章中,我们提到了在netty的客户端通过使用Http2FrameCodec和Http2MultiplexHandler可以支持多路复用,也就是说在一个连接的channel基础上创建多个子channel,通过子channel来处理不同的stream,从而达到多路复用的目的。

既然客户端可以做到多路复用,同样的服务器端也可以,今天给大家介绍一下如何在netty的服务器端打造一个支持http2协议的多路复用服务器。

多路复用的基础

netty中对于http2多路复用的基础类是Http2FrameCodec、Http2MultiplexHandler和Http2MultiplexCodec。

Http2FrameCodec是将底层的HTTP/2 frames消息映射成为netty中的Http2Frame对象。

有了Http2Frame对象就可以通过Http2MultiplexHandler对新创建的stream开启不同的channel。

Http2MultiplexCodec是Http2FrameCodec和Http2MultiplexHandler的结合体,但是已经不再被推荐使用了。

因为Http2FrameCodec继承自Http2ConnectionHandler,而Http2MultiplexHandler继承自Http2ChannelDuplexHandler,所以这两个类可以同时在客户端和服务器端使用。

客户端使用Http2FrameCodecBuilder.forClient().build()来获得Http2FrameCodec,而服务器端通过Http2FrameCodecBuilder.forServer().build()来获得Http2FrameCodec。

多路复用在server端的使用

配置TLS处理器

对于服务器端,同样需要处理TLS和普通clear text两种情况。对于TLS来说,我们需要自建ProtocolNegotiationHandler继承自ApplicationProtocolNegotiationHandler,然后实现configurePipeline方法,在其中分别处理http2和http1.1的连接:

    protected void configurePipeline(ChannelHandlerContext ctx, String protocol) {
if (ApplicationProtocolNames.HTTP_2.equals(protocol)) {
//添加多路复用支持
ctx.pipeline().addLast(Http2FrameCodecBuilder.forServer().build());
ctx.pipeline().addLast(new Http2MultiplexHandler(new CustMultiplexHttp2Handler()));
return;
} if (ApplicationProtocolNames.HTTP_1_1.equals(protocol)) {
ctx.pipeline().addLast(new HttpServerCodec(),
new HttpObjectAggregator(MAX_CONTENT_LENGTH),
new CustHttp1Handler("ALPN Negotiation"));
return;
} throw new IllegalStateException("未知协议: " + protocol);
}

首先添加Http2FrameCodec,然后添加Http2MultiplexHandler。因为Http2MultiplexHandler已经封装了多路复用的细节,所以自定义的handler只需要实现正常的消息处理逻辑即可。

因为Http2FrameCodec已经对消息进行了转换成为HTTP2Frame对象,所以只需要处理具体的Frame对象:

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof Http2HeadersFrame) {
onHeadersRead(ctx, (Http2HeadersFrame) msg);
} else if (msg instanceof Http2DataFrame) {
onDataRead(ctx, (Http2DataFrame) msg);
} else {
super.channelRead(ctx, msg);
}
}

配置clear text upgrade

对于h2c的升级来说,需要向pipline中传入sourceCodec和upgradeHandler两个处理器。

sourceCodec可以直接使用HttpServerCodec。

upgradeHandler可以使用HttpServerUpgradeHandler。

HttpServerUpgradeHandler的构造函数需要传入一个sourceCodec和一个upgradeCodecFactory。

sourceCodec我们已经有了,再构造一个upgradeCodecFactory即可:

    private static final UpgradeCodecFactory upgradeCodecFactory = protocol -> {
if (AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocol)) {
return new Http2ServerUpgradeCodec(
Http2FrameCodecBuilder.forServer().build(),
new Http2MultiplexHandler(new CustMultiplexHttp2Handler()));
} else {
return null;
}
};

从代码中可以看出,upgradeCodecFactory内部又调用了Http2FrameCodec和Http2MultiplexHandler。这和使用TLS的处理器是一致的。

        final ChannelPipeline p = ch.pipeline();
final HttpServerCodec sourceCodec = new HttpServerCodec();
p.addLast(sourceCodec);
p.addLast(new HttpServerUpgradeHandler(sourceCodec, upgradeCodecFactory));

总结

通过上述方式,就可以创建出支持多路复用的http2 netty服务器了。

本文的例子可以参考:learn-netty4

本文已收录于 http://www.flydean.com/33-netty-multiplex-http2server/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

netty系列之:性能为王!创建多路复用http2服务器的更多相关文章

  1. netty系列之:手持framecodec神器,创建多路复用http2客户端

    目录 简介 配置SslContext 客户端的handler 使用Http2FrameCodec Http2MultiplexHandler和Http2MultiplexCodec 使用子channe ...

  2. netty系列之:轻轻松松搭个支持中文的服务器

    目录 简介 netty的HTTP支持 netty中使用HTTP的原理 100 (Continue) Status 为netty搭建HTTP服务器 总结 简介 之前讲了那么多关于netty的文章,都是讲 ...

  3. 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ?

    [读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ? 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...

  4. Netty 系列之 Netty 高性能之道 高性能的三个主题 Netty使得开发者能够轻松地接受大量打开的套接字 Java 序列化

    Netty系列之Netty高性能之道 https://www.infoq.cn/article/netty-high-performance 李林锋 2014 年 5 月 29 日 话题:性能调优语言 ...

  5. Netty系列之Netty百万级推送服务设计要点

    1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...

  6. 【netty】Netty系列之Netty百万级推送服务设计要点

    1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...

  7. Netty系列之Netty百万级推送服务设计要点(转)

    1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...

  8. 3. 彤哥说netty系列之Java BIO NIO AIO进化史

    你好,我是彤哥,本篇是netty系列的第三篇. 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识. 简介 上一章我们介绍了IO的五种模型,实际上Java只支持其中的三种,即BIO/NIO/ ...

  9. 5. 彤哥说netty系列之Java NIO核心组件之Channel

    你好,我是彤哥,本篇是netty系列的第五篇. 简介 上一章我们一起学习了如何使用Java原生NIO实现群聊系统,这章我们一起来看看Java NIO的核心组件之一--Channel. 思维转变 首先, ...

随机推荐

  1. Databend 设计概述 | 白皮书

    Databend 是一个开源的.完全面向云架构的新式数仓,它提供快速的弹性扩展能力,并结合云的弹性.简单性和低成本,使 Data Cloud 构建变得更加容易. Databend 把数据存储在像 AW ...

  2. Salesforce Consumer Goods Cloud 浅谈篇二之门店产品促销的配置

    本篇参考:https://documentation.b2c.commercecloud.salesforce.com/DOC1/index.jsp?topic=%2Fcom.demandware.d ...

  3. dedecms被挂马排毒的过程

    又经历了一次dedecms被挂马排毒的过程,排毒过程在这里跟大家分享一下. 挂马之后,网站的表现形式: 直接访问网站没有任何问题,从百度搜索的关键词访问网站,就跳转到另外一个网站. 根据我原来的排毒经 ...

  4. SQL中单引号和双引号

    比如说: String sql = "select * from clients where logname='" + name + "'and password='&q ...

  5. [loj3330]猜数游戏

    如果两个数$a_{x}$和$a_{y}$,$\exists 0<i,a_{x}^{i}\equiv a_{y}(mod\ p^{k})$,就建一条$x$到$y$的有向边,再对这张图强连通分量缩点 ...

  6. 力扣 - 剑指 Offer 46. 把数字翻译成字符串

    题目 剑指 Offer 46. 把数字翻译成字符串 思路1(递归,自顶向下) 这题和青蛙跳台阶很类似,青蛙跳台阶说的是青蛙每次可以跳一层或者两层,跳到第 n 层有多少种解法,而这题说的是讲数字翻译成字 ...

  7. Codeforces 521E - Cycling City(点双连通分量+分类讨论)

    Codeforces 题面传送门 & 洛谷题面传送门 大家都是暴力找生成树然后跳路径,代码不到 50 行(暴论)的一说--好,那本蒟蒻决定提供一种代码 150 行,但复杂度也是线性的分类讨论做 ...

  8. Codeforces 626G - Raffles(贪心+堆)

    题面传送门 考虑对于固定的彩票池 \(i\),我们假设现在押了 \(x\) 张彩票.利用差分的思想,从 \(x\) 张彩票变为 \(x+1\) 张时,期望的变化量 \(\Delta E=\dfrac{ ...

  9. Codeforces 1188D - Make Equal(dp)

    Codeforces 题目传送门 & 洛谷题目传送门 首先我们考虑枚举最后这 \(n\) 个数变成的值 \(v\),那么需要的操作次数即为 \(\sum\limits_{i=1}^n\text ...

  10. Notepad++—显示代码对齐是使用了制表符还是空格

    使用Notepad++打开脚本,勾选"显示空格与制表符",此时你会看到代码对齐使用了制表符与空格 右箭头:TAB:空格:点: 参考:https://www.cnblogs.com/ ...