web应用程详解part1 - http协议详解
如何看待一整套架构的上下游对接/通信?
上下游不用管具体是什么软件,只要通信协议能对上就可以,即上游用什么协议封装,下游就英爱用什么协议解封。
1、web应用层各中程序的部署
协议:
http协议
cgi、fastcgi、php-fpm ---- >php语言体系
wsgi、uwsgi、agi ---- >python语言体系
http协议 ---->JAVA语言
http协议 ---->go语言
不同语言程序的部署(服务部分和程序部分)
部署php: nginx -------- php-fpm( php应用程序)-------- mysql
部署Python:nginx -------- uwsgi( python应用程序)-------- mysql
部署java应用:nginx -------- tomact( java应用程序)-------- mysql
部署go应用:nginx -------- go二进制程序 -------- mysql
在复杂的软件架构中,上下游系统之间的对接与通信是关键环节。无需关注上下游具体使用的是何种软件,只要双方遵循相同的通信协议,即可实现无缝对接。换言之,上游系统使用某种协议进行数据封装,下游系统则需采用相同的协议进行解封,以确保信息的准确传递。 1. Web应用层的多元化程序部署 为了实现高效灵活的Web应用,部署过程中需要选择合适的通信协议,以匹配相应的编程语言体系: HTTP协议:作为Web应用的基础协议,负责客户端与服务器之间的通信。 CGI、FastCGI、PHP-FPM:这些协议专门用于PHP语言体系,通过PHP-FPM管理PHP应用程序,实现动态内容生成。 WSGI、uWSGI、AGI:针对Python语言体系,优化Python应用程序的性能与扩展性。 Java语言:通过HTTP协议与Web服务器交互,利用Tomcat等应用服务器运行Java应用程序。 Go语言:直接通过HTTP协议与Web服务器通信,执行Go编写的二进制程序。 在部署不同语言编写的应用程序时,服务器架构通常包括以下几个部分: 部署PHP应用:Nginx作为Web服务器,通过PHP-FPM与PHP应用程序通信,同时连接MySQL数据库存储数据。 部署Python应用:Nginx同样作为Web服务器,使用uWSGI与Python应用程序交互,连接MySQL数据库。 部署Java应用:Nginx与Tomcat结合,运行Java应用程序,并与MySQL数据库进行数据交换。 部署Go应用:Nginx直接与Go编写的二进制程序通信,访问MySQL数据库。 2. Nginx详解:四层与七层负载均衡及Web服务功能 Nginx作为一款高性能的Web服务器和反向代理服务器,广泛应用于现代Web架构中。它不仅支持四层(传输层)和七层(应用层)的负载均衡,还能在Web层充当重要服务角色: 四层负载均衡:基于IP和端口进行负载分配,适用于TCP/UDP协议,适合处理大量并发连接。 七层负载均衡:基于HTTP/HTTPS请求的URL、头部等信息进行负载分配,提供更智能的流量管理。 Web服务功能:Nginx可作为静态内容服务器,处理高速的HTTP请求,同时通过代理功能,将动态请求转发给后端应用程序服务器。
用户用浏览器访问网页,默认走的都是http协议,所以要深入研究web层,必须掌握http协议。
用户浏览器----------HTTP协议------------web应用程序
2、什么是http协议?
HTTP(HyperText Transfer Protocol,超文本传输协议)。
普通文本:文件内存放的是一些人类能认识的文字符号(汉字、英文、阿拉伯数字......)。
超级文本:除了普通文本内容之外,还有视频、图片、语音、超链接......
超文本包含:html文件、css文件、js文件、图片、视频......
http协议都能传输上述内容,所以说http协议是专用于传输超文本的协议。
http协议主要用于B/S架构的程序。
http协议是基于tcp协议的。
强调:基于http协议发包之前,必须建立tcp协议的双向通路
3、http协议的发展史(主要经历3个版本)
伴随着浏览器的诞生---->网景浏览器(万能客户端)----访问---->各种各样的服务端。
http0.9(基本不用了)
请求方法:只支持GET方法
请求头:不支持请求头。
响应信息:只支持纯文本,不支持图片。
无连接:利用完tcp连接之后会立即回收。
http协议通信,先建立tcp连接,然后客户端发请求包,服务端收到后发送响应包,服务端一旦发送完响应包之后,服务端会立即主动断开tcp连接,下次http通信还需要重新建立tcp连接。所以我们称http协议是无连接的(持久连接/长连接)
无状态:(一个http协议的请求无法标识自己的身份)
http无法保存状态,比如登录状态
http1.0(还有再用)
请求方法:支持GET(查)、POST(改)、DELETE(删)、PUT(增)......
请求头:发送者在发的时候可以定制一些自己的请求参数
响应信息:更加丰富,支持超文本
支持缓存
无状态:解决方案:cookie、session、jwt
无连接:解决方案:支持持久连接/长连接 keep-alive
http1.1(主要在用)
在1.1的基础上又新增了一些功能:长连接(默认了所有请求都启用长连接)、pipeline(请求流水线/管道化)、分块传输编码chunked、
浏览器与web服务器建立tcp连接后,双方就可以通过发送请求信息和应答消息进行数据传输了。
问题:
同一个用户在短期内频繁的访问服务端,会造成大量的时间都消耗在重复建立tcp连接,在高并发场景下,对服务端是非常大的消耗,对客户端的访问速度也会很慢。
目标:
同一个用户在短期内访问多次服务端,不要重复建立tcp连接,而是能够共用一个tcp连接
解决方案:支持持久连接/长连接 keep-alive
前提:
发送完http响应包之后,服务端立即断tcp连接,这是服务端的默认行为。
要改变这种默认行为,要客户端通知服务端才行
实现:
客户端在发送http的请求时,需要在请求头里带上connection:keep-alive这个参数,服务端的keepalive_alive设置要大于0。
服务端收到这个参数之后,服务端会保持与这一个客户端tcp连接一段时间,响应时也会在响应头里放connection:keep-alive这个参数。
该tcp连接会保持一段时间直到达到服务端设置的keepalive_timeout时间。
补充:
在http1.0协议中还需要在发请求时自己加上connection:keep-alive参数
问题:
服务端无法标识一个http请求的唯一性(http协议本身就没有可以表示自身请求唯 一性的字段或机制),会导致用户登录状态无法保存,那么每次请求都需要重新输一遍账号密码
目标:
服务端要客户端有状态(让客户端每次发请求时都能标识自身的唯一性)
解决方案:
cookie、session、jwt
cookie机制:
流程:
1、首先第一次请求带着认证(账号、密码)到服务端通过认证后,服务端会生成一段独一无二的字符,生成响应信息把这一段字符带进去,响应头里会有set-cookie:字符(服务端会生成一段独一无二的字符)k1=v1;k2=v2;k3=v3
2、客户端(浏览器)收到服务端的响应信息后开始解析协议,响应头里有set-cookie立刻明白服务端让它保存cookie值,对应好对应的网站
3、下次再发请求的时候如果还是这个网站,浏览器会查找到本地的存放的该网站的这个cookie值,注入http协议的请求头里发送给服务端
特点:
1、cookie是浏览器的功能,是存放在客户端的;
2、cookie内存放的内容是可以被客户端篡改的;
cookie机制+session机制:
流程:
1、客户端访问一个站点,输入账号密码进行认证,服务端收到请求通过认证之后会产生一些标识用户身份的数据,这些数据(value)是放在服务端的,称之为session,针对这些数据会得到一个对应的key值。
2、服务端会把key放入set-cookie里,返回给客户端
3、客户端收到响应后,会把key存入到本地的浏览器cookie
4、下次请求该网站,会带着key去目标站点访问,目标站点收到后,会根据key取出value,value里放着本次请求的身份信息
特点:
1、把保密数据放在服务端,称之为session数据,然后对session数据生成一个key值存入客户端的cookie中,可以防止篡改
2、 在集群的场景下,需要做会话共享(session存入共享的地方,通常会将session数据存入Redis数据库缓存,Redis作为一个大家都依赖的共享点,会影响集群的扩展性)
总结:
单用cookie来存放状态信息:
优点:服务端不需要做会话共享
缺点:客户端可以篡改状态信息,不安全
cookie+session:
优点:状态信息即session数据是存放在服务端的,状态信息不会被篡改
缺点:服务端需要做会话共享,增加了集群的耦合性
jwt(json web token)机制:核心是即不需要做会话共享,又很安全。
服务端会将状态信息进行加密,然后把加密的数据放入客户的cookie中---->解决了篡改的问题;
下次请求会从cookie中取出token带上一切发送给服务端,服务端收到了会用加密算法解密---->不需要再做会话共享。
基于http协议完整的请求响应流程:
浏览器访问一个url地址
1、浏览器会先问本地dns把域名解析为ip地址
2、浏览器作为客户端会与目标ip:port建立tcp连接
3、浏览器会基于http协议封装请求包(osi七层的封包流程)
4、服务端收到包(osi七层的解包流程),拿到一个http协议的请求包,按照http协议解析请求(请求首行、请求头、空行和请求体数据),会拿到请求路径部分,服务端会打开该文件(对一个文件描述符)把文件内容从硬盘读入内存,然后服务端程序会基于http协议封装读入内存的数据,形成一个响应包发给客户端浏览器。
5、浏览器收到http协议的响应包之后,先解析响应首行,看到响应的状态码,知道本次访问是否成功;再解析响应头,可以拿到Content-Type:就知道该用什么方法来解析内容,如果值为text/html就会按照html代码的方式来解析返回的内容,再读取内容部分,当成html代码来解析。
6、在解析html代码的过程中,有可能遇到css、jss、图片、视频等资源,会发起多次的请求再往回拿数据,直到把整个页面都渲染完毕。
补充:http1.1默认是开启持久连接的(核心是请求与响应头里都带着connection:keep-alive)
URI:统一资源标识符,是一种思想
URL:统一资源定位符,是uri的一种具体实现
URN:也是uri的一种具体实现
地址都是用来找东西,比如ip地址是用来找唯一的一台机器,如果再搭配上端口号就可以找到那台机器上的某个网络程序了,所以ip+port可以找到全世界范围内独一无二的程序(192.168.1.112:8080)。
发请求找到程序,程序还需要定位到具体的文件,在ip+port的基础之上再定位到文件那就是url地址,访问资源的西协议如果是http协议那完整的url地址就是http://192.168.1.112:8080/a/b/1.txt?a=1&b=2&age=10#name_lable5
url地址一般由三个关键部分组成:访问资源的命名机制,存放资源的主机名,资源本身的名称,由路径表示,着重强调于资源
http:// 协议部分
192.168.1.112:8080 ip+port(一般是域名,但是域名最终也是解析成ip+port)
/a/b/1.txt 路径部分
?a=1&b=2&age=10 请求参数部分,主要用于get方法
#name_lable5 锚,定位到某个页面的具体位置
6.1、请求request
包含四部分:请求首行、请求头、空行、请求体数据
请求首行:由3部分组成(请求方法、URI和HTTP协议版本),它们之间用空格分隔。
请求方法 请求的路径部分及后续部分 使用的http协议版本
请求方法:
GET ---- 检索URI所标识的资源,请求的数据可以放在url地址的?后面。
POST ---- 请求服务器接受被写入客户端输出流中的数据,携带请求体数据。
DELETE ---- 请求服务器删除URI中命名的资源。
PUT ---- 服务器保存请求数据作为指定URI新内容的请求。
HEAD ---- 与GET方法相同,不同的是指挥获取响应头(包含状态码)而不会获取响应的数据。
OPTIONS ---- 请求得到服务器支持的请求方法。
请求头:都是key:value格式,用来定制一些参数
常见参数:
accept:代表能接收什么样的数据
accept-encoding:支持压缩算法
accept-language:能接收的语言
空行:隔开请求体数据
请求体数据:
如果是GET 方法是没有请求体数据的
6.2、响应response
包含四部分:响应首行、响应头、空行、响应体
响应首行:协议版本 状态码
常见状态码:
1xx:信息,请求收到,继续处理
2xx:成功
3xx:重定向,为了完成请求,必须进一步执行的动作。
4xx:客户端错误,请求包含语法错误或者请求无法实现。404表示客户端访问的资源不存在,403表示客户端没有对目标资源的访问权限,
5xx:服务端错误。503表示服务端故障
响应头:
常用字段:
set-cookie:要求浏览器把cookie信息存入到本地
cache-control:缓存控制手段
connection:连接状态
content-type:告诉浏览器本次返回内容的格式
空行:

浙公网安备 33010602011771号