前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >『互联网架构』软件架构-netty之http协议应用实践(58)

『互联网架构』软件架构-netty之http协议应用实践(58)

作者头像
IT架构圈
发布2019-05-31 17:33:43
6290
发布2019-05-31 17:33:43
举报
文章被收录于专栏:IT架构圈IT架构圈

(一)Http协议概述
  • 1.什么是Http协议

HTTP是一个属于【应用层】的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。

  • 2.HTTP协议的主要特点

支持客户/服务器模式。 简单快速 客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与 服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。 灵活 HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。 无连接 无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。 无状态 HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。从HTTP协议来讲是无状态的,其实在应用的时候,很多情况通过回话的方式还是有状态的。

(二)Http协议交互过程

协议交互本质是指协议两端(客户端、服务端),互联网上没有协议是混乱的,正如如果现实中没有法律也会打乱一样。

1.传输数据

传输数据一般基于TCP/IP 实现,体现到开发语言上就是我们所熟悉的Socket 编程。

2.交换数据

交换数据本质是指,两端(客户端、服务端)能各自识别对方所发送的数据。那么这就需要制定一套【报文编码】格式,双方以该格式编码数据发送给对方。 Http 对应的Request 与Response报文

注: 我们可以通过抓包工具(fiddler)可以直接看到该报文格式。

报文约定好以后两端都需要对其进行解码和编码操作

3.Http协议内容组成

请求方法

方法

描述

GET

请求指定的页面信息,并返回实体主体。

HEAD

类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头

POST

向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。

PUT

从客户端向服务器传送的数据取代指定的文档的内容。

DELETE

请求服务器删除指定的页面。

CONNECT

HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

OPTIONS

允许客户端查看服务器的性能。

TRACE

回显服务器收到的请求,主要用于测试或诊断。

部分请求头

请求头

说明

Host

接受请求的服务器地址,可以是IP:端口号,也可以是域名

User-Agent

发送请求的应用程序名称

Connection

指定与连接相关的属性,如Connection:Keep-Alive

Accept-Charset

通知服务端可以发送的编码格式

Accept-Encoding

通知服务端可以发送的数据压缩格式

Accept-Language

通知服务端可以发送的语言

部分响应头

响应头

说明

Server

服务器应用程序软件的名称和版本

Content-Type

响应正文的类型(是图片还是二进制字符串)

Content-Length

实体报头域用于指明实体正文的长度,以字节方式存储的十进制数字来表示响应正文长度

Content-Charset

响应正文使用的编码

Content-Encoding

响应正文使用的数据压缩格式

Content-Language

响应正文使用的语言

部分响应状态

状态码

说明

200

响应成功

302

跳转,跳转地址通过响应头中的Location属性指定(JSP中Forward和Redirect之间的区别)

400

客户端请求有语法错误,不能被服务器识别

403

服务器接收到请求,但是拒绝提供服务(认证失败)

404

请求资源不存在

500

服务器内部错误

(二)基于Netty 实现Http协议过程分析

Http协议分为三部分:

1.远程数据传输 2.报文编解码 3.业务处理

但如果是开发基于Http普通应用,完全没有必要重复造轮子,,我们只需实现业务即可。现比较成熟的中间件有:Tomcat、Jetty、Jboos。这些中间有个缺点是较重,如果需要轻量实现可采用:netty 或JDK自还http 实现JDK Http源码参见:com.sun.net.httpserver.HttpServer

  • netty 实现http

源码:nio/http中。

1.初始ServerBootstrap 2.通过ChannelInitializer 初始 pipeline 3.基于SimpleChannelInboundHandler HttpServer处理类

代码语言:javascript
复制
import io.netty.bootstrap.ServerBootstrap;import io.netty.buffer.Unpooled;import io.netty.channel.*;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.ServerSocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import io.netty.handler.codec.http.*;import io.netty.util.concurrent.Future;import io.netty.util.concurrent.GenericFutureListener;
import java.net.ContentHandler;import java.util.concurrent.ThreadFactory;
/** * Created by idig8.com */public class HttpSimpleServer {    //open 启动服务    public void openServer() {        ServerBootstrap bootstrap = new ServerBootstrap();        bootstrap.channel(NioServerSocketChannel.class);        EventLoopGroup boss = new NioEventLoopGroup(1);        EventLoopGroup work = new NioEventLoopGroup(8);        bootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {            @Override            protected void initChannel(NioSocketChannel ch) throws Exception {                ch.pipeline().addLast("http-decoder", new HttpRequestDecoder());                ch.pipeline().addLast("http-aggregator", new HttpObjectAggregator(65536));                ch.pipeline().addLast("http-encoder", new HttpResponseEncoder());                ch.pipeline().addLast("http-server", new HttpServerHandler());            }        });        bootstrap.group(boss, work);        try {            ChannelFuture future = bootstrap.bind(8080).sync();            System.out.println("服务启动:8080");            future.channel().closeFuture().sync();        } catch (InterruptedException e) {            e.printStackTrace();        } finally {            boss.shutdownGracefully();            work.shutdownGracefully();        }    }
    private static class HttpServerHandler extends SimpleChannelInboundHandler {        @Override        protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=UTF-8");            String html = "<!DOCTYPE html>\n" +                    "<html lang=\"en\">\n" +                    "<head>\n" +                    "    <meta charset=\"UTF-8\">\n" +                    "    <title>hello idig8.com</title>\n" +                    "</head>\n" +                    "<body>\n" +                    "hello idig8.com\n" +                    "</body>\n" +                    "</html>";            response.content().writeBytes(html.getBytes("UTF-8"));            ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);        }    }
    public static void main(String[] args) {        HttpSimpleServer simpleServer = new HttpSimpleServer();        simpleServer.openServer();    }

}

实现过程分析

  1. 建立连接读取消息流
  2. 解码Request
  3. 业务处理
  4. 编码Response
  5. 返回消息关闭连接

Channel 与 ChannelPipeline

1.Channel: a. ServerSocketChannel b. SocketChannel

2.pipeline:一个pipeline 当中包含了多个ChandlerHandler,而且是有顺序的

3.ChandlerHandler a. HttpRequestDecode:解码请求 b. HttpResponseEncode :编码返回结果 在 Netty 中每个 Channel 都有且仅有一个 ChannelPipeline 与之对应, 它们的组成关系如下:

一个 Channel 包含了一个 ChannelPipeline, 而 ChannelPipeline 中又维护了一个由 ChannelHandlerContext 组成的双向链表. 这个链表的头是 HeadContext, 链表的尾是 TailContext,并且每个 ChannelHandlerContext 中又关联着一个 ChannelHandler

代码语言:javascript
复制
bootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {ch.pipeline().addLast("http-decoder", new HttpRequestDecoder());ch.pipeline().addLast("http-aggregator", new HttpObjectAggregator(65536));ch.pipeline().addLast("http-encoder", new HttpResponseEncoder());ch.pipeline().addLast("http-server", new HttpServerHandler());}});

HttpRequest 在netty 当中的表示结构

HttpResponse在netty 当中的结构

PS:说了下http协议和如何通过netty完成http服务。下次一起说说通过netty完成websocket。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程坑太多 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • (一)Http协议概述
  • (二)Http协议交互过程
  • (二)基于Netty 实现Http协议过程分析
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档