简介
- 前端、运维、后端都会用到nginx解决问题
- 这里介绍的主要内容:
- 初始nginx——基本用法
- nginx架构模块——进程模型和数据结构
- HTTP模块
- 反向代理和负载均衡——不同上游协议的反向代理
- 系统层性能优化——Linux磁盘内存CPU
- nginx与OpenResty——第三方模块
- 适合小白入门,为深入理解nginx打下基础
初识nginx
- 网页访问需要web服务器支持,常见的有Apache、Tomcat、uwsgi、gunicorn,nginx的出现让网站的性能大大提升;(如果你将Linux电脑理解成服务器,可以将web服务器理解成上面的软件)
- nginx的主要应用场景:
- 理解一下这段话:
- 一个web请求过来后,首先经过nginx再到应用服务(例如Tomcat、Django)
- 然后访问Redis或者MySQL数据库提供基本的数据服务
- 这里有一个问题,应用服务的运行效率很低,TPS、QPS和并发是受限的。我们可以把很多的应用服务组成集群,此时就需要nginx的反向代理功能,把动态请求传导给应用服务
- 集群的出现带两大问题:扩容和容灾,这就要求反向代理具有负载均衡功能
- 随着网络链路的增长,时延必定增加,所以如果能将已经请求来的静态内容,或暂时不变的内容放在缓存中,便能够减少时延,这就是反向代理的缓存功能
- 还有一些静态资源,例如css和js文件、小图片,可以直接让nginx访问服务器静态文件夹,不必通过应用服务
- 数据库的应用场景相较应用服务简单,他的TPS和并发能力远高于应用,所以这里出现第三个应用场景,nginx直接访问数据库(API),这也要求API服务有强大的业务处理能力,OpenResty提供的高质量第三方模块可以满足
nginx的出现
- 在NGINX之前最常用的当属Apache,但是随着硬件的发展,多核处理器出现,Apache并没有做好准备,它的进程切换思想损耗了很多性能
- Apache被设计成一个进程同一时间只会处理一个请求,只有当此次请求完毕,才会处理下一个
- 往往同一时间会出现数以万计的请求,但没法开如此多的进程,此时只能进程切换来接request,很麻烦!
- nginx的核心优势
- 右表展示的是随着并发量的增加,服务器的RPS急剧下降,但是nginx很平稳;怎么实现的呢?这涉及到多CPU合理调度和IO多路复用(可以学一下OS&计组 ),后面说;
- 热部署:在不宕机的情况下更新升级,非常关键
组成
- 主要由四部分组成
- nginx二进制可执行文件:包含了nginx本身和第三方模块功能(处理请求的方式)
- nginx.conf配置:定义功能如何使用
- access.log日志:记录http请求信息
- error.log日志:定位错误
- nginx官网可以看到版本:
- CHANGES可以看到具体更新情况:2018年之后bug很少了
- nginx有免费版(org)和商业版(com),如果业务不是很复杂,免费版足够;如果需要开发API服务器和web防火墙,可以使用openresty
基本使用
- 环境:虚拟机CentOS系统
- 如果要使用第三方模块,必须通过编译的方式安装,步骤如下:
- 如果你不需要第三方模块可直接命令行安装,默认安装在/usr/local/nginx
- 在Linux系统上,下载nginx:复制最新稳定版的链接地址,命令行:
wget http://nginx.org/download/nginx-1.18.0.tar.gz # 解压并进入
- 目录结构
- contrib/vim下的文件可以让nginx配置文件在vim编辑时语法高亮显示,需要拷贝出来
cp -r contrib/vim/* ~/.vim/ # 先创建~/.vim vim conf/nginx.conf
- 编译
- 参数介绍
- 常使用的是
--prefix
参数,默认安装在/usr/local
下(centos) - 也可以直接执行命令:
./configure
,如果没错当前目录会生成objs文件夹,主要是里面的这个文件:决定了哪些模块编译进去
- 要知道这个是nginx的目标文件,如果不是首次安装,需要版本升级时,不能执行makeinstall,而是make后将这里的objs/nginx文件拷贝到安装目录sbin下,参考,注:版本升级后就的进程并不会结束,可以回退
- 执行
make
编译,生成的中间文件都会放在objs/src目录 - 执行
make install
- 参数介绍
配置语法
-
nginx的功能模块都需要配置使用,遵循配置语法
-
主要配置都包含在HTTP模块,一个http指令包含四块:
- http表示里面所有的指令只能由HTTP模块解析
- upstream表示上游服务,当nginx需要与Django等服务器交互时使用(负载均衡)
- server对应一个或一组域名,一个server相当于一台web服务器(不同进程)
- location是url表达式
- 整个配置相当于在匹配处理网络请求!
-
配置示例:nginx.conf
-
注意时间单位:
expires 3m
表示三分钟后刷新
-
注意空间单位:
zone=one:10m
表示一个10M大小的共享内存空间
命令行
- Linux中常用的操作nginx的指令
- nginx操作进程使用发信号的方式,这里用
-s
- 启动
sudo ./nginx -c ../conf/nginx.conf
(指定到sbin目录下执行,也可以配置环境变量,这里讲究个原生态)ps -ef|grep nginx
查看进程 - 重载配置文件:
./nginx -s reload
- 日志文件切割:
- 备份:
mv access.log access.log.bak
./nginx -s reopen
- 通常写成定时任务,放在定时crontab,例如写个refresh.sh如下,放在nginx安装目录即可
- 备份:
- 启动
- Demo:静态资源web服务器
- 如果你是小白,这个必须跟着来,自己解决你遇到的bug
- 你可以用虚拟机(NAT),会有内网IP ,直接配给server_name
- 将user换成你的nginx启动用户,一般是root,否则可能403
- 配置:
http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; # 日志格式 access_log logs/access.log main; sendfile on; tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; gzip on; # 大文件压缩 gzip_min_length 50; # 小于50字节不压缩 server { listen 8080; # 访问端口 server_name 192.168.154.66; #charset koi8-r; access_log logs/test.access.log main; # 所有访问此服务器端口8080的都记录在此 location / { #root html; # 定义资源文件目录,nginx默认以安装目录定位,这里的html肯定是放在安装目录下的,如果是/html就是服务器根目录,注意区别 #index index.html index.htm; # index一般是网站首页 alias test/; # 表示所有的请求都转换到访问test目录 autoindex on; # 访问test下的文件夹,会以目录形式呈现,共享静态资源,类似下图 set $limit_rate 1k; # 限制传输速度,1k会非常慢,禁用浏览器缓存(304)可以观察到;$是变量,limit_rate是nginx模块提供的 } ......
反向代理
- 我们将搭建好的静态服务器作为上游服务器,再配置一台nginx服务器反向代理
- 上游服务器即我们的业务服务器,写代码处理逻辑的,效率低,一般对公网不提供访问,所以配置
listen: 8080; server_name 127.0.0.1;
(更改配置文件名并启动-c
) - 反向代理可理解成边缘服务器,分发请求,提供负载均衡功能
- 做反向代理,修改配置文件:nginx.conf
user root; http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; # 日志格式 access_log logs/access.log main; sendfile on; tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; gzip on; # 大文件压缩 gzip_min_length 50; # 小于50字节不压缩 include vhost/*.conf; # 新建vhost,可将其他域名的nginx配置放进去;nginx.conf相当于入口 upstream local { # vim ndd p # 这也是做负载均衡的基本方法,业务服务器可以运行在多个端口,这里都配上,nginx默认采用交替轮流的算法思想分发请求 server 127.0.0.1:8080; # 转发请求地址 } server { listen 80; server_name 192.168.154.66; location / { # 以下配置是因为反向代理后,有些变量值会法发生变化,上游服务器可能找不到对应值 # 例如tcp连接,代理和用户连接,上游拿到的是localhost,此时需要将RealIP给上游,做限制访问等操作使用 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://local; # 代理转发 } } }
- 此时直接访问就IP就可将请求转发到业务服务器
- proxy_pass的所有配置可以从官网查看
- 需要关注的是
proxy_cache
,即代理缓存,将有些内容设置缓存时间,请求时直接返回缓存内容 - 来个官网的例子,稍加修改:
# 10M的共享内存,保存缓存内容的键 proxy_cache_path /tmp/nginx_cache/cache levels=1:2 keys_zone=cache_zone:10m max_size=1g use_temp_path=off; # map $request_method $purge_method { # 暂时没看懂 # PURGE 1; # default 0; # } server { ... location / { proxy_pass http://local; # 前面的配置也都加上 proxy_cache cache_zone; # 对应上key的名称 proxy_cache_key $host$uri$is_args$args; # 不同用户展示的内容可能不一样,所以加入用户参数 # proxy_cache_purge $purge_method; proxy_cache_valid 200 304 302 1d; } }
- 此时关闭我们的业务服务器(kill吧,好像没有指定pid的命令),还是可以访问网址
- 上游服务器即我们的业务服务器,写代码处理逻辑的,效率低,一般对公网不提供访问,所以配置
监控access
- access日志记录了nginx的大部分响应非常重要,但是长的很难看,这里使用GoAccess实现可视化
- 它会以HTML文件的格式展示,安装
sudo yum install goaccess
,配置可以参考官方 - 这里介绍一种常用方式,切换到logs目录下执行:
# 这会占用当前shell goaccess test.access.log -o ../html/accessreport.html --real-time-html --time-format='%H:%M:%S' --date-format='%d/%b/%Y' --log-format=COMBINED # 先在nginx.conf添加匹配 location /report.html { alias html/accessreport.html; }
- 此时访问/report.html即可看到:
SSL/TLS
- 先看看HTTP和HTTPS的区别
- HTTPS协议需要到证书颁发机构(Certificate Authority,简称CA)申请证书,一般免费证书很少,需要交费
- HTTP是超文本传输协议,信息是明文传输,HTTPS则是更具有安全性的SSL加密传输协议
- 使用的端口不一样,HTTP是80,HTTPS是443
- 即数据完整性、数据隐私性和身份认证;完整性和隐私性由TLS Record Protocol保证,身份认证由TLS Handshaking Protocols实现
- SSL/TLS是两个网络安全传输协议,保证数据完整性和数据加密,规定了接下来要讲的所有东西
- 发展过程:
- TLS加密套件解读:
- 发展过程:
- 对称加密原理
- 交互双方持有相同密钥,根据加密算法生成加密文档
- 没有密钥,知道了加密算法也不能解密
- 非对称加密
- 生成的是一对密钥,即公钥和私钥
- 用公钥加密,私钥才能解密;用私钥加密,公钥才能解密
- 什么是证书?
- 证书用来验证身份,但客户端(操作系统或浏览器等)无法内置所有证书,需要服务端将证书发送给客户端;因此网站需要申请证书才能安全运作
- PKI公钥基础设施:注意过程,这就是TLS协议的规定(也叫建立SSL连接)
- CA颁发证书
- nginx服务器部署证书
- 用户请求证书并判断有效性(主要看给这个站点颁发的根证书是否有效;有证书链)
- 证书包含的是服务器公钥,浏览器验证通过后,会给服务器发送一个用公钥加密的随机值
- 服务器用私钥解密,获取随机值后,以后的通信便通过此值加密
- 最消耗性能的是交换密钥和加密数据,nginx在面对小文件时主要优化ECDHE算法,面对大文件时主要优化AES算法
- 证书类型:EV就比较高级,能在前面显示名称
- 免费证书,将我们的站点改造成https
- 安装python工具
yum install python-certbot-nginx
- 执行命令,此工具会自动修改配置文件,这里需要指出nginx的配置文件目录,会增加一些东西
certbot --nginx --nginx-server-root=~/nginx_test/conf/ -d roykun.vip # -d指定要申请证书的域名
- 安装python工具
更多服务
- 基于OpenResty用Lua语言实现更多服务
- 下载OpenResty源码
- openresty是一款基于 NGINX 和 LuaJIT 的 Web 平台,大部分和nginx结构相同
- 进入bundle目录,可以看到nginx-1.19.3,即是根据1.19版本的nginx开发的,我们的nginx是1.18,这并不影响,只不过用不了一些nginx的新特性
- 查看
./configure --help|more
,--without
表示默认内置在模块中,可以移出去 - 编译安装,这次就不指定目录了
./configure gmake sudo gmake install
- 默认安装在
/usr/local/openresty/
- 注:openresty相当于nginx加强版,此时关闭之前的nginx服务器,在这里配置启动
- nginx的配置语法和Lua不一样,可以使用
content_by_lua
server { listen 80; server_name 192.168.154.66; #charset koi8-r; #access_log logs/host.access.log main; location /lua { #root html; #index index.html index.htm; default_type text/html; content_by_lua 'ngx.say("User-Agent:",ngx.req.get_headers()["User-Agent"])'; } location / { alias html/test/; } }
- 启动
sudo ./sbin/nginx -c conf/nginx.conf
,访问之
- nginx的配置语法和Lua不一样,可以使用
小结
- 以上便是nginx入门级的使用总结,关键在于把握nginx作为边缘节点,与业务服务器的关系
- 接下来更进一步了解为什么nginx能如此优秀