十二HTTP 2.0

时间:2024-10-11 07:04:04

# HTTP 2.0

## 一、HTTP/2.0 的前世今生

​    超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。指定了客户端发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;HTTP最早只是为了浏览器获取web服务器端资源信息的,但当时的页面的内容、排版、交互等都相对简单,所以早期的HTTP/1.0 和 1.1 都没有考虑太多效率上的问题,但随着web 2.0 甚至 web 3.0 时代的到来,HTTP 效率的问题逐渐凸显,页面上内容更加丰富(视频、图片)、排版也更加精美多样(css样式)、复杂的用户交互也越来越多(js),所以当前我们请求网站首页时所需要加载的数据总量和请求数量都越来越多,效率不足已经是亟待解决的问题了。

#### HTTP协议

* 原理,它是一种用于传输超文本文件的协议,能够正确保留超文本标签及其对应的链接地址,让浏览器识别并加载这些标签的功能。

#### HTTP/2.0

​    HTTP/2.0 协议的出现主要归功于google的一个工具SPDY。
​    SPDY:HTTP在引入SPDY协议后,页面的加载效率平均提高了60+%。
特性:HTTP/2.0协议相较于HTTP/1.1在加载大量图片资源时,其响应效率更高,这主要是由于HTtP2.0对TCP协议进行了优化,从而提高了传输效率。H2协议相比H1协议具备许多优势,像支持多路复用、首部压缩等

## 二、HTTP/2.0 升级后的新特性

## 1. 全新的二进制格式(Binary Format)

http/1.x诞生的时候是明文协议,其格式由三部分组成:start line(request line或者status line),header,body。![[Pasted image 20240930163553.png]]


​    http/2.0 的格式定义更接近tcp层的方式,length定义了整个frame的开始到结束,type定义frame的类型,flags用bit位定义一些重要的参数,stream id用作流控制,剩下的payload就是request的正文了。看上去协议的格式和http/1.x完全不同了,实际上http/2.0并没有改变http/1.x的语义,只是把原来http/1.x的header和body部分用frame重新封装了一层而已。调试的时候浏览器甚至会把http/2.0的frame自动还原成http/1.x的格式。

![[Pasted image 20240930163642.png]]

#### 2. 多路复用 (Multiplexing)

​    在HTTP/1.1 协议中,浏览器作为客户端,在同一时间内针对同一域名下的请求有一定数量的限制,当超过数量限制时请求会被阻塞。==允许多个请求和响应同时在一个连接上进行,避免了HTTP/1.1中的队头阻塞问题。==

​    多路复用允许同时通过单一的 HTTP/2.0 连接发起多重的请求-响应消息。因此 HTTP/2.0 可以很轻松的实现**多流并行**而不用依赖建立多个 TCP 连接,HTTP/2.0 把 HTTP 协议通信的基本单位缩小为一个一个的帧,这些帧对应着逻辑流中的消息。并行地在同一个 TCP 连接上**双向交换**消息。
![[Pasted image 20240930163754.png]]
#### 3. 首部压缩(Header Compression)

​    HTTP/1.1并不支持 HTTP 首部压缩,为此 SPDY 和 HTTP/2.0 应运而生, SPDY 使用的是通用的DEFLATE 算法,而 ==HTTP/2.0 则使用了专门为首部压缩而设计的 HPACK 算法。减少了数据传输量,提高了性能。==

![[Pasted image 20240930163820.png]]
#### 4. 服务端数据推送(Server Push)

​    在 HTTP/2.0 中,服务器可以对客户端的一个请求发送多个响应,如果你的请求是一个网站的首页,服务器很可能会响应主页内容、logo 以及样式文件等,因为服务器知道客户端会用到这些东西。这相当于在一个 HTML 文档内集合了所有的资源,不过与之相比,服务器推送还有一个很大的好处:可以缓存!不同页面之间可以共享缓存资源。==服务器可以在客户端请求之前预先推送资源,进一步减少加载时间。==

## 三、HTTP/2.0 对比 HTTP/1.1 效果展示

#### 对比效果图:
![[Pasted image 20240930163855.png]]

## 四、实验:web 服务器实现 HTTP/2.0

#### 1. 准备工作
==注意事项:在部署过程中,需要开启加密和Http2.0的是apache和Nginx服务器==
1. 操作系统选择CentOS 7.x,yum源自带的很多软件版本依赖就足够了
2. httpd 版本需要在2.4.17以上,否则不支持 mod_http2
3. Nginx 版本需要在1.10以上,否则不支持HTTP/2.0
   openssl版本需要在1.0.2以上,否则不支持HTTP/2.0
4. HTTP/2.0只支持开启了https的网站,即便如此还是要比用HTTP/1.1版本未加密的效率要高

基础源:wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

扩展源:wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

#### 1. 实验一加密并开启http2.0 Apache服务器

