HTTP探索
Nginx
进程池
Nginx是一个轻量级的Web服务器,因为其CPU、内存占用都非常少,同样的资源配置下就能够为更多的用户提供服务
之前的服务器都是是多线程的,这样会存在创建进程或线程的成本,还会有进程线程上下文切换的额外开销
而Nginx则没有使用多线程,而是使用进程池和单线程的工作模式
Nginx在启动的时候会先创建好固定数量的worker数量,在之后的运行过程中不会再fork出新进程,这就是线程池
可以自动把进程绑定到独立的CPU上,这样就完全消除了进行创建和切换的成本,能够充分利用多核CPU的计算能力
进程池之上还有一个master进程,专门用来管理进程池,监控进程,自动恢复发生异常的worker,保持进程池的稳定和服务能力
I/O多路复用
由于Nginx采用单线程的方式,开发简单,没有互斥锁的成本,但是其处理能力能够超越其他多线程服务器
这是因为Nginx使用了I/O多路复用接口epoll
他把多个HTTP请求处理打散成碎片,都复用到一个单线程中,不按照先来后到的顺序处理,而是只当连接上真正可读可写的时候才处理,可能发生阻塞就立马切换出去,处理其他请求
又因为网络收发并不会消耗太多的CPU计算能力,也不需要却换进程、线程,所以整体的CPU负载是很低的
epoll还有一个特点,大量的连接管理工作都是在操作系统内核中做的,这就减轻了应用程序的负担,所以Nginx可以为每个连接分配很小的内存维护状态
多阶段处理
Nginx处理HTTP请求的方式是通过化整为零的方式处理的
把整个Web服务器分解成多个功能模块,实现高度的灵活性和扩展性
Nginx的HTTP处理有四大类模块:
- handler模块:直接处理HTTP请求
- filter模块:不直接处理请求,而是加工过滤响应报文
- upstream:实现反向代理,转发请求到其他服务器
- balance:实现反向代理的负载均衡算法
职责链:像工厂中的流水线,原料从一头流入,工程会进行各种加工,另一头流出完整产品
Nginx中的handler和filter就是这种模式,HTTP报文是原材料,各个模块就是工厂里的工人,走完模块构成的流水线,出来的就是处理完成的响应报文
OpenResty
Nginx也存在一些缺点,比如Nginx的配置每次修改后都需要重启才能生效
这对于频繁变动业务是非常麻烦的,仅仅增加一行或者删除一行就要分发,重启所有机器,这样成本很高
所以现在又出现了一个Web服务器OpenResty,没有Nginx的缺点,又轻量、高性能、灵活、可动态配置
OpenResty是什么
OpenResty基于Nginx,利用了其模块化,可扩展性的特性,开发了一系列增强模块
OpenResty的核心虽然是Nginx,但是又超过了Nginx,关键在于其**ngx_lua模块**,他把小巧灵活的Lua语言嵌入了Nginx,可以用脚本的方法操作Nginx内部的进程、多路复用、阶段式处理等各种构件
脚本语言的好处:不需要编译,随写随执行
动态的Lua
Lua的设计目标是嵌入到其他应用程序中运行的,为其他编程语言提供脚本化的能力
作为脚本语言,Lua还有一个重要的代码热加载特性,不需要重启进程,就能够从磁盘、Redis或者其他地方加载数据,随时替换内存中的代码片段
使用OpenResty就能实现永不停机,在微秒毫秒级别实现配置和业务逻辑的实时更新
高效率的Lua
同步非阻塞的编程方式是OpenResty高效运行的基础
但是同步非阻塞本质上还是一种多路复用,但是还是有区别的
- epoll是操作系统级别的多路复用,运行在内核空间;而OpenResty则是基于Lua内建的协程,是应用程序级别的多路复用,运行在用户空间,所以消耗资源更少
- OpenResty每一段Lua程序都由携程来调度运行,发生阻塞则马上切换出去,执行其他程序
阶段式处理
OpenResty也使用流水线来处理HTTP请求,底层运行基础是Nginx的阶段式处理
Nginx的流水线是由一个个C模块组成的,只能在静态文件中配置,开发麻烦,配置麻烦
而OpenResty流水线则是由一个个Lua脚本组成的,可以从磁盘上加载,也可以从Redis、MySQL加载,编写调试方便快捷
WAF
HTTPS只是保证了通信链路的安全,但是对于通信链路的两端,也就是客户端和服务器,就不能提供保护了
Web服务遇到的威胁
这有几种常见的攻击Web服务的方式:
-
DDos(洪水攻击):黑客控制许多僵尸计算机,向目标服务器发起大量的无效请求,服务器由于不能区别正常用户和黑客,所以会全收,这样就会挤占了正常用户应有的资源,如果攻击强度很大,那么就会对网站的服务能力造成冲击,耗尽带宽、CPU和内存,导致网站无法正常提供服务
这种方式技术含量比较低,不涉及HTTP协议内部细节
-
SQL注入:利用了服务器字符串拼接形成SQL语句的漏洞,构造出非正常的SQL语句,获取数据库内部的敏感信息
-
HTTP头注入:在Host、User-Agent等字段加上了恶意数据或代码,服务器如果解析不当,则会执行预设的恶意代码
-
XSS攻击:跨站脚本攻击,属于JS代码注入,利用JS脚本获取未设防的Cookie
网络应用防火墙
传统的防火墙只工作在三层或四层,隔离了外网和内网,使用预设的规则,只允许某些IP地址和端口号的数据包通过,拒绝不符合调教的数据流入或流出内网,实际上是一种网络数据过滤设备
而网络应用防火墙也就是WAF,工作在七层,看到的不仅是IP地址和端口号,还能看到整个HTTP报文,所以就能够对报文做更深入细致的审核,使用更复杂的规则来过滤数据,实际上是一种HTTP入侵检测和防御系统
一款产品称为WAF需要具备的功能:
- IP黑名单和白名单,拒绝黑名单访问,或者只允许白名单访问
- URI黑名单和白名单,类似于上一代你,允许或禁止对某些URI进行访问
- 防护DDos攻击,对特定的IP地址限连限速
- 过滤请求报文,防御代码注入攻击
- 过滤响应报文,防御敏感信息外泄
- 审计日志,记录所有检测到的入侵操作
Nginx实现IP地址黑名单:
map $remote_addr $blocked {
default 0;
"1.2.3.4" 1;
"5.6.7.8" 1;
}
if($blocked){
return 403 "you are blocked"
}
CDN
现在我们可以使用HTTPS强化通信链路安全,使用HTTP/2优化传输效率;使用Nginx/OpenResty提升网站服务能力,WAF抵御网站入侵攻击
现在我们来了解一个外部加速HTTP协议的服务,就是CDN,即内容分发网络
为什么要有网络加速
虽然说现在的HTTP传输并不算差,但是在现实中,可能由于各种因素的影响,还是会存在传输慢的情况
在实际中,电缆的传输速度会比光速慢三分之一(20万公里/秒),虽然说这个速度还很快,但是如果距离足够长,那么就会产生一定的时延
并且,互联网是一张大网,由许多小网络组成,小网络内沟通很顺畅,但是网络之间只有很少的联通点,而宽带有限,所以还是会带来延迟的
网络中还存在许多路由器和网关,数据每经过一个节点都会停顿一下,这也会消耗时间带来时延
什么是CDN
CDN就是专门解决长距离访问速度慢而诞生的一种网络应用服务
CDN有三个关键词:内容、分发、网络
-
网络
CDN的核心原则是就近访问,所以如果用户能在本地几十公里的距离内获取到数据,那么时延就近似于0了
所以CDN在全国乃至全球各大枢纽城市建立了机房,部署了大量拥有高存储高带宽的节点,构建了一个专用网络
这个专用网络是跨运营商的、跨地域的,基本上可以认为不存在网络拥堵
-
分发
把源站的内容逐级缓存到网络上的每一个节点上
所以用户在上网的时候就不需要直接访问源站了,而是访问离他最近的一个CDN节点,也叫做边缘节点,这样就可以省去长途跋涉的时间成本了,实现网络加速
-
内容
内容其实是HTTP协议中的资源,如超文本、图片、视频等
资源又分为静态资源和动态资源,静态资源可以被缓存加速、就近访问,但是动态资源只能由源站实时生成,缓存了也没有意义,不过也可以做短暂的缓存(使用Cache-Control),可以被CDN缓存加速
CDN负载均衡
CDN两个关键组成部分:全局负载均衡和缓存系统
全局负载均衡一般简称GSLB,主要用于用户接入网络的时候在CDN专网挑选出一个最佳节点提供服务,解决的是用户如何找到最近的边缘节点,对整个CDN网络进行负载均衡
GSLB最常见的实现方式是DNS负载均衡
权威DNS返回的不是IP地址,而是一个CNAME别名记录,指向的就是CDN的GSLB,因为没拿到IP地址,所以本地DNS就会向GSLB再发起请求,这样就进入了CDN的全局负载均衡系统,开始智能调度:
- 看用户的IP地址,查表得知地理位置,选择最近的边缘节点
- 看用户的运营商网络,找相同网络的边缘节点
- 检查边缘节点的负载情况,选择负载轻的边缘节点
把上面这些因素综合,找出最合适的边缘节点返回给用户
CDN缓存代理
如果缓存系统的服务能力不够,那么即便GSLB算法再优秀也没用
由于资源无穷无尽,所以缓存系统只能缓存最常用的那些资源
这里有两个关键概念:命中和回源
- 命中:用户访问的资源刚好在缓存系统中,可以直接返回给用户
- 回源:缓存中没有用户访问的资源,所以需要用代理的方式回源站取
- 命中率:命中次数与访问次数之比
- 回源率:回源次数与访问次数之比
提高命中率,降低回源率的方法:
- 从存储系统下手,采用高速CPU、大内存等硬件
- 划分一级缓存节点和二级缓存节点
- 使用高性能的缓存服务
\