程序员L札记

V1

2022/12/14阅读:32主题:橙心

Nginx入门与实践

Nginx入门与实践

@(随手记)


前言

这一篇是本人当时的学习笔记,分享给大家

基础篇

什么是Nginx

  1. Nginx简述

Nginx是一个开源且高性能、可靠的HTTP中间件、代理服务

  1. 常见的HTTP服务

HTTPD-Apache基金会 IIS-微软 GWS-Google

Nginx特性

  1. I/O多路复用epoll

1.1 I/O多路复用

多个描述符的I/O操作都能在一个线程内并发交替的顺序完成,这就叫I/O多路复用。这里的「复用」,指的是复用一个线程

1.2 什么是epoll

IO多路复用的实现方式:select、poll、epoll

  1. 轻量级
  • 功能模块少
  • 代码模块化
  1. CPU亲和(affinity)

是一种吧CPU核心和Nginx工作进程绑定方式,把每个worker进程固定在一个CPU上执行,减少切换CPU的cache miss,获得更好的性能。

  1. sendfile

Nginx安装(CentOS)

安装

参考地址1

参考地址2

  1. 创建/etc/yum.repos.d/nginx.repo
  2. 添加如下内容
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
  1. 开始安装
 yum list | grep nginx
 yum install nginx
#  查看版本
 nginx -v
#  查看配置参数
 nginx -V

4.启动

# 检查配置是否正确
nginx -t -c /etc/nginx/nginx.conf
# 启动
nginx -s start -c /etc/nginx/nginx.conf

安装目录

  1. 查看安装目录
rpm -ql nginx
  1. 目录详解

nginx.conf配置文件

Nginx日志类型

  • error.log
  • access_log

error.log指令

Syntax: error_log file [level];
Default: 
error_log logs/error.log error;
Context: main, http, mail, stream, server, location

access_log指令

Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default: 
access_log logs/access.log combined;
Context: http, server, location, if in location, limit_except

log_format指令

Syntax: log_format name [escape=default|json|none] string ...;
Default: 
log_format combined "...";
Context: http

Nginx变量

  • HTTP请求变量 arg_PARAMETER、http_HEADER、send_http_HEADER
  • 内置变量
  • 自定义变量 参考网址

Nginx默认模块

ngx_http_stub_status_module

Nginx的客户端状态

指令

参考网址

Syntax: stub_status;
Default: —
Context: server, location

ngx_http_random_index_module

在主目录中随机选择一个主页

指令

参考网址

Syntax: random_index on | off;
Default: 
random_index off;
Context: location

ngx_http_sub_module

http响应内容替换

指令

参考网址

Syntax: sub_filter string replacement;
Default: —
Context: http, server, location

ngx_http_limit_conn_module

http连接的限制(一次http请求建立在tcp连接的基础上)

指令

参考网址

Syntax: limit_conn_zone key zone=name:size;
Default: —
Context: http
Syntax: limit_conn zone number;
Default: —
Context: http, server, location

ngx_http_limit_req_module

http请求的限制

指令

参考网址

Syntax: limit_req_zone key zone=name:size rate=rate [sync];
Default: —
Context: http
Syntax: limit_req zone=name [burst=number] [nodelay | delay=number];
Default: —
Context: http, server, location

ngx_http_access_module

基于ip的访问控制

指令

参考网址

Syntax: allow address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except
Syntax: deny address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except
局限性
  • 只能通过$remote_addr控制
解决办法
  • 采用其它HTTP头信息控制访问,如HTTP_X_FORWARD_FOR
  • 结合geo模块
  • 通过HTTP自定义变量传递

ngx_http_auth_basic_module

基于用户的安全认证的访问控制

指令

参考网址

Syntax: auth_basic string | off;
Default: 
auth_basic off;
Context: http, server, location, limit_except
Syntax: auth_basic_user_file file;
Default: —
Context: http, server, location, limit_except
局限性
  • 用户信息依赖文件方式
  • 操作管理机械,效率低下
解决方法
  • Nginx结合LUA实现高效验证
  • Nginx和LDAP打通,利用nginx-auth-ldap模块

场景实战篇

静态资源WEB服务

CDN场景

文件读取
Syntax: sendfile on | off;
Default: 
sendfile off;
Context: http, server, location, if in location
  • tcp_nopush

sendfile开启的情况下,提高网络包的传输效率。「大文件传输」 参考网址

