netty系列之:一个价值上亿的网站速度优化方案
简介
其实软件界最赚钱的不是写代码的,写代码的只能叫马龙,高级点的叫做程序员,都是苦力活。那么有没有高大上的职业呢?这个必须有,他们的名字就叫做咨询师。
咨询师就是去帮企业做方案、做架构、做优化的,有时候一个简单的代码改动、一个架构的调整都可以让软件或者流程更加高效的运行,从而为企业节省上亿的开支。
今天除了要给大家介绍一下如何在netty中同时支持http和https协议之外,还给大家介绍一个价值上亿的网站数据优化方案,有了这个方案,年薪百万不是梦!
本文的目标
本文将会给大家介绍一下如何在一个netty服务中同时支持http和http2两种协议,在这两个服务器中,提供了对多图片的访问支持,我们介绍如何从服务器端返回多个图片。最后介绍一个价值上亿的速度优化方案,肯定大家会受益匪浅。
支持多个图片服务
对于服务器端来说,是通过ServerBootstrap来启动服务的,ServerBootstrap有一个group方法用来指定acceptor的group和client的group。
public ServerBootstrap group(EventLoopGroup group)
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup)
当然你可以指定两个不同的group,也可以指定同一个group,它提供了两个group方法,效果上没太大的区别。
这里我们现在主服务器中创建一个EventLoopGroup,然后将其传入到ImageHttp1Server和ImageHttp2Server中。然后分别在两个server中调用group方法,然后配置handler即可。
先看一下ImageHttp1Server的构造:
ServerBootstrap b = new ServerBootstrap();
b.option(ChannelOption.SO_BACKLOG, 1024);
b.group(group).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch){
ch.pipeline().addLast(new HttpRequestDecoder(),
new HttpResponseEncoder(),
new HttpObjectAggregator(MAX_CONTENT_LENGTH),
new Http1RequestHandler());
}
});
我们传入了netty自带的HttpRequestDecoder、HttpResponseEncoder和HttpObjectAggregator。还有一个自定义的Http1RequestHandler。
再看一下ImageHttp2Server的构造:
ServerBootstrap b = new ServerBootstrap();
b.option(ChannelOption.SO_BACKLOG, 1024);
b.group(group).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(sslCtx.newHandler(ch.alloc()), new CustProtocolNegotiationHandler());
}
});
为了简单起见,我们默认如果从http来访问的话,就使用http1服务,如果是从https来访问的话,就使用http2服务。
所以在http2服务中,我们只需要自定义ProtocolNegotiationHandler即可,而不用处理clear text升级的请求。
http2处理器
在TLS环境中,我们通过自定义CustProtocolNegotiationHandler,继承自ApplicationProtocolNegotiationHandler来进行客户端和服务器端协议的交互。
对于http2协议来说,使用了netty自带的InboundHttp2ToHttpAdapterBuilder和HttpToHttp2ConnectionHandlerBuilder将http2 frame转换成为http1的FullHttpRequest对象。这样我们直接处理http1格式的消息即可。
转换过程如下:
DefaultHttp2Connection connection = new DefaultHttp2Connection(true);
InboundHttp2ToHttpAdapter listener = new InboundHttp2ToHttpAdapterBuilder(connection)
.propagateSettings(true).validateHttpHeaders(false)
.maxContentLength(MAX_CONTENT_LENGTH).build();
ctx.pipeline().addLast(new HttpToHttp2ConnectionHandlerBuilder()
.frameListener(listener)
.connection(connection).build());
ctx.pipeline().addLast(new Http2RequestHandler());
转换转换的http2 handler和普通的http1的handler唯一不同的是需要额外设置一个streamId属性到请求头和响应头中。
并且不需要处理http1特有的100-continue和KeepAlive。其他的和http1 handler没什么两样。
处理页面和图像
因为我们使用转换器将http2的frame转换成了http1的普通对象,所以对请求相应的页面和图像来说,跟http1的处理没什么太大区别。
对于页面来说,我们需要获取要返回的html,然后设置CONTENT_TYPE为"text/html; charset=UTF-8",返回即可:
private void handlePage(ChannelHandlerContext ctx, String streamId, FullHttpRequest request) throws IOException {
ByteBuf content =ImagePage.getContent();
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, content);
response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
sendResponse(ctx, streamId, response, request);
}
对于图像来说,我们获取到要返回的图像,将其转换成为ByteBuf,然后设置CONTENT_TYPE为"image/jpeg",返回即可:
private void handleImage(String id, ChannelHandlerContext ctx, String streamId,
FullHttpRequest request) {
ByteBuf image = ImagePage.getImage(parseInt(id));
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, image);
response.headers().set(CONTENT_TYPE, "image/jpeg");
sendResponse(ctx, streamId, response, request);
}
这样,我们就能够在netty服务器端同时处理页面请求和图片请求了。
价值上亿的速度优化方案
终于要到本文中最精彩的部分了,价值上亿的速度优化方案是什么呢?
在讲这个方案之前,先给大家讲一个抗洪抢险的故事。有两个县都住在一条大河的旁边。这条大河很不安稳,经常会发洪灾,但是两个县的县长做法很不同。
A县的县长认真负责,派人定期巡逻检查所属的河段,筑堤、种树、巡视,一刻都放松,在他的任期平平安安,没有发生任何洪水溃堤的情况。
B县的县长从来不巡检,一道河水泛滥的时候,B县长就组织人抗洪抢险,然后媒体全都报道的是B县长抗洪的丰功伟绩,最后B县长由于政绩突出,升任市长。
好了,故事讲完了,接下来是我们的优化。不管是用户请求页面还是图片,最终都需要调用ctx.writeAndFlush(response)方法进行响应回写。
如果将其放入一个定时任务中,来定时执行,如下所示:
ctx.executor().schedule(new Runnable() {
@Override
public void run() {
ctx.writeAndFlush(response);
}
}, latency, TimeUnit.MILLISECONDS);
那么服务器在经过latency指定的毫秒之后,才会发送对应的响应。比如这里我们设置latency的值为5秒。
当然5秒是不能够让人满意的,于是领导或者客户找到你,说让你给优化一下。你说这个性能问题是很难的,涉及到了麦克斯韦方程组和热力学第三定律,需要一个月时间。领导说好,撸起袖子加油干,下个月给你工资涨50%。
一个月后,你把latency改成2.5秒,性能提升了100%,这个优化值不值几个亿?
总结
当然,上一节给大家开个玩笑,不过在netty响应中使用定时任务的技巧,大家也应该牢牢掌握,原因你懂的!
本文的例子可以参考:learn-netty4
本文已收录于 http://www.flydean.com/34-netty-multiple-server/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
netty系列之:一个价值上亿的网站速度优化方案的更多相关文章
- 【网站管理6】_一个网站SEO优化方案
首先,前端/页编人员主要负责站内优化,主要从四个方面入手: 第一个,站内结构优化 合理规划站点结构(1.扁平化结构 2.辅助导航.面包屑导航.次导航) 内容页结构设置(最新文章.推荐文章.热门文章.增 ...
- 一个网站SEO优化方案
首先,前端/页编人员主要负责站内优化,主要从四个方面入手: 第一个,站内结构优化 合理规划站点结构(1.扁平化结构 2.辅助导航.面包屑导航.次导航) 内容页结构设置(最新文章.推荐文章.热门文章.增 ...
- netty系列之:搭建HTTP上传文件服务器
目录 简介 GET方法上传数据 POST方法上传数据 POST方法上传文件 总结 简介 上一篇的文章中,我们讲到了如何从HTTP服务器中下载文件,和搭建下载文件服务器应该注意的问题,使用的GET方法. ...
- 一个网站完整详细的SEO优化方案
根据自己的个人经验完成了这篇文章,希望对SEOer有点帮助,高手直接跳过,请勿喷水... 一个完整的SEO优化方案主要由四个小组组成: 一.前端/页编人员 二.内容编辑人员 三.推广人员 四.数据分析 ...
- 一个完整的SEO优化方案
一个完整的SEO优化方案主要由四个小组组成: 一.前端/页编人员 二.内容编辑人员 三.推广人员 四.数据分析人员 接下来,我们就对这四个小组分配工作. 首先,前端/页编人员主要负责站内优化,主要从四 ...
- 应届生应聘阿里,腾讯,美团90%会被问到的Netty面试题!史上最全系列!
1.BIO.NIO 和 AIO 的区别? BIO:一个连接一个线程,客户端有连接请求时服务器端就需要启动一个线程进行处理.线程开销大.伪异步 IO:将请求连接放入线程池,一对多,但线程还是很宝贵的资源 ...
- C#进阶系列——MEF实现设计上的“松耦合”(二)
前言:前篇 C#进阶系列——MEF实现设计上的“松耦合”(一) 介绍了下MEF的基础用法,让我们对MEF有了一个抽象的认识.当然MEF的用法可能不限于此,比如MEF的目录服务.目录筛选.重组部件等高级 ...
- Netty系列之Netty百万级推送服务设计要点
1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...
- 【netty】Netty系列之Netty百万级推送服务设计要点
1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...
随机推荐
- PAT A1107——并查集
Social Clusters When register on a social network, you are always asked to specify your hobbies in ...
- MySQL语法练习一
DESC t_dept ALTER TABLE t_dept ADD descri VARCHAR(20) ALTER TABLE t_dept ADD decribe VARCHAR(20) FIR ...
- Hi3516开发笔记(三):Hi3516虚拟机基础环境搭建之交叉编译环境境搭建以及开机启动脚本分析
前言 前面进行了可以传输,那么写一个简单的C程序来交叉编译并传入运行. 虚拟机 上一篇搭建的虚拟机环境,包含了sftp传递文件,网络能ping通,基于上一篇的虚拟机继续搭建. 海思交叉 ...
- idea添加插件后重启后报错:cannot load project xxxx 解决方案
问题原因:新安装的idea下载插件后重启报错 找到windows上c:\Users\.IntelliJIdea<版本>\config\plugins\这个目录,然后 将对应插件删除
- vscode 整理————开篇之力(一)
前言 作为一个开发为什么对一个vscode 这样的工具进行整理呢,因为vscode 非常的常用,它包含很多编辑器共同有的特征,这些特征帮助我们了解其他编辑器. 这里可能就有人疑问了,我们需要去非常的关 ...
- 洛谷 P2481 [SDOI2010]代码拍卖会(背包+隔板法)
题面传送门 题意: 给出 \(n,p\),求有多少 \(n\) 位数 \(X=a_1a_2a_3\dots a_n\) 满足: 该 \(n\) 位数不含前导零 \(a_i \leq a_{i+1}\) ...
- Contest 2050 and Codeforces Round #718 (Div. 1 + Div. 2) 题解
竟然上 GM 了,incredible( A 首先如果 \(2050\nmid n\) 那显然就 \(-1\) 了,否则答案显然为 \(\dfrac{n}{2050}\) 的各位数字和. B 显然这个 ...
- 自定义 Word 模板
自定义 Word 模板 目录 必要设置 样式设置 标题样式 多级列表 封面 正文 引用目录 页码 页眉 图标 自定义模板保存 样式导入和导出 批量删除多余空白段落 必要设置 显示所有格式标记 选择&q ...
- Matlab流体后处理中的奇淫巧术总结
Matlab流体后处理中的奇淫巧术总结 主要参考\demos\volvec.m示例 1.等值面绘制 %% Isosurface of MRI Data cla load mri D = squeeze ...
- python12对象初