1. 下载合适版本的httpd软件 [Welcome! - The Apache HTTP Server Project](https://httpd.apache.org/)

2. 安装支持HTTP/2.0的库

```shell
yum -y install libnghttp2-devel
```

http/2 依赖 libnghttp2 的库,需要提前安装。

3. 解决依赖关系并安装httpd软件

```shell
tar -xf apr-1.7.5.tar.gz 
tar -xf apr-util-1.6.3.tar.gz
cp -r apr-1.7.5 httpd-2.4.62/srclib/apr
cp -r apr-util-1.6.3 httpd-2.4.62/srclib/apr-util
 yum -y install gcc gcc-c++ pcre-devel openssl openssl-devel expat-devel libnghttp2-devel
cd httpd-2.4.62/
./configure --prefix=/usr/local/apache2 --sysconfdir=/usr/local/apache2/etc --with-included-apr --enable-so --enable-deflate=shared --enable-expires=shared --enable-rewrite=shared --enable-ssl --enable-http2
 make && make install

```

4. 修改配置文件,开启HTTP/2.0模块和SSL模块的调用

```shell
cd /usr/local/apache2/etc/
vim httpd.conf
LoadModule http2_module modules/mod_http2.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
```

5. 创建证书秘钥文件

```shell
 cd /usr/local/apache2/etc/
 openssl genrsa -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -sha256 -in server.csr -signkey server.key -out server.crt

```

5. 修改配置文件,开启虚拟主机,添加443端口的虚拟主机

```shell
vim httpd.conf
ServerName www.linuxlc.com:80
Protocols h2c http/1.1
#兼容不同的客户端,使其2和1.1都能响应。
Include etc/extra/httpd-ssl.conf
<Directory "/usr/local/apache2/htdocs">
    RewriteEngine on
    RewriteCond %{SERVER_PORT} !^443$
    RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1
</Directory>
 vim extra/httpd-ssl.conf
<VirtualHost _default_:443>
DocumentRoot "/usr/local/apache2/htdocs"
#就添加支持h2协议即可
Protocols h2 http/1.1
ServerName www.linuxlc.com:443
ServerAdmin you@example.com
ErrorLog "/usr/local/apache2/logs/error_log"
TransferLog "/usr/local/apache2/logs/access_log"
SSLEngine on
#因为创建的证书和秘钥文件符合配置文件中默认的目录和文件名,所以没有写但单独的调用
```

5. 检查配置文件并重启httpd服务,浏览器单独验证httpd是否支持HTTP/2.0协议

```shell
/usr/local/apache2/bin/apachectl -t
/usr/local/apache2/bin/apachectl start

```


效果展示:

![[Pasted image 20240930163952.png]]

Chrome 浏览器查看:开发者模式 —> Network —>  右键标题勾选 Protocol —> 查看 Protocol 为 h2
Firefox 浏览器查看:开发者模式 —> Network —> 网页头信息 Headers —> Version: HTTP/2.0
Safari 浏览器查看:开发者模式 —> Resources —> 网页头信息 —> Resource —> Protocol HTTP/2

#### ==2. 实验二Nginx在反向代理apache接收用户请求并实现加密和http2.0==

原理:Nginx在反向代理模式下,只需在nginx端保留加密和Http2.0协议即可,apache无需保留,因为真正接收用户请求的nginx,只需要nginx加密即可

原理图:![[Pasted image 20241004144424.png]]
1. 下载Nginx源码软件包

[nginx news](https://nginx.org/)

2. 编译安装nginx软件包

   ```shell
   #安装支持HTTP/2.0的库
   yum -y install gcc gcc-c++ pcre-devel openssl openssl-devel expat-devel libnghttp2-devel
tar -xf nginx-1.27.1.tar.gz 
 cd nginx-1.27.1/
 useradd -r -s /sbin/nologin nginx
  ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module
  make && make install
  
   ```

3. 修改配置文件,开启SSL和HTTP/2.0

   ```shell
            cd /usr/local/nginx/conf
openssl genrsa -out server.key 1024
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -sha256 -in server.csr -signkey server.key -out server.crt
vim nginx.conf
   user nginx ;
   worker_processes  auto;
   http {
        server {
                 listen       80;
                 server_name  www.bbs1.com;
                 location / {
                     root   html;
                     index  index.html index.htm;
                     rewrite ^(.*)$ https://www.bbs1.com$1;
      }
    }

           server {
               listen    443 ssl;
               http2 on;
               server_name  www.bbs1.com;
               ssl_certificate     server.crt;
               ssl_certificate_key server.key;
               ssl_session_cache    shared:SSL:1m;
               ssl_session_timeout  5m;
               ssl_ciphers  HIGH:!aNULL:!MD5;
               ssl_prefer_server_ciphers  on;
               location / {
                   root   html;
                   index  index.html index.htm;
                   proxy_pass   http://192.168.90.103:80;
           }
     } 
   }
   # http2 on;开启http2.0 proxy_pass   http://192.168.90.103:80;反向代理apache服务器
   ```
4. 在另一台服务器上编译安装httpd软件

```shell
tar -xf apr-1.7.0.tar.gz 
tar -xf apr-util-1.6.1.tar.gz
cp -r apr-1.7.0 httpd-2.4.46/srclib/apr
cp -r apr-util-1.6.1 httpd-2.4.46/srclib/apr-util
 yum -y install gcc gcc-c++ pcre-devel openssl openssl-devel expat-devel 
cd httpd-2.4.46/
./configure --prefix=/usr/local/apache2 --sysconfdir=/usr/local/apache2/etc --with-included-apr  --enable-expires=shared 
 make && make install

```
   

5. 重启Nginx服务,验证HTTP/2.0效果

   ```shell
  /usr/local/apache2/bin/apachectl stop
  /usr/local/nginx/sbin/nginx
   ```