Syntax: tcp_nopush on | off;
Default: 
tcp_nopush off;
Context: http, server, location
  • tcp_nodelay

keepalive连接下,提高网络包的传输实时性 参考网址

Syntax: tcp_nodelay on | off;
Default: 
tcp_nodelay on;
Context: http, server, location
  • 压缩「ngx_http_gzip_module」

压缩传输,对图片的压缩比不高。 参考网址

Syntax: gzip on | off;
Default: 
gzip off;
Context: http, server, location, if in location
  • 扩展Nginx压缩模块
  1. ngx_http_gzip_static_module

预读gzip功能,需要提前使用gzip压缩源文件,占用额外的磁盘空间 参考网址

  1. ngx_http_gunzip_module

支持gunzip的压缩方式,解决部分浏览器不支持gzip 参考网址

  • 配置案例

浏览器缓存

ngx_http_headers_module模块 在HTTP response header中添加Cache-ControlExpires头信息 参考网址

流程图
指令
Syntax: expires [modified] time;
expires epoch | max | off;
Default: 
expires off;
Context: http, server, location, if in location

跨域访问

ngx_http_headers_module模块 利用add_header指令,添加Access-Control-Allow-OriginAccess-Control-Allow-Methods头信息 参考网址

指令
Syntax: add_header name value [always];
Default: —
Context: http, server, location, if in location

防盗链

防止资源被盗用 区别哪些请求是非正常的用户请求 基于http_referer防盗链配置模块 参考网址

指令
Syntax: valid_referers none | blocked | server_names | string ...;
Default: —
Context: server, location

代理服务

参考网址 ngx_http_proxy_module模块

Syntax: proxy_pass URL;
Default: —
Context: location, if in location, limit_except

反向代理

正向代理

缓冲

proxy_buffer_size

设置用于读取从代理服务器接收的响应的第一部分的缓冲区的大小。这部分通常包含一个小的响应头。默认情况下,缓冲区大小等于一个内存页。这是4K还是8K,取决于平台。然而,它可以做得更小

Syntax: proxy_buffer_size size;
Default: 
proxy_buffer_size 4k|8k;
Context: http, server, location
proxy_buffering

当缓冲被启用时,nginx会尽快从代理服务器接收响应,并将其保存到proxy_buffer_sizeproxy_buffers指令设置的缓冲区中。如果整个响应无法装入内存,则可以将其中一部分保存到磁盘上的临时文件中。写入临时文件由proxy_max_temp_file_sizeproxy_temp_file_write_size指令控制。

当缓冲被禁用时,响应会立即同步地传递到客户端。nginx不会尝试从代理服务器读取整个响应。nginx一次可以从服务器接收到的最大数据大小是由proxy_buffer_size指令设置的。

缓冲也可以通过在“X-Accel-Buffering”响应头字段中传递“yes”或“no”来启用或禁用。可以使用proxy_ignore_headers指令禁用此功能。

Syntax: proxy_buffering on | off;
Default: 
proxy_buffering on;
Context: http, server, location
proxy_buffers

为单个连接设置用于从代理服务器读取响应的缓冲区的数量和大小。默认情况下,缓冲区大小等于一个内存页。这是4K还是8K,取决于平台。

Syntax: proxy_buffers number size;
Default: 
proxy_buffers 8 4k|8k;
Context: http, server, location
proxy_busy_buffers_size

当启用代理服务器的响应缓冲时,将限制缓冲区的总大小,这些缓冲区在响应尚未完全读取时忙于向客户机发送响应。与此同时,剩余的缓冲区可以用于读取响应,如果需要,还可以将响应的一部分缓冲到临时文件中。默认情况下,大小由proxy_buffer_sizeproxy_buffers指令设置的两个缓冲区的大小限制

Syntax: proxy_busy_buffers_size size;
Default: 
proxy_busy_buffers_size 8k|16k;
Context: http, server, location
proxy_max_temp_file_size

当启用了来自代理服务器的响应的缓冲,并且整个响应不适合proxy_buffer_sizeproxy_buffers指令设置的缓冲区时,可以将响应的一部分保存到临时文件中。这个指令设置临时文件的最大大小。每次写入临时文件的数据大小由proxy_temp_file_write_size指令设置。

Syntax: proxy_max_temp_file_size size;
Default: 
proxy_max_temp_file_size 1024m;
Context: http, server, location
proxy_temp_file_write_size

