Netty http 相关机制

keep-alive,gzip,truncked

3 压缩  

3.1 背景

     在http请求(特别是移动端),如果请求的资源比较多,则网络的开销会比较大,用户体验较差。则可以开启数据的无损压缩,节省传输的流量,提升数据的加载性能。

3.2 压缩类型

    1:压缩需要客户端,服务器端同时支持。在chrome中,请求默认会加上Accept-Encoding: gzip, deflate,客户端默认开启数据压缩。而tomcat默认关闭压缩,如果开启需要增加配置。

    2:在请求时,需要通过header的Accept-Encoding: gzip, deflate 来告诉服务器客户端支持的压缩类型。

    3:在返回时,http server会在返回的header中添加Content-Encoding: gzip 来告诉客户端数据的压缩方式。

    4:压缩类型主要包含如下几种:

          gzip      说明body采用GNU zip编码

         compress 说明body采用Unix的文件压缩程序

         deflate  说明body是用zlib的格式压缩的

         identity  说明没有对实体进行编码。

    其中 gzip, compress, 以及deflate编码都是无损压缩算法,不会导致信息损失。 gzip效率最高,使用较为广泛。

3.4 优点
      减少流量,帮公司节省带宽及流量,帮用户节省流量
      客户端(特别是移动端),加载速度变快,提升用户体验。
3.5 缺点
     服务器端需要更多的cpu资源进行计算,会降低服务器的整体吞吐量

5 粘包,拆包

5.1背景

    TCP是基于stream机制,其实就是一串没有边界的数据流。 这里主要面临两个问题:1:如何定义数据的边界 2:拆包和粘包的问题。HTTP协议是基于TCP,所以也会面临前面两个问题。

 

 1:发送端发送数据,数据先通过网卡到服务端tcp的receive buffer中。服务端的上层应用如果需要读取数据,会申请一段业务buffer,调用JDK的IO接口,IO会将tcpreceive  buffer的数据拷贝到业务的buffer里面。上层业务再通过设定的反序列化协议将业务buffer转换成对象进行业务处理。

   2:服务端读取数据时,先申请一段业务buffer(大小一般是1k),通过调用JDK的channel.read(buffer) IO方法,IO会将tcp buffer的数据拷贝到业务buffer里面。返回值为读取字节的个数:如果返回值大于0,说明读取到了对应大小的数据;如果是0,表示没有读到数据,数据读取完成(可能业务buffer是满的,不能往里面写数据);如果是-1,代表tcp连接被关闭(一般处理是关闭到该连接)

5.3 粘包拆包说明

         

  说明:假如服务端连续接收了4个包。 应用申请1k的buffer空间去读取tcp数据。读取的流程如下。

    1:业务先申请1k大小的业务buffer,先调用JDK IO接口,会拷贝Receive Buffer的1k数据到业务的buffer里面。

    2:每个包定义有边界。通过边界定义,读取到包1和包2分别进行反序列化的处理,转换为对象供上层应用处理。(解决粘包的问题)

    3:如下图:在读取到包3的时候,由于把buffer读完还没有发现边界。便将包3(剩下的10个)的数据拷贝到buffer的最前端。然后再调用JDK IO接口,tcp receive buffer拷贝数据是从业务buffer的第10个位置进行拷贝赋值。拷贝完后再读取包3的数据,直到边界(解决拆包的问题)

                        

      4:然后读取包4,发现到边界后,并且数据没有可读的,则整个流程结束。

5.4 http解决方案:

      1:请求行的边界是CRLF,如果读取到CRLF,则意味着请求行的信息已经读取完成。

      2:Header的边界是CRLF,如果连续读取两个CRLF,则意味着header的信息读取完成。

      3:body的长度是有Content-Length 来进行确定。如果没有Content-Length ,则是chunked协议(具体参考前面的trunked协议)。

 

相关流程分析:

 只需要在netty的pipeLine中配置HttpRequestDecoder和HttpObjectAggregator。

 

 1:如果把解析这块理解是一个黑盒的话,则输入是ByteBuf,输出是FullHttpRequest。通过该对象便可获取到所有与http协议有关的信息。

    2:HttpRequestDecoder先通过RequestLine和Header解析成HttpRequest对象,传入到HttpObjectAggregator。然后再通过body解析出httpContent对象,传入到HttpObjectAggregator。当HttpObjectAggregator发现是LastHttpContent,则代表http协议解析完成,封装FullHttpRequest。

   3:对于body内容的读取涉及到Content-Length和trunked两种方式。两种方式只是在解析协议时处理的不一致,最终输出是一致的。

 

6.3 response的流程处理

6.3.1实现

   只需要在netty的pipeLine中配置HttpResponseEncoder 

6.3.2原理

         

     1:输入是FullHttpResponse对象,输出是ByteBuf。socket再将ByteBuf数据发送到访问端。

     2:对FullHttpResponse按照http协议进行序列化。判断header里面是ContentLength还是Trunked,然后body按照相应的协议进行序列化。 

 

压缩实现:

在HttpResponseEncoder之前加上 HttpContentCompressor 。response对象先进过HttpContentCompressor 压缩后,再经过HttpResponseEncoder进行序列化。

  1:压缩主要是针对body进行压缩。http1.1不支持对header的压缩。

  2:压缩后body的输出是trunked,而不是Content-length的形式。

6.4.2 Gzip格式

      gzip压缩后主要包含三部分:

    

      gzip头:主要存储的是gzip的压缩方式

      deflate编码:内容采用的是deflate压缩算法

      gzip尾:主要是采用CRC32算法对编码内容进行校验。

 

参考资料:

https://www.cnblogs.com/chris-oil/p/6098258.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

执于代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值