学习Nginx入门到实践-Nginx中间件笔记
nginx官网
Nginx是一个开源且高性能、可靠的HTTP中间件、代理服务。
IO多路复用epoll
轻量级
CPU亲和
sendfile
参数 | 注释 |
---|---|
user | 设置nginx服务的系统使用用户 |
worker_processes | 工作进程数 |
error_log | nginx的错误日志 |
pid | nginx服务启动时候的pid |
参数 | 注释 | |
---|---|---|
events | worker_connections | 每个进程允许最大连接数 |
use | 使用内核模型 |
error.log 错误日志
access.log 每次请求
Syntax: | log_format name [escape=default|json|none] string …; |
---|---|
Default: | log_format combined “…”; |
Context: | http |
log_format 关键字
name 自定义变量
[escape=default|json|none] string … 日志具体内容,即HTTP请求变量、nginx内置变量、自定义变量组成
log_format combined “…” 日志默认值
日志内容:
HTTP请求变量 - arg_PARAMETER http_HEADER sent_http_HEADER
内置变量 - Nginx内置的http-只能配置在http作用域下配置
自定义变量 - 自定义的
nginx官方模块
第三方模块
作用:Nginx的客户端状态,连接信息
Syntax: | stub_status; |
---|---|
Default: | — |
Context: | server,location |
示例
在配置文件中添加
server {
...
location /mystatus{
stub_status;
}
...
}
作用:目录中选择一个随机主页
Syntax: | random_index on|off; |
---|---|
Default: | random_index off; |
Context: | location |
示例
在配置文件中添加
server {
...
location / {
root /opt/app/code;
random_index on;
#index index.html index.htm;
}
...
}
.开始的隐藏文件不会选择
作用:HTTP内容替换
Syntax: | sub_filter string replacement; |
---|---|
Default: | — |
Context: | http,server,location |
Syntax: | sub_filter_last_modified on|off; |
---|---|
Default: | sub_filter_last_modified off; |
Context: | http,server,location |
Syntax: | sub_filter_once on|off; |
---|---|
Default: | sub_filter_once on; |
Context: | http,server,location |
示例
在配置文件中添加
server {
...
location / {
root /opt/app/code;
index index.html index.htm;
sub_filter 'aaa' 'AAA';
sub_filter_once off;
}
...
}
limit_conn_module
Syntax: | limit_conn_zone key zone=name:size; |
---|---|
Default: | — |
Context: | http |
key 表示存储在共享内存中的key
zone=name:size 表示共享内存名称和大小
Syntax: | limit_conn zone number; |
---|---|
Default: | — |
Context: | http,server,location |
zone 表示存储在共享内存中的key
number 表示限制的连接数
示例
在配置文件中添加
limit_conn_zone $binary_remote_addr zone=conn_zone:1m;
server {
...
location / {
root /opt/app/code;
# 服务端同一时刻只允许一个IP连接过来
limit_conn conn_zone 1;
index index.html index.htm;
}
...
}
limit_req_module
Syntax: | limit_req_zone key zone=name:size rate=rate; |
---|---|
Default: | — |
Context: | http |
key 表示存储在共享内存中的key
zone=name:size 表示共享内存名称和大小
rate=rate 表示请求数率,例如:10r/s每秒请求10次
Syntax: | limit_req zone=name [burst=number] [nodelay]; |
---|---|
Default: | — |
Context: | http,server,location |
zone 表示存储在共享内存中的key
[burst=number] 表示突发请求数(最大请求数),遗留的请求放到下一秒执行(延迟响应)
[nodelay | delay=number] 其中nodelay表示请求没有延迟,超出的请求丢失;delay=number表示可以延迟处理请求的数量
示例
在配置文件中添加
# 通过$binary_remote_addr(ip)限制,每秒1个
limit_req_zone $binary_remote_addr zone=req_zone:1m rate=1r/s;
server {
...
location / {
root /opt/app/code;
#limit_req zone=req_zone burst=3 nodelay;
#limit_req zone=req_zone burst=3;
#limit_req zone=req_zone;
index index.html index.htm;
}
...
}
http_access_module
Syntax: | allow address|CIDR|unix:|all; |
---|---|
Default: | — |
Context: | http,server,location,limit_except |
address:IP地址
CIDR:网段
unix:unix或linux上socket方式的访问
all:允许所有
Syntax: | deny address|CIDR|unix:|all; |
---|---|
Default: | — |
Context: | http,server,location,limit_except |
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 |
参考官方文档
Syntax: | sendfile on |off; |
---|---|
Default: | sendfile off; |
Context: | http,server,location,if in location |
引读:–with-file-aio 异步文件读取 (很少用)
配置语法-tcp_nopush (多个文件打包一起发送)
作用:sendfile开启的情况下,提高网络包的传输效率
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 |
配置语法-压缩
作用:压缩传输
Syntax: | gzip on | off; |
---|---|
Default: | gzip off; |
Context: | http,server,location,if in location |
Syntax: | gzip_comp_level level; |
---|---|
Default: | gzip_comp_level 1; |
Context: | http,server,location |
Syntax: | gzip_http_version 1.0|1.1; |
---|---|
Default: | gzip_http_version 1.1; |
Context: | http,server,location |
扩展nginx压缩模块
http_gzip_static_module 预读gzip功能,需要事先压缩好
http_gunzip_module 应用支持gunzip的压缩方式(不支持gzip压缩时使用,较少)
示例
在配置文件中添加
server {
...
# 开启文件读取
sendfile on;
location ~ .*\.(jpg|gif|png)$ {
gzip on;
gzip_http_version 1.1;
gzip_comp_level 2;
# gzip压缩类型
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
root /opt/app/code/images;
}
location ~ .*\.(txt|xml)$ {
gzip on;
gzip_http_version 1.1;
gzip_comp_level 1;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
root /opt/app/code/doc;
}
location ~ ^/download {
# 预读功能
gzip_static on;
tcp_nopush on;
root /opt/app/code;
}
...
}
HTTP协议定义的缓存机制(如:Expires;Cache-control等)
校验是否过期 | Expires、Cache-Control(max-age) | 协议版本不同 |
---|---|---|
协议中Etag头信息校验 | Etag | 一串字符串 |
Last-Modified头信息校验 | Last-Modified | 具体的时间到秒 |
配置语法 - expires
作用:添加Cache-Control、Expires头
Syntax: | expires [modified] time; expires epoch | max | off; |
---|---|
Default: | expires off; |
Context: | http,server,location,if in location |
示例
在配置文件中添加
server {
...
location ~ .*\.(htm|html)$ {
expires 24h;
root /opt/app/code
}
....
}
为什么浏览器禁止跨域访问?(不安全,容易出现CSRF攻击)
Syntax: | add_header name value [always]; |
---|---|
Default: | — |
Context: | http,server,location,if in location |
读取这个Access-Control-Allow-Origin头信息,查看是否允许跨站;默认阻止
示例
在配置文件中添加
server {
...
location ~ .*\.(htm|html)$ {
# 允许的域名 *代表所有 可以只打开指定的域名
add_header Access-Control-Allow-Origin *;
# 允许的方法
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
root /opt/app/code;
}
....
}
目的:防止资源被盗用
设置思路
首要方式:区别哪些请求是非正常的用户请求
基于http_refer防盗链配置模块
Syntax: | valid_referers none|blocked|server_names|string…; |
---|---|
Default: | — |
Context: | server,location |
示例
在配置文件中添加
server {
...
location /app{
...
# none代表没有refer信息的 blocked代表refer信息不是http://这种标准形式的
# 支持域名正则匹配的方式
valid_referers none blocked 192.168.247.130 ~/google\./;
if($invalid_referer){
return 403;
}
....
}
....
}
http_refer的方式有一定的局限性
正向代理:代理的对象是客户端
反向代理:代理的对象是服务端
http的方式:http://localhost:8000/uri/
https的方式:https://192.168.1.1:8000/uri/
socket的方式:http://unix:/tmp/backend.socket:/uri/;
Syntax: | proxy_pass URL; |
---|---|
Default: | — |
Context: | location,if in location,limit_except |
示例
在配置文件中添加
server {
...
# 代理到8080端口
location ~ /test_proxy.html$ {
proxy_pass http://127.0.0.1:8080;
}
....
}
Syntax: | proxy_buffering on|off; |
---|---|
Default: | proxy_buffering on; |
Context: | http,server,location |
扩展 proxy_buffer_size 、proxy_buffers 、proxy_busy_buffers_size
Syntax: | proxy_redirect default; proxy_redirect off; proxy_redirect redirect replacement; |
---|---|
Default: | proxy_redirect default; |
Context: | http,server,location |
Syntax: | proxy_set_header field value; |
---|---|
Default: | proxy_set_header Host $proxy_host; proxy_set_header Connection close; |
Context: | http,server,location |
扩展:proxy_hide_header 、proxy_set_body
Syntax: | proxy_connect_timeout time; |
---|---|
Default: | proxy_connect_timeout 60s; |
Context: | http,server,location |
扩展:proxy_read_timeout 、proxy_send_timeout
示例
在配置文件中添加
server {
...
# 代理到8080端口
location ~ /test_proxy.html$ {
proxy_pass http://127.0.0.1:8080;
proxy_redirect default;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffer_size 32k;
proxy_buffering on;
proxy_buffers 4 128k;
proxy_busy_buffers_size 256k;
proxy_max_temp_file_size 256k;
}
....
}
nginx属于七层负载均衡
nginx通过代理,将请求代理到upstream server,upstream server里面存放了一些相似的服务
Syntax: | upstream name {…} |
---|---|
Default: | — |
Context: | http |
示例
在配置文件中添加
http {
...
# 负载均衡 默认轮询 ip/域名/socket方式
upstream test {
server 192.168.247.130:8001;
server 192.168.247.130:8002;
server 192.168.247.130:8003;
}
...
server {
...
location / {
proxy_pass http://test;
#500/502/503/504/invalid_header/timeout/error 这些情况时用下一个代理
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
...
}
...
}
...
}
down | 当前的server暂时不参与负载均衡 |
---|---|
backup | 预留的备份服务器 |
max_fails | 允许请求失败的次数 |
fail_timeout | 经过max_fails失败后,服务暂停的时间 |
max_conns | 限制最大的接收的连接数 |
示例
在配置文件中添加
http {
...
upstream test {
server 192.168.247.130:8001 down;
server 192.168.247.130:8002 backup;
server 192.168.247.130:8003 max_fails=1 fail_timeout=10s;
}
...
server {
...
location / {
proxy_pass http://test;
...
}
...
}
...
}
轮询 | 按时间顺序逐一分配到不同的后端服务器 |
---|---|
加权轮询 | weight值越大,分配到的访问几率越高 |
ip_hash | 每个请求按访问IP的hash结果分配,这样来自同一个IP的固定访问一个后端服务器 |
url_hash | 按照访问的URL的hash结果来分配请求,是每个URL定向到同一个后端服务器 |
least_conn | 最少连接数,哪个机器连接数少就分发 |
hash关键数值 | hash自定义的key |
在配置文件中添加
http {
...
upstream test {
server 192.168.247.130:8001;
server 192.168.247.130:8002 weight=5;
server 192.168.247.130:8003;
}
...
server {
...
location / {
proxy_pass http://test;
...
}
...
}
...
}
在配置文件中添加
http {
...
upstream test {
ip_hash;
server 192.168.247.130:8001;
server 192.168.247.130:8002;
server 192.168.247.130:8003;
}
...
server {
...
location / {
proxy_pass http://test;
...
}
...
}
...
}
Syntax: | hash key [consistent] |
---|---|
Default: | — |
Context: | upstream |
示例
在配置文件中添加
http {
...
upstream test {
hash $request_uri;
server 192.168.247.130:8001;
server 192.168.247.130:8002;
server 192.168.247.130:8003;
}
...
server {
...
location / {
proxy_pass http://test;
...
}
...
}
...
}
Syntax: | proxy_cache_path path [levels=levels] [user_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 |
Syntax: | proxy_cache zone|off |
---|---|
Default: | proxy_cache off; |
Context: | http,server,location |
Syntax: | proxy_cache_valid [code …] time; |
---|---|
Default: | — |
Context: | http,server,location |
Syntax: | proxy_cache_key string; |
---|---|
Default: | proxy_cache_key $scheme$proxy_host$request_uri; |
Context: | http,server,location |
示例
在配置文件中添加
http{
#配置3台服务
upstream test {
server 192.168.247.130:8001;
server 192.168.247.130:8002;
server 192.168.247.130:8003;
}
#配置proxy_cache_path 存放缓存临时文件的目录 缓存的目录分级(2层) keys_zone开辟的空间 max_size最大大小(超过启动淘汰规则) 不活跃时间60分钟
proxy_cache_path /opt/app/cache levels=1:2 keys_zone=test_cache:10m max_size=10g inactive=60m use_temp_path=off;
server {
...
location / {
proxy_cache test_cache;
proxy_pass http://test;
# 200或304的code 在12小时过期
proxy_cache_valid 200 304 12h;
# 其他code 在10分钟过期
proxy_cache_valid any 10m;
# 缓存的key定义
proxy_cache_key $host$uri$is_args$args;
#add_header Nginx-Cache "$upstream_cache_status";
#500/502/503/504/invalid_header/timeout/error 这些情况时用下一个服务
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
...
}
...
}
}
Syntax: | proxy_no_cache string …; |
---|---|
Default: | — |
Context: | http,server,location |
示例
在配置文件中添加
http{
...
server {
...
if($request_uri ~ ^/(url3|login|register|password\/reset)){
set $cookie_nocache 1;
}
location / {
proxy_cache test_cache;
proxy_pass http://test;
# 200或304的code 在12小时过期
proxy_cache_valid 200 304 12h;
# 其他code 在10分钟过期
proxy_cache_valid any 10m;
# 缓存的key定义
proxy_cache_key $host$uri$is_args$args;
proxy_no_cache $cookie_nocache $arg_nocache $arg_comment;
proxy_no_cache $http_pragma $http_authorization;
#add_header Nginx-Cache "$upstream_cache_status";
#500/502/503/504/invalid_header/timeout/error 这些情况时用下一个服务
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
...
}
...
}
}
大文件分片请求
Syntax: | slice size; |
---|---|
Default: | slice 0; |
Context: | http,server,location |
优势:每个子请求收到的数据会形成一个独立文件,一个请求断了,其他请求不受影响。
缺点:当文件很大或者slice很小的时候,可能会导致文件描述符耗尽等情况。
通过中间件将动态请求和静态请求分离。
upstream java_api {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name localhost;
root /opt/app/code;
# 动态请求 请求tomcat页面 代理方式
location ~ \.jsp$ {
proxy_pass http://java_api;
proxy_set_header Host $host;
}
# 静态请求
location ~ \.(jpg|png|gif)$ {
expires 1h;
gzip on;
}
...
}
作用:实现url重写以及重定向
场景
配置语法
Syntax: | rewrite regex replacement[flag]; |
---|---|
Default: | — |
Context: | server,location,if |
last | 停止rewrite检测 |
---|---|
break | 停止rewrite检测 |
redirect | 返回302临时重定向,地址栏会显示跳转后的地址 |
permanent | 返回301永久重定向,地址栏会显示跳转后的地址 |
示例
在配置文件中添加
server{
...
root /opt/app/code;
# break会去/opt/app/code/test/下面寻找
location ~ ^/break {
rewrite ^/break /test/ break;
}
# last重新建了一个请求到test
location ~ ^/last {
rewrite ^/last /test/ last;
}
location /test/ {
default_type application/json;
return 200 '{"status":"success"}';
}
...
}
server {
listen 80;
server_name localhost;
root /opt/app/code;
location / {
# 场景一 重写请求路径
rewrite ^/course-(\d+)-(\d+)-(\d+)\.html$ /course/$1/$2/course_$3.html break;
# 场景二 Chrome浏览器访问的指定地址重定向百度
if ($http_user_agent ~* Chrome) {
rewrite ^/nginx http://www.baidu.com redirect;
}
# 场景三 请求的资源不存在就重定向百度
if (!-f $request_filename) {
rewrite ^/(.*)$ http://www.baidu.com/$1 redirect;
}
index index.html index.htm;
}
...
}
Rewrite规则优先级
执行server块的rewrite指令
执行location匹配
执行选定的location中的rewrite
Syntax: | secure_link expression; |
---|---|
Default: | — |
Context: | http,server,location |
Syntax: | secure_link_md5 expression; |
---|---|
Default: | — |
Context: | http,server,location |
示例
在配置文件中添加
server {
listen 80;
server_name localhost;
root /opt/app/code;
location / {
# 两个参数md5和expires
secure_link $arg_md5,$arg_expires;
# secure_link_md5加密方式 test自定义加密串
secure_link_md5 "$secure_link_expires$uri test";
if ($secure_link = "") {
return 403;
}
if ($secure_link = "0") {
return 410;
}
}
...
}
基于IP地址匹配MaxMind GeoIP二进制文件,读取IP所在地域信息。
安装模块 yum install nginx-module-geoip
使用场景
查看module安装
$ cd /etc/nginx/modules/
$ ls
示例
在nginx.conf中引入模块
load_module "modules/ngx_http_geoip_module.so";
load_module "modules/ngx_stream_geoip_module.so";
下载文件
# 现在要登陆后下载
$ wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
$ wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
修改配置文件
# 引入文件
geoip_country /etc/nginx/geoip/GeoIP.dat;
geoip_city /etc/nginx/geoip/GeoLiteCity.dat;
server {
listen 80;
server_name localhost;
location / {
if ($geoip_country_code != CN) {
return 403;
}
root /usr/share/nginx/html;
index index.html index.htm;
}
location /myip {
default_type text/plain;
return 200 "$remote_addr $geoip_country_name $geoip_country_code $geoip_city";
}
...
}
# 1. 生成key密钥 设置一个密码
$ openssl genrsa -idea -out test.key 1024
# 2. 生成证书签名请求文件(csr文件)使用设置的密码
$ openssl req -new -key test.key -out test.csr
# 3. 生成证书签名文件(CA文件) 使用设置的密码
# 注意一定要加-days,否则默认一个月左右过期
$ openssl x509 -req -days 3650 -in test.csr -signkey test.key -out test.crt
# 查看当前加密证书算法类型
$ openssl x509 -noout -text -in ./test.crt
# 去除key密钥文件的保护密码
$ openssl rsa -in ./test.key -out ./test_nopass.key
ssl的开启与关闭
Syntax: | ssl on|off; |
---|---|
Default: | ssl off; |
Context: | http,server; |
ssl证书文件
Syntax: | ssl_certificate file; |
---|---|
Default: | — |
Context: | http,server |
ssl密码文件
Syntax: | ssl_certificate_key file; |
---|---|
Default: | — |
Context: | http,server |
示例
在配置文件中添加
server
{
listen 443;
server_name 192.168.247.130;
ssl on;
ssl_certificate /etc/nginx/ssl_key/test.crt;
ssl_certificate_key /etc/nginx/ssl_key/test.key;
index index.html index.htm;
location / {
root /opt/app/code;
}
}
- 服务器所有的连接使用TSL1.2以上版本(openssl 1.0.2)
- HTTPS证书必须使用SHA256以上哈希算法签名
- HTTPS证书必须使用RSA 2048位或ECC 256位以上公钥算法
- 使用前向加密技术
# 直接通过key密钥文件生成CA证书文件,不生成中间csr文件
$ openssl req -days 3650 -x509 -sha256 -nodes -newkey rsa:2048 -keyout test.key -out test_apple.crt
server
{
listen 443;
server_name 192.168.247.130;
ssl on;
ssl_certificate /etc/nginx/ssl_key/test_apple.crt;
ssl_certificate_key /etc/nginx/ssl_key/test.key;
index index.html index.htm;
location / {
root /opt/app/code;
}
}
server
{
listen 443;
server_name 192.168.247.130;
# 激活长连接
keepalive_timeout 100;
ssl on;
# 设置ssl session缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_certificate /etc/nginx/ssl_key/test.crt;
ssl_certificate_key /etc/nginx/ssl_key/test.key;
index index.html index.htm;
location / {
root /opt/app/code;
}
}
Lua是一个简洁、轻量、可扩展的脚本语言。
优势:充分得结合Nginx的并发处理epoll优势和Lua的轻量,实现简单的功能和高并发的场景。
安装Lua yum install lua
-- 行注释
--[[
块注释
--]]
-- while循环
sum=0
num=1
while num <= 100 do
sum = sum + num
num = num + 1
end
print("sum = ",sum)
-- for循环
sum = 0
for i = 1,100 do
sum = sum + i
end
-- if-else判断语句
if age == 40 and sex == "Male" then
print("大于40男人")
elseif age > 60 and sex ~= "Female" then
print("非女人而且大于60")
else
local age = io.read()
print("Your age is "..age)
end
--[[
布尔类型只有nil和false是false,其他都是true
lua没有++或是+=这样的操作
变量默认都是全局变量,local修饰表示局部变量
"~=" 是不等于
字符串的拼接操作符 ".."
io库的分别从stdin和stdout读写的read和write函数
--]]
下载相关文件
# 下载nginx 1.18.0
$ wget http://nginx.org/download/nginx-1.18.0.tar.gz
# 下载LuaJIT 2.1
$ wget https://luajit.org/download/LuaJIT-2.1.0-beta3.tar.gz
# 下载ngx_devel_kit模块
$ wget https://github.com/vision5/ngx_devel_kit/archive/refs/tags/v0.3.1.tar.gz
# 下载lua-nginx-module模块
$ wget https://github.com/openresty/lua-nginx-module/archive/refs/tags/v0.10.13.tar.gz
安装LuaJIT
# 解压缩
$ tar -zxvf LuaJIT-2.1.0-beta3.tar.gz
# 进入相关目录
$ cd LuaJIT-2.1.0-beta3/
# 编译安装
$ make install PREFIX=/usr/local/LuaJIT
# 添加环境变量
$ echo 'export LUAJIT_LIB=/usr/local/LuaJIT/lib' >> /etc/profile
$ echo 'export LUAJIT_INC=/usr/local/LuaJIT/include/luajit-2.1' >> /etc/profile
# 加载lua库,加入到ld.so.conf文件
$ echo '/usr/local/lib' >> /etc/ld.so.conf
$ echo '/usr/local/LuaJIT/lib' >> /etc/ld.so.conf
# 重新加载环境变量
$ source /etc/profile
$ ldconfig
解压ngx_devel_kitj和lua-nginx-module
$ tar -zxvf v0.3.1.tar.gz
$ tar -zxvf v0.10.13.tar.gz
安装配置nginx1.18
# 安装必要依赖
$ yum install -y gcc pcre-devel openssl-devel zlib-devel
# 解压缩
$ tar -zxvf nginx-1.18.0.tar.gz
# 进入相关目录
$ cd nginx-1.18.0
# 编译安装nginx
$./configure --prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib64/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
--user=nginx \
--group=nginx \
--with-compat \
--with-file-aio \
--with-threads \
--with-http_addition_module \
--with-http_auth_request_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_mp4_module \
--with-http_random_index_module \
--with-http_realip_module \
--with-http_secure_link_module \
--with-http_slice_module \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_sub_module \
--with-http_v2_module \
--with-mail \
--with-mail_ssl_module \
--with-stream \
--with-stream_realip_module \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' \
--with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' \
--add-module=/home/anglesang/work/app/ngx_devel_kit-0.3.1 \
--add-module=/home/anglesang/work/app/lua-nginx-module-0.10.13
# 同目录下,编译安装
$ make -j 4 && make install
# 验证 查看最后几行
$ nginx -V
lua-nginx-module-0.10.19
模板使用了新版导致,使用 lua-nginx-module-0.10.13
解决
adding module in /home/anglesang/work/app/lua-nginx-module-0.10.19
checking for LuaJIT 2.x ... not found
./configure: error: unsupported LuaJIT version; ngx_http_lua_module requires LuaJIT 2.x.
安装lua开发包解决 yum install -y lua-devel
checking for Lua library ... not found
checking for Lua library in /usr/local/ ... not found
checking for Lua library in /usr/local/ ... not found
checking for Lua library in /usr/pkg/ ... not found
checking for Lua library in /opt/local/ ... not found
checking for Lua library in /usr/local/*/lua51/ ... not found
checking for Lua library in /usr/ ... not found
checking for LuaJIT library in /usr/local/ ... not found
checking for LuaJIT library in /usr/ ... not found
checking for LuaJIT library in /usr/ ... not found
./configure: error: ngx_http_lua_module requires the Lua library.
Nginx的可插拔模块化加载执行,共11个处理阶段
set_by_lua set_by_lua_file |
设置nginx变量,可以实现复杂的赋值逻辑 |
---|---|
access_by_lua access_by_lua_file |
请求访问阶段处理,用于访问控制 |
content_by_lua content_by_lua_file |
内容处理器,接受请求处理并输出响应 |
… | … |
ngx.var | nginx变量 |
---|---|
ngx.req.get_headers | 获取请求头 |
ngx.req.get_uri_args | 获取url请求参数 |
ngx.redirect | 重定向 |
ngx.print | 输出响应内容体 |
ngx.say | 同ngx.print,但是会最后输出一个换行符 |
ngx.header | 输出响应头 |
… | … |
按照一定的关系区别,分部分的代码进行上线,使代码的发布能平滑过渡上线。
memcached 配置
# 安装memcached
$ sudo yum install -y memcached
# 启动memcached
$ memcached -p 11211 -u nobody -d -m 128
# 连接memcached
$ telnet 127.0.0.1 11211
# 设置值
$ set 192.168.247.133 0 0 1
> 1
# 获取值 验证
$ get 192.168.247.133
启动并配置两个tomcat 8080和9090
复制tomcat8080为tomcat9090,将tomcat9090中的server.xml文件中的所有8改为9
修改nginx配置
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/log/host.access.log main;
location /hello {
default_type 'text/plain';
content_by_lua 'ngx.say("hello, lua")';
}
location /myip {
default_type 'text/plain';
content_by_lua '
clientIP = ngx.req.get_headers()["Host"]
ngx.say("IP:",clientIP)
';
}
location / {
default_type "text/html";
content_by_lua_file /opt/app/lua/dep.lua;
}
location @server{
proxy_pass http://127.0.0.1:9090;
}
location @server_test{
proxy_pass http://127.0.0.1:8080;
}
error_page 500 502 503 504 404 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
测试lua
访问http://192.168.247.130/hello
地址
添加lua文件
clientIP = ngx.req.get_headers()["X-Real-IP"]
if clientIP == nil then
clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
clientIP = ngx.var.remote_addr
end
local memcached = require "resty.memcached"
local memc, err = memcached:new()
if not memc then
ngx.say("failed to instantiate memc: ", err)
return
end
local ok, err = memc:connect("127.0.0.1", 11211)
if not ok then
ngx.say("failed to connect: ", err)
return
end
local res, flags, err = memc:get(clientIP)
if err then
ngx.say("failed to get clientIP ", err)
return
end
if res == "1" then
ngx.exec("@server_test")
return
end
ngx.exec("@server")
添加lua调用memcached的模块
# 下载lua中memcached的模块
$ wget https://github.com/openresty/lua-resty-memcached/archive/refs/tags/v0.15.tar.gz
# 解压
$ tar -zxvf v0.15.tar.gz
# 移动
$ cp -r lua-resty-memcached-0.15/lib/resty /usr/lib64/lua/5.1
# 重新加载环境变量
$ ldconfig
相同server_name多个虚拟主机优先级访问
server{
listen 80;
server_name testserver1 aaa.aaa.com;
location / {
...
}
}
server{
listen 80;
server_name testserver2 aaa.aaa.com;
location / {
...
}
}
优先级根据配置加载顺序
location匹配优先级
匹配方式 | 含义 |
---|---|
= | 全等匹配 |
普通匹配 | |
^~ | 普通匹配,使用前缀匹配 |
~ | 正则匹配,区分大小写 |
~* | 正则匹配,不区分大小写 |
try_files使用
按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如果所有的文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。
location / {
try_files $uri $uri/ /index.php;
}
Nginx的alias和root区别
root
location /test/img/ {
root /home/anglesang/img/;
}
请求 http://www.test.com/test/img/cat.png
实际访问资源 /home/anglesang/img/test/img/cat.png
root地址+uri
alias
location /test/img/ {
alias /home/anglesang/img/;
}
请求 http://www.test.com/test/img/cat.png
实际访问资源 /home/anglesang/img/cat.png
用什么方法传递用户的真实IP
set x_real_ip = $remote_addr
nginx中常见错误码
413 Request Entity Too Large
用户上传文件限制 client_max_body_size
503 bad gateway
后端服务无响应
504 Gateway Time-out
后端服务执行超时
…
几个关于压力测试的概念
吞吐率(Requests per second)
概念:服务器并发处理能力的量化描述,单位是reqs/s,指的是某个并发用户数下单位时间内处理的请求数。某个并发用户数下单位时间内能处理的最大请求数,称之为最大吞吐率。
计算公式:总请求数 / 处理完成这些请求数所花费的时间,即
Request per second = Complete requests / Time taken for tests
并发连接数(The number of concurrent connections)
概念:某个时刻服务器所接受的请求数目,简单的讲,就是一个会话。
并发用户数(The number of concurrent users,Concurrency Level)
概念:要注意区分这个概念和并发连接数之间的区别,一个用户可能同时会产生多个会话,也即连接数。
用户平均请求等待时间(Time per request)
计算公式:处理完成所有请求数所花费的时间/ (总请求数 / 并发用户数),即
Time per request = Time taken for tests /( Complete requests / Concurrency Level)
服务器平均请求等待时间(Time per request: across all concurrent requests)
计算公式:处理完成所有请求数所花费的时间 / 总请求数,即
Time taken for / testsComplete requests
可以看到,它是吞吐率的倒数。
同时,它也=用户平均请求等待时间/并发用户数,即
Time per request / Concurrency Level
安装
yum install -y httpd-tools
ab -n 2000 -c 2 http://127.0.0.1/
-n 总的请求数
-c 并发数
-k 是否开启长连接
文件句柄设置
linux\Unix 一切皆文件,文件句柄就是一个索引
设置方式
系统全局性修改
用户局部性修改
进程局部性修改
CPU亲和配置
# 物理CPU个数
$ cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l
# 每个物理CPU中core的个数
$ cat /proc/cpuinfo | grep "cpu cores" | uniq
# 逻辑CPU的个数
$ cat /proc/cpuinfo | grep "processor" | wc -l
nginx通用配置优化
# 每个work连接数
work_connections 1024;
# 字符集统一
charset utf-8;
# 日志格式
log_format ....
# 日志情况设置
access_log off;
# sendfile设置
sendfile on;
# 静态资源推荐
tcp_nopush on;
# 动态资源推荐
tcp_nodeny on;
keepalive_timeout 65;
# gzip压缩可配置
常见恶意行为
爬虫行为和恶意抓取、资源盗用
基础防盗链功能 - 目的不让恶意用户能轻易的爬取网站对外数据
secure_link_module - 对数据安全性提高加密验证和失效性,适合如核心重要重要数据
access_module - 对后台、部分用户服务的数据提供IP防控
常见的攻击手段
后台密码撞库 - 通过猜测密码字典不断对后台系统登录性尝试,获取后台登录密码
方法一、后台登录密码复杂度
方法二、access_module - 对后台提供IP防控
方法三、预警机制
文件上传漏洞 - 利用这些可以上传的接口将恶意代码植入到服务器中,再通过url去访问以执行代码
对上传文件判断
location ^~ /upload {
root /opt/app/images;
if($request_filename ~* (.*)\.php){
return 403;
}
}
SQL注入 - 利用未过滤/未审核用户输入的攻击方法,让应用运行本不应该运行的SQL代码
…
# 检查配置文件语法
$ nginx -t -c /etc/nginx/nginx.conf
# centos系,查看nginx文件
$ rpm -ql nginx
$ systemctl start nginx
$ systemctl restart nginx
$ systemctl stop nginx
$ systemctl reload nginx
$ systemctl status nginx