在启用代理服务器对临时文件的响应缓冲时,限制一次写入临时文件的数据的大小。默认情况下,大小由proxy_buffer_sizeproxy_buffers指令设置的两个缓冲区限制。临时文件的最大大小由proxy_max_temp_file_size指令设置。

Syntax: proxy_temp_file_write_size size;
Default: 
proxy_temp_file_write_size 8k|16k;
Context: http, server, location
重定向
Syntax: proxy_redirect default;
proxy_redirect off;
proxy_redirect redirect replacement;
Default: 
proxy_redirect default;
Context: http, server, location

负载均衡调度器SLB

GSLB

SLB

七层负载均衡

Nginx负载均衡

配置语法

参考网址

Syntax: upstream name { ... }
Default: —
Context: http

例子

upstream backend {
    server backend1.example.com weight=5;
    server 127.0.0.1:8080       max_fails=3 fail_timeout=30s;
    server unix:/tmp/backend3;

    server backup1.example.com  backup;
}

server参数

  • down

当前的server暂时不参与负载均衡

  • backup

将服务器标记为备份服务器。它将在主服务器不可用时传递请求。

  • max_fails

允许请求失败的次数

  • fail_timeout

经过max_fails次失败后,服务暂停的时间

  • max_conns

限制最大连接数

负载均衡算法

轮询

按时间顺序逐一分配到不同的后端服务器

加权轮询

weight值越大,分配到的访问几率越高

ip_hash

每个请求按访问ip的hash结果分配,这样来自同一个ip的请求固定访问同一个后端服务器

url_hash

按照访问的url的hash结果来分配请求,每个url定向到同一个后端服务器。「通过hash key实现」

least_conn

最少连接数,哪个server连接数少就分配到哪个

hash

hash自定义的key

动态缓存

缓存类型

  • 客户端缓存
  • 代理缓存
  • 服务端缓存

代理缓存

ngx_http_proxy_module模块 参考网址

proxy_cache_path

设置缓存的路径和其他参数

Syntax: proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
Default: —
Context: http
proxy_cache

定义用于缓存的共享内存区域。同一个区域可以用于多个地方。参数值可以包含变量(1.7.9)。off参数禁用从以前的配置级别继承的缓存。

Syntax: proxy_cache zone | off;
Default: 
proxy_cache off;
Context: http, server, location
proxy_cache_valid

为不同的响应代码设置缓存时间

Syntax: proxy_cache_valid [code ...] time;
Default: —
Context: http, server, location
proxy_cache_key

定义用于缓存的键

Syntax: proxy_cache_key string;
Default: 
proxy_cache_key $scheme$proxy_host$request_uri;
Context: http, server, location

补充

清理缓存
  • rm -rf 删除缓存目录内容
  • 第三方扩展模块ngx_cache_purge
部分页面不缓存
  • proxy_no_cache

定义不将响应保存到缓存的条件。如果字符串参数中至少有一个值不为空且不等于“0”,则不会保存响应。

Syntax: proxy_no_cache string ...;
Default: —
Context: http, server, location
大文件的分片请求
  • ngx_http_slice_module

默认情况下不构建此模块,应该使用——with-http_slice_module配置参数启用它

  • 配置示例
location / {
    slice             1m;
    proxy_cache       cache;
    proxy_cache_key   $uri$is_args$args$slice_range;
    proxy_set_header  Range $slice_range;
    proxy_cache_valid 200 206 1h;
    proxy_pass        http://localhost:8000;
}

slice指令设置分片的大小为1m。 这里使用了proxy_set_header指令,在取源时的HTTP请求中添加了Range头部,向源服务器请求文件的一部分,而不是全部内容。在proxy_cache_key中添加slice_range变量这样可以分片缓存

深度学习篇

动静分离

通过中间件将静态请求和动态请求分离。目的是减少不必要的请求消耗,减少请求延时。

Nginx的rewrite规则

实现url重写以及重定向

场景

  • URL访问跳转,支持开发设计
  • SEO优化
  • 维护「后台维护,流量转发等」
  • 安全

指令

参考网址 ngx_http_rewrite_module模块

Syntax: rewrite regex replacement [flag];
Default: —
Context: server, location, if

