解决用netty去做web服务时,post长度过大的问题
原文地址
http://my.oschina.net/momohuang/blog/114552
先说一下,本来是想自己写socket ,启动一个简单点的web服务用于接收数据的。写完之后,发现会有各种情况没有考虑到的,很有可能出现问题,而且,太折腾了。于是,就用了netty去其web服务,另外,我也觉得netty基本上是最简单的web服务了吧,如果童鞋们有其他推荐的话,就留个言呗。
1、server
public class AdminServer {
protected static final Log log = LogFactory.getLog(AdminServer.class);
public static void main(String[] args) {
log.info("start app");
start(8088);
// System.out.println("admin start on "+1);
}
public static void start(int port) {
// 配置服务器-使用java线程池作为解释线程
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
// 设置 pipeline factory.
bootstrap.setPipelineFactory(new ServerPipelineFactory());
// 绑定端口
bootstrap.bind(new InetSocketAddress(port));
System.out.println("admin start on "+port);
ServiceLocator.initServiceLocator();
}
private static class ServerPipelineFactory implements
ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("encoder", new HttpResponseEncoder());
//http处理handler
pipeline.addLast("handler", new AdminServerHandler());
return pipeline;
}
}
}
启动了服务,绑定了8088端口。
2、当客户端给服务端post数据的时候,如果数据超过50K,这个时候服务端接受到的post内容是空的了。这是因为超过了 服务端默认的post的长度的最大值。
http协议里边,本来是没有对post的长度进行限制,但是,无论是系统层面或者是服务端层面的,都会对post的长度进行限制,这个也有利于网络安全。
3、在netty中的解决方法
private static class ServerPipelineFactory implements
ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = Channels.pipeline();
// pipeline.addFirst("frameDecoder", new LengthFieldBasedFrameDecoder(100000000,0,4,0,4));
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("encoder", new HttpResponseEncoder());
// pipeline.addLast("streamer", new ChunkedWriteHandler());
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));//设置块的最大字节数
//http处理handler
pipeline.addLast("handler", new AdminServerHandler());
return pipeline;
}
}
加上
pipeline.addLast("aggregator", new HttpChunkAggregator(65536))
之后,设置默认的chunk最大为 65536,这样,就可以接受最大post的内容大小为 65536。
这样有一个不好的地方,就是这个大小不好控制,开大了,会浪费空间。并且在接受到的字符串的最后,会出现空白的字符串,这是由于post的内容长度小于chunk里边的ChannelBuffer的数组的大小,程序给予补全。
4、自己设置,自己读取chunk
加上
pipeline.addLast("streamer", new ChunkedWriteHandler());
设置为给位 分开一个个chunk去接受信息。
public boolean excuteChunk(ChannelHandlerContext ctx, MessageEvent e)
throws TooLongFrameException {
// HttpMessage currentMessage = e.getMessage();
if (e.getMessage() instanceof HttpMessage) {
HttpMessage m = (HttpMessage) e.getMessage();
if (m.isChunked()) {
// A chunked message - remove 'Transfer-Encoding' header,
// initialize the cumulative buffer, and wait for incoming
// chunks.
List<String> encodings = m
.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
encodings.remove(HttpHeaders.Values.CHUNKED);
if (encodings.isEmpty()) {
m.removeHeader(HttpHeaders.Names.TRANSFER_ENCODING);
}
m.setContent(ChannelBuffers.dynamicBuffer(e.getChannel()
.getConfig().getBufferFactory()));
this.currentMessage = m;
} else {
// Not a chunked message - pass through.
this.currentMessage = null;
}
return false;
} else if (e.getMessage() instanceof HttpChunk) {
// Sanity check
if (currentMessage == null) {
throw new IllegalStateException("received "
+ HttpChunk.class.getSimpleName() + " without "
+ HttpMessage.class.getSimpleName());
}
// Merge the received chunk into the content of the current message.
HttpChunk chunk = (HttpChunk) e.getMessage();
ChannelBuffer content = currentMessage.getContent();
if (content.readableBytes() > maxContentLength
- chunk.getContent().readableBytes()) {
throw new TooLongFrameException("HTTP content length exceeded "
+ maxContentLength + " bytes.");
}
content.writeBytes(chunk.getContent());
if (chunk.isLast()) {
this.currentMessage = null;
currentMessage.setHeader(HttpHeaders.Names.CONTENT_LENGTH,
String.valueOf(content.readableBytes()));
return true;
// Channels.fireMessageReceived(ctx, currentMessage,
// e.getRemoteAddress());
}
}
return true;
}
在handle中,自己做处理,接受 整个post过来的数据,然后在整合起来,即可
解决用netty去做web服务时,post长度过大的问题的更多相关文章
- idea 为模块添加Tomcat依赖 解决: Intelij IDEA 创建WEB项目时没有Servlet的jar包
解决: Intelij IDEA 创建WEB项目时没有Servlet的jar包 今天创建SpringMVC项目时 用到HttpServletRequest时, 发现项目中根本没有Servlet这个包, ...
- 解决: Intelij IDEA 创建WEB项目时没有Servlet的jar包
今天创建SpringMVC项目时 用到HttpServletRequest时, 发现项目中根本没有Servlet这个包, 在网上搜了一下,这个问题是因为web项目没有添加服务器导致的. 配置tomec ...
- 解决eclipse中运行web项目时弹出的"Port 8080 required by Tomcat 9.0 Server at localhost is already in use...
1.tomcat默认端口是8080,可以修改通过tomcat的端口 修改tomcat\conf\server.xml 结果运行程序,还是报"Port 8080 required by ...
- ASP.NET Web服务调用发生错误,错误代码404
现象: iOS端使用ASIHTTP连接Web服务时,得到的数据是一个错误代码为404的页面,错误信息(web.config添加<customErrors mode="Off" ...
- 服务设计模式一:Web服务概述
目录 1. Web服务是什么 2.为什么要使用Web服务 3.Web服务考虑的因素和替代方案 4.SOA是什么 Web服务是什么? 所谓服务,通俗的理解就是别人帮你做一些事情,比如说,腰酸背痛了,找个 ...
- Web服务端性能提升实践
随着互联网的不断发展,日常生活中越来越多的需求通过网络来实现,从衣食住行到金融教育,从口袋到身份,人们无时无刻不依赖着网络,而且越来越多的人通过网络来完成自己的需求. 作为直接面对来自客户请求的Web ...
- Linux实战教学笔记37:企业级Nginx Web服务优化实战(上)
一,Nginx基本安全优化 1.1 调整参数隐藏Nginx软件版本号信息 一般来说,软件的漏洞都和版本有关,这个很像汽车的缺陷,同一批次的要有问题就都有问题,别的批次可能就都是好的.因此,我们应尽量隐 ...
- 踩坑踩坑之Flask+ uWSGI + Tensorflow的Web服务部署
一.简介 作为算法开发人员,在算法模块完成后,拟部署Web服务以对外提供服务,从而将算法模型落地应用.本文针对首次基于Flask + uWSGI + Tensorflow + Nginx部署Web服务 ...
- Python Web 服务开发者: 第 1 部分
Python Web 服务开发者: 第 1 部分 Python Web 服务世界 Python 的座右铭一向是“装备齐全”,这是指在安装该语言时会附带一大套标准库和功能程序.本文概述了在 Python ...
- 利用OpenShift托管Node.js Web服务进行微信公众号开发
最近写了一个微信的翻译机器人.用户只要关注该公众号,发送英文的消息,就能收到中文翻译的回复.有兴趣的读者可以扫描下面的二维码关注该公众号,尝试发送英文单词试试看.(有时候第一次发送单词会收到“该公众号 ...
随机推荐
- glance对接ceph
目录 glance对接ceph 1. 上传镜像 2. 对接ceph 2.1 创建池 2.2 创建用户 2.3 下发ceph文件 2.4 修改globals文件 2.5 更新glance配置 3. 上传 ...
- USB协议详解第1讲(核心概念通俗理解)
0.概括 USB协议学习中最重要几个概念如下,没有提及的就是对USB协议学习中不重要的或者编程不需要用到的.大家也不用着急,概念必须要学会,否则都不知道下面这些东西是什么还学什么通用串行总线协议,大家 ...
- 某小说解锁VIP
在User类中定位到这个方法,尝试直接返回true 可以发现apk显示了vip的到期时间,测试一下vip是否有效 显然这个vip是没起作用的,还有地方在控制这个vip的方法.在jadx中查看交叉引用 ...
- Centos7下非lvm的分区扩容
Centos7下非lvm的分区扩容(重要) 前言:一般在生产环境中,如果需要使用一个分区保存大量的文件,建议的做法是在虚拟化环境中增加一块单独的硬盘,挂载一个单独的分区,比如 /data 上图我们可以 ...
- vue3+tpyeScript + element plus 三级复选框,全选控制全部,左侧选中控制右侧全选
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...
- Litmus 实践:让群魔在混沌中乱舞,看 K8s 能撑到何时
对于云服务而言,如果系统出现异常,将会带来很大的损失.为了最大程度地降低损失,我们只能不断探寻系统何时会出现异常,甚至缩小到某些特定参数变化是否会造成系统异常.然而随着云原生的发展,不断推进着微服务的 ...
- 第147篇:微信小程序开发中Promise的使用(aysnc,await)
好家伙, 0.错误描述 今天在开发中犯了一个比较严重的错误 对于Promise的错误使用 场景: 微信小程序中展示搜索条件列表 // API请求工具函数 const apiRequest = (url ...
- 玩黑悟空要配什么显卡?ToDesk云电脑一招搞定!
近期国产游戏大作<黑神话·悟空>的预售开启,许多玩家对于如何配置自己的电脑以畅玩这款画质卓越.支持全景光追的3A大作产生了浓厚的兴趣. 尤其是显卡的选择,成为了玩家们关注的焦点.<黑 ...
- 工作中的技术总结_ thymeleaf的应用 _select&input的数据回显 _20210910
工作中的技术总结_ thymeleaf的应用 _select&input的数据回显 _20210910 在需要用户输入的场合,常常会有对用户填入数据的验证,对数据的验证不通过则需要返回到表单页 ...
- springBoot项目启动卡在Root WebApplicationContext: initialization completed... (非DEBUG断点问题)
通过源码启动排查发现,初始化连接池时创建了200次,通过配置文件中将initialSize值改为10,启动时间从1分钟变为了3秒.