Netty应用:快速了解http各版本的特性 HttpServer的小demo

简介: Netty应用:快速了解http各版本的特性 HttpServer的小demo

HTTP协议

0.9版本

GET /index.html

1

服务端只能返回html格式,传输过程只能处理文字。


1.0版本

支持任何格式的内容,包括图像、视频、二进制等等

引入了POST命令、HEAD命令

HEAD命令 : 这个命令和 get 是有相似之处的 只返回头部信息,不会返回全部内容,速度较快,一般用来验证连接的有效性

增加了请求头、状态码,以及权限、缓存等

那么1.0 他的会是什么样子的呢?


请求

GET / HTTP/1.0

User-Agent:Mozilla/1.0

Accept: */*


响应格式


HTTP/1.0 200 OK

Content-Type: text/plain

Content-Encoding: gzip


<html>

 <body> hello world </body>

</html>


a、 Content-Type


服务端通知客户端,当前数据的格式


示例: text/html 、 image/png 、 application/pdf 、 video/mp4


前面是一级类型,后面是二级类型,用斜杠分隔; 还可以增加其他参数,如编码格式。


Content-Type: text/plain; charset=utf-8


b、Content-Encoding


表示数据压缩的方式,gzip、compress、deflate


对应客户端的字段为 Accept-Encoding,代表接收哪些压缩方式


c、缺点和问题


每个TCP连接只能发送一个请求,发送完毕连接关闭,使用成本很高,性能较差。


Connection: keep-alive   - 非标准字段

1

1.1版本

在http1.0推出后的半年 1.1版本也随之而来,


这个版本也一直沿用至今,当前我们大部分的http请求 都是用的 1.1 版本的


这里我们使用 postman 来请求一下 常用的搜索引擎 cn.bing.com


请求

GET / HTTP/1.1
User-Agent: PostmanRuntime/7.28.4
Accept: */*
Postman-Token: 2e1942a8-9e7c-4c89-87d7-a46c11205b8c
Host: cn.bing.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

响应

HTTP/1.1 200 OK
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Content-Encoding: br
Vary: Accept-Encoding
P3P: CP="NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND"
Set-Cookie: SUID=M; domain=.bing.com; expires=Sun, 21-Nov-2021 09:49:46 GMT; path=/; HttpOnly
Set-Cookie: MUID=015C0F598C4C6F831C8A1FAC8D066E50; domain=.bing.com; expires=Thu, 15-Dec-2022 09:49:46 GMT; path=/
Set-Cookie: MUIDB=015C0F598C4C6F831C8A1FAC8D066E50; expires=Thu, 15-Dec-2022 09:49:46 GMT; path=/; HttpOnly
Set-Cookie: _EDGE_S=F=1&SID=1793E6C6781468071F6CF633795E69AE; domain=.bing.com; path=/; HttpOnly
Set-Cookie: _EDGE_V=1; domain=.bing.com; expires=Thu, 15-Dec-2022 09:49:46 GMT; path=/; HttpOnly
Set-Cookie: SRCHD=AF=NOFORM; domain=.bing.com; expires=Mon, 20-Nov-2023 09:49:46 GMT; path=/
Set-Cookie: SRCHUID=V=2&GUID=A3776BC1B7E749699ADB5F7804C9FEE3&dmnchg=1; domain=.bing.com; expires=Mon, 20-Nov-2023 09:49:46 GMT; path=/
Set-Cookie: SRCHUSR=DOB=20211120; domain=.bing.com; expires=Mon, 20-Nov-2023 09:49:46 GMT; path=/
Set-Cookie: SRCHHPGUSR=SRCHLANG=zh-Hans; domain=.bing.com; expires=Mon, 20-Nov-2023 09:49:46 GMT; path=/
Set-Cookie: _SS=SID=1793E6C6781468071F6CF633795E69AE; domain=.bing.com; path=/
Set-Cookie: ULC=; domain=.bing.com; expires=Fri, 19-Nov-2021 09:49:46 GMT; path=/
Set-Cookie: _HPVN=CS=eyJQbiI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiUCJ9LCJTYyI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiSCJ9LCJReiI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiVCJ9LCJBcCI6dHJ1ZSwiTXV0ZSI6dHJ1ZSwiTGFkIjoiMjAyMS0xMS0yMFQwMDowMDowMFoiLCJJb3RkIjowLCJHd2IiOjAsIkRmdCI6bnVsbCwiTXZzIjowLCJGbHQiOjAsIkltcCI6MX0=; domain=.bing.com; expires=Mon, 20-Nov-2023 09:49:46 GMT; path=/
X-SNR-Routing: 1
X-Cache: CONFIG_NOCACHE
X-MSEdge-Ref: Ref A: C567D165BB114CD98893F50FEF5FAEE8 Ref B: BJ1EDGE0716 Ref C: 2021-11-20T09:49:46Z
Date: Sat, 20 Nov 2021 09:49:45 GMT
The console only showsresponse bodies smaller than 10 KB inline. To view the complete body, inspect it by clicking  Open.