正则表达式

  • . 「匹配除换行符以外的任意字符」
  • ? 「重复0次或1次」
  • + 「重复1次或更多次」
  • * 「匹配前面的子表达式任意次,等价于{0,}」
  • \d 「匹配数字」
  • ^ 「匹配输入字行首」
  • $ 「匹配输入行尾」
  • {n} 「重复n次」
  • {n,} 「重复n次或更多次」
  • [c] 「匹配单个字符c」
  • [a-z] 「字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符」
  • \ 「转义字符」
  • ( ) 「用于匹配括号之间的内容,通过** 2**调用」
  • pcretest 「终端测试命令」

flag参数

last

停止处理当前rewrite指令,并开始搜索与更改的URI匹配的新的location。服务端只会接收到一次请求。

break

停止处理当前rewrite指令,不会搜索与更改的URI匹配的其它location

redirect

返回一个带有302状态码的临时重定向,地址栏会显示跳转后的地址。服务端会接收到多次请求。

permanent

返回带有301代码的永久重定向,地址栏会显示跳转后的地址。

案例

Nginx高级模块

ngx_http_secure_link_module

用于检查请求链接的真实性,保护资源不受未授权访问,并限制链接的生存期。 参考网址

指令
Syntax: secure_link expression;
Default: —
Context: http, server, location
Syntax: secure_link_md5 expression;
Default: —
Context: http, server, location
验证图示
案例
location /s/ {
    secure_link $arg_md5,$arg_expires;
    secure_link_md5 "$secure_link_expires$uri$remote_addr secret";

    if ($secure_link = "") {
        return 403;
    }

    if ($secure_link = "0") {
        return 410;
    }

    ...
}

ngx_http_geoip_module

基于IP地址,匹配MaxMind GeoIP二进制文件,读取IP所在地域信息 默认没有安装此模块,使用yum install nginx-module-geoip安装 配置nginx.conf文件,在http上下文中添加:

  • load_module modules/ngx_http_geoip_module.so;
  • load_module modules/ngx_stream_geoip_module.so;

需要下载MaxMind GeoIPGeoLiteCountryGeoLiteCity过期了 参考地址

使用场景
  • 区别国内外,做http访问规则
  • 区别国内城市地域,做http访问规则
指令
Syntax: geoip_country file;
Default: —
Context: http

Syntax: geoip_city file;
Default: —
Context: http

ngx_http_ssl_module(https)

参考网址

生成秘钥和CA证书
  1. 生成秘钥

openssl genrsa -des3 -out server.key 2048

  1. 生成证书签名请求文件(csr文件)

openssl req -new -key server.key -out server.csr

  1. 生成证书签名文件(crt文件)「自签」

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

指令
# 开关https,1.15.0版本之后过时,应该使用listen指令的ssl参数
Syntax: ssl on | off;
Default: 
ssl off;
Context: http, server

# CA证书的路径
Syntax: ssl_certificate file;
Default: —
Context: http, server

# 秘钥key文件的路径
Syntax: ssl_certificate_key file;
Default: —
Context: http, server
生成苹果公司要求的openssl证书
  • nginx启动或停止时会要求输入密码,可以使用如下方法去除密码:
  • openssl x509 -req -days 365 -sha256 -nodes -newkey rsa:2048 -keyout server.key -out apple_server.crt
  • -keyout server.key 会生成一个新的没有密码保护的key文件
  • 或者使用这种方式,去除私钥中的密码openssl rsa -in server.pass.key -out server.key
https服务的优化

Nginx与Lua开发

Lua及基础语法

Lua

是一个简洁、轻量、可扩展的脚本语言

基础语法
  1. 安装lua 「yum install lua」
  2. 运行lua 「1.执行lua命令 2.lua文件」
  3. 语法

Nginx与Lua环境

  1. luaJIT
  2. ngx_devel_kit和lua-nginx-module
  3. 重新编译nginx
  4. 参考文章

Nginx调用Lua模块指令

Nginx的可插拔模块化加载执行,共11个处理阶段

  • set_by_lua 设置nginx变量,可以实现复杂的赋值逻辑
  • set_by_lua_file
  • access_by_lua
  • access_by_lua_file 请求访问阶段处理,用于访问控制
  • content_by_lua
  • content_by_lua_file 内容处理器,接收请求处理并输出响应

Nginx Lua Api

  • ngx.var nginx变量
  • ngx.req.get_headers 获取请求头
  • ngx.req.get_uri_args 获取url请求参数
  • ngx.redirect 重定向
  • ngx.print 输出响应内容体
  • ngx.say 同上,但是会最后输出一个换行符
  • ngx.header 输出响应头
  • 更多

