nginx学习笔记

nginx学习笔记

安装

mac os:

1
brew install nginx

ubuntu:

1
sudo apt-get install nginx

启动

1
nginx

http://localhost 检测是否访问成功

1
2
3
nginx -s stop // 强制停掉
nginx -s quit // 优雅停掉
nginx -s reload // 重启
1
ps -ef|grep nginx

nginx进程在启动的时候,会附带一个守护进程,用于保护正式进程不被异常终止;如果守护进程一旦发现nginx进程被终止了,会自动重启该进程。

守护进程一般会称为master进程,业务进程被称为worker进程

nginx.conf

mac下的nginx.conf位置: /usr/local/etc/nginx/nginx.conf

可以命令搜索

1
sudo find / -name nginx.conf

嫌麻烦打开,配置别名

1
2
// .zshrc code是vscode命令快捷打开功能
alias ngc="code /usr/local/etc/nginx/nginx.conf"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
... #全局块
events { #events块
...
}

http #http块
{
... #http全局块

server #server块
{
... #server全局块
location [PATTERN] #location块
{
...
}
location [PATTERN]
{
...
}
}

server
{
...
}

... #http全局块
}

默认root路径

1
2
root html => /usr/local/Cellar/nginx/[version]/html
root /var/www => /usr/local/var/www

规则

1
2
3
4
server {
listen 8080;
server_name localhost;
location ...

我们访问http://xxx.com/proxy/index.html

case 1:

1
2
3
location /proxy/ {
proxy_pass http://127.0.0.1/;
}

代理到 http://127.0.0.1/index.html

case 2:

1
2
3
location /proxy/ {
proxy_pass http://127.0.0.1;
}

代理到 http://127.0.0.1/proxy/index.html

case 3:

1
2
3
location /proxy/ {
proxy_pass http://127.0.0.1/api/;
}

代理到 http://127.0.0.1/api/index.html

case 4:

1
2
3
location /proxy/ {
proxy_pass http://127.0.0.1/api;
}

代理到 http://127.0.0.1/apiindex.html

看case 2 和 4是比较难理解的,为什么都是没有后面的/差别为什么这么大,个人理解,如果proxy_pass只是域名则只替换原地址域名,否则全部替换掉。

用到的文件路径

ng配置: nginx.conf => /usr/local/etc/nginx

访问日志: access.log => /usr/local/var/log/nginx

优先级

方式 意义
=PATH 精确匹配路径
^~PATH 使用正则表达式匹配URI的前半段
~PATH 使用正则表达式匹配URI,区分大小写
~*PATH 使用正则表达式匹配URI,不区分大小写
PATH 直接使用PATH匹配,表示在PATH路径下的资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
location = / {                                  # 仅当URI为"/"时,使用A配置
[ configuration A ]
}

location / { # URI为"/"下包含的路径时,使用B配置
[ configuration B ]
}

location /documents/ { # URI为"/documents/"下包含的路径时,使用C配置
[ configuration C ]
}

location ^~ /images/ { # URI靠前部分为"/images/",使用D配置
[ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ { # URI结尾是gif、jpg或jpeg时,使用E配置
[ configuration E ]
}

按上述定义,和优先级规则。比如:

www.test.com/”匹配A配置;
www.test.com/test”、”www.test.com/example”匹配B配置,因为URI都在”/”下;
www.test.com/documents/test.html”匹配C配置,虽然它也符合B配置,但能匹配到的越长优先级越高;
www.test.com/images/test.html”匹配D配置,虽然它也符合B配置,但正则表达式匹配前端字符优先级高;
www.test.com/documents/test.jpg”匹配E配置,虽然它也符合C配置,但正则表达式匹配高于普通字符串。

配置https本地开发环境

在开发qtalk-web版本时遇到这样一个需求

images

实现谷歌推送消息,经过调研发现这个需要在https协议下,api才会生效,当时搜出的方法就是nginx,可是由于时间紧迫并没有时间研究,使用的比较快捷有效的方法,恰巧beta环境有https的支持,那我本地用charles劫持了js代码到本地,利用beta环境变成本地的调试环境。

我是通过这篇博客学习了https本地搭建

https://www.jianshu.com/p/fe0fadb38600

全局搜索配置文件:

1
sudo find / -name nginx.conf

证书及https配置

1
2
3
4
5
6
cd /usr/local/etc/nginx # 进入希望生成证书和私钥的目录,这里我们选择nginx.conf所在目录
openssl genrsa -des3 -out server.key 1024 # 创建服务器私钥,该命令会让你输入一个口令
openssl req -new -key server.key -out server.csr # 创建签名请求的证书(CSR)
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key # 在加载SSL支持的Nginx并使用上述私钥时除去必须的口令
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt # 最后标记证书使用上述私钥和CSR

配置 nginx.config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# HTTPS server
#
server {
listen 443 ssl;
server_name localhost;

# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
ssl_certificate server.crt;
ssl_certificate_key server.key;

# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;

# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;

location / {
root /www/;
index index.html index.htm;
}
}

那我这里想在我的项目里用到https协议,这样还不能满足,我需要更改下location

1
2
3
location / {
proxy_pass http://my.corp.qunar.com:3002;
}

还是会报一个错误

1
GET https://my.corp.qunar.com/index.js net::ERR_CONTENT_LENGTH_MISMATCH 200 (OK)

google后发现是因为nginx会从缓存中拿文件,是这个目录proxy_temp,而没有权限,所以网上一些方法是

1
chown -R _www:admin proxy_temp

不过更改文件夹权限我是莫名地抵触的,我选择了一个我认为还不错的方法

1
2
3
4
location / {
proxy_pass http://my.corp.qunar.com:3002;
proxy_buffering off;
}

就是把缓存禁掉

总结

ng访问地址404 自己会根据优先级逐级查找,如果都404,则按照原地址访问。这样就有可能导致形成内循环,相互跳转,产生错误。