持久连接,含义为默认不关闭tcp连接,可以被多个请求复用。大多时候,浏览器对同一个域名,允许同时建立6个连接。

管道机制,支持客户端发送多个请求,管理请求的顺序的。服务器还是按照接受请求的顺序,返回对应的响应结果。

Content-Length, 用来区分数据包的重要字段

支持PUT、DELETE、PATCH等命令

缺点和问题


当部分请求耗时较长时,仍会阻塞后续请求的处理速度,这种现象叫做“队头阻塞”/“线头阻塞”。


2.0版本

解决队头阻塞的问题,使用的是多路复用的方式。


多路复用 不只是在 netty上有 他可以运用到很多地方


说了这么多 上代码来操作一下吧!!

我们的编写思路是这样的


编写初始化服务端

编写自定义初始化器 和 自定义处理器

启动postman 查看我们设置的 http 的响应结果

我们这里有三个类


HttpServer 初始化服务端

MyHttpHandler 自定义处理器

MyHttpInitializer 自定义初始化

首先是 server


我们需要在初始化服务端的时候 设置主从线程模型(Netty中常用)

设置 启动参数 和阻塞队列的长度等设置

设置 初始化


public class HttpServer {
    public static void main(String[] args) {
        //可以自定义线程的数量
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        // 默认创建的线程数量 = CPU 处理器数量 *2
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler())
                //当前连接被阻塞的时候,BACKLOG代表的事 阻塞队列的长度
                .option(ChannelOption.SO_BACKLOG, 128)
                //设置连接保持为活动状态
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childHandler(new MyHttpInitializer());
        try {
        //设置为异步启动 异步 关闭
            ChannelFuture future = serverBootstrap.bind(9988).sync();
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
          //netty的优雅关闭 指 等一切执行完毕之后 慢慢的关闭
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

编写 初始化


继承ChannelInitializer泛型为Channel,用来进行设置出站解码器和入站编码器

使用 codec netty封装好的解码器,这样我们就不用每次定义 解码和编码

public class MyHttpInitializer extends ChannelInitializer<Channel> {
    @Override
    protected void initChannel(Channel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();
        //先对应请求解码,后对响应解码
        //pipeline.addLast("decoder", new HttpRequestDecoder());
        //pipeline.addLast("encoder", new HttpRequestEncoder());
        //当然每次我们都要解码编码很麻烦,netty也有为我们提供对应的解决方案,建议直接使用这个 不会出错
        pipeline.addLast("codec", new HttpServerCodec());
        //压缩数据
        pipeline.addLast("compressor", new HttpContentCompressor());
        //聚合完整的信息 参数代表可以处理的最大值 此时的是 512 kb
        pipeline.addLast("aggregator", new HttpObjectAggregator(512 * 1024));
        pipeline.addLast(new MyHttpHandler());
    }
}

有了初始化,我们还需要一个做事的 那就是 处理器 Handler


netty帮我们封装了返回完整http响应的类 DefaultFullHttpResponse

我们只需要在读取的时候 设置协议,状态码和响应信息,

配置响应头的类型和长度 就可以完成对请求的响应


/*
 * 泛型需要设置为 FullHttpRequest
 * 筛选 message 为此类型的消息才处理
 * */
public class MyHttpHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws Exception {
        //DefaultFullHttpResponse 是一个默认的完整的http响应
        DefaultFullHttpResponse response = new DefaultFullHttpResponse(
                HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
                Unpooled.wrappedBuffer("hello http netty demo".getBytes())
        );
        //    我们还需要设置响应头
        // 设置请求 响应头字段 可以使用 HttpHeaderNmaes
        // 设置字段时 可以使用
        HttpHeaders headers = response.headers();
        headers.add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN + ";charset=UTF-8");
        headers.add(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        ctx.write(response);
    }
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }
}