用Nginx结合Lua实现代码的灰度发布

连接不存在了

架构篇

Nginx常见问题

相同server_name多个虚拟主机的访问优先级

优先访问先读取到的server_name

location匹配优先级

  1. = 进行普通字符精确匹配,也就是完全匹配
  2. ^~ 表示普通字符匹配,使用前缀匹配
  3. ~ \ ~* 表示执行一个正则匹配

try_files使用

按指定顺序检查文件是否存在,并使用第一个找到的文件进行请求处理;处理是在当前上下文中执行的。文件的路径是根据根和别名指令从文件参数构造的。可以通过在名称后面指定一个斜杠来检查目录是否存在,例如“$uri/”。如果没有找到任何文件,则对最后一个参数中指定的uri进行内部重定向。

Syntax: try_files file ... uri;
try_files file ... =code;
Default: —
Context: server, location

Nginx的alias和root的区别

如果请求的uri是/1/2/3.html alias /a/b/c,将会查找/a/b/c/3.html root /a/b/c,将会查找/a/b/c/1/2/3.html

用什么方法传递用户的真实IP

常见错误码

Nginx性能优化

性能优化考虑点

  1. 当前系统结构瓶颈

观察指标,压力测试

  1. 了解业务模式

接口业务类型,系统层次化结构

  1. 性能与安全

ab接口压力测试工具

  1. 安装

yum install httpd-tools

  1. 使用

ab -n 200 -c 100 http://localhost -n 总的请求数 -c 并发数 -k 是否开启长连接

系统与Nginx的性能优化

  • 网络
  • 系统
  • 服务
  • 程序
  • 数据库、底层服务
文件句柄

linux/unix 一切皆文件,文件句柄就是一个索引

设置方式

系统全局性修改、用户局部性修改、进程局部性修改 系统和用户级修改**/etc/security/limits.conf** 进程级别修改nginx.conf文件在添加worker_rlimit_nofile属性

CPU亲和

参考网址

Syntax: worker_cpu_affinity cpumask ...;
worker_cpu_affinity auto [cpumask];
Default: —
Context: main
For example

worker_processes    4;
worker_cpu_affinity 0001 0010 0100 1000;
# 查看系统的端口端口状态
netstat -luntp | grep 8080
# 查看系统cpu数
cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l
# 查看但cpu核心数
cat /proc/cpuinfo | grep "cpu cores" | uniq
# 查看work进程与cpu绑定关系
ps -eo pid,args,psr | grep [n]ginx

基于Nginx架构的安全

常见的恶意行为

爬虫行为和恶意抓取、资源盗用

  1. 基础防盗链ngx_http_referer_module:目的是不让恶意用户轻易的爬取网站对外数据
  2. secure_link_module:对数据安全性提供加密验证和时效性,适合核心重要数据
  3. access_module:对后台、部分用户服务的数据提供IP防控

常见的应用层攻击手段

后台密码撞库

通过猜测密码字典,不断对后台系统进行尝试性登录,获取后台登录密码

  • 密码复杂度
  • access_module对后台提供IP防控
  • 预警机制
文件上传漏洞

利用这些可以上传的接口,将恶意代码植入到服务器中,再通过url去访问以执行代码

SQL注入

Nginx防攻击策略

Nginx+Lua防火墙

参考网址

基于Nginx的中间件架构

了解需求
  1. 定义nginx在服务体系中的角色
  • 静态资源服务
  • 代理服务
  • 动静分离服务
  1. 静态资源服务的功能设计
  • 类型分类
  • 浏览器缓存
  • 防盗链
  • 流量限制
  • 防资源盗用
  • 压缩
  1. 代理服务
  • 协议类型
  • 正向代理
  • 反向代理
  • 负载均衡
  • 代理缓存
  • 头信息的处理
  • proxypass
  • lnmp
设计评估
  • 硬件:cpu、内存、硬盘
  • 系统:用户权限、日志目录存放
  • 关联服务:LVS、keepalive、syslog、fastcgi
配置注意事项
  • 合理配置
  • 了解原理
  • 关注日志

欢迎关注我的公众号:程序员L札记

更多原创文章,请扫码关注我的微信公众号
更多原创文章,请扫码关注我的微信公众号

分类:

后端

标签:

后端

作者介绍

程序员L札记
V1