启动结果


postman 差看到的请求响应 参数

可以看到我们设置的 http1.1 协议

类型 text/plain 长度 47

响应给客户端的 内容 hello http netty demo

1.png



小结

了解 http 各个版本的解决了什么问题,优缺点,优劣性

手动编写一个服务端的响应,用postman 查看响应头我们设置的内容

体验到 netty强大的封装带给我们的便利性

2.png

相关文章
|
6天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
15天前
|
前端开发 JavaScript 安全
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第27天】本文介绍了HTTP/2和HTTPS在前端性能调优中的应用。通过多路复用、服务器推送和头部压缩等特性,HTTP/2显著提升了Web性能。同时,HTTPS确保了数据传输的安全性。文章提供了示例代码,展示了如何使用Node.js创建一个HTTP/2服务器。
29 3
|
2月前
|
安全 网络协议 应用服务中间件
AJP Connector:深入解析及在Apache HTTP Server中的应用
【9月更文挑战第6天】在Java Web应用开发中,Tomcat作为广泛使用的Servlet容器,经常与Apache HTTP Server结合使用,以提供高效、稳定的Web服务。而AJP Connector(Apache JServ Protocol Connector)作为连接Tomcat和Apache HTTP Server的重要桥梁,扮演着至关重要的角色
74 2
|
3天前
|
缓存 安全 网络安全
HTTP/2与HTTPS在Web加速中的应用
HTTP/2与HTTPS在Web加速中的应用
|
12天前
|
缓存 安全 前端开发
HTTP 协议的请求方法在实际应用中有哪些注意事项?
【10月更文挑战第29天】HTTP协议的请求方法在实际应用中需要根据具体的业务场景和需求,合理选择和使用,并注意各种方法的特点和限制,以确保网络通信的安全、高效和数据的一致性。
|
16天前
|
前端开发 安全 应用服务中间件
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第26天】随着互联网的快速发展,前端性能调优成为开发者的重要任务。本文探讨了HTTP/2与HTTPS在前端性能优化中的应用,介绍了二进制分帧、多路复用和服务器推送等特性,并通过Nginx配置示例展示了如何启用HTTP/2和HTTPS,以提升Web应用的性能和安全性。
17 3
|
15天前
|
网络协议 前端开发 API
HTTP 和 TCP 协议的应用场景有哪些不同
【10月更文挑战第25天】HTTP(超文本传输协议)和 TCP(传输控制协议)处于网络协议栈的不同层次,各自具有独特的功能和特点,因此它们的应用场景也存在明显的差异。
|
1月前
|
JavaScript 安全 Java
谈谈UDP、HTTP、SSL、TLS协议在java中的实际应用
下面我将详细介绍UDP、HTTP、SSL、TLS协议及其工作原理,并提供Java代码示例(由于Deno是一个基于Node.js的运行时,Java代码无法直接在Deno中运行,但可以通过理解Java示例来类比Deno中的实现)。
65 1
|
2月前
|
安全 网络安全 数据安全/隐私保护
HTTP与HTTPS协议区别及应用场景
在互联网高速发展的今天,HTTP与HTTPS作为数据传输的基石,作用至关重要。HTTP允许客户端与服务器间传输超文本文档,但其数据传输过程未加密,存在安全隐患;HTTPS则在此基础上加入了SSL/TLS协议,实现了数据加密传输,增强了安全性,广泛应用于电子商务、网上银行、政府网站及社交媒体平台等涉及敏感信息传输的领域,有效保护了用户隐私和数据安全。随着网络安全意识提升,HTTPS正逐渐成为主流。
|
1月前
|
JSON API 开发者
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
16 0