Nginx前端实践小结
Nginx是一款轻量级的HTTP服务器,采用事件驱动的异步非阻塞处理方式框架,这让其具有极好的IO性能,时常用于服务端的反向代理和负载均衡
相信很多小伙伴看到过上面这段话,Http服务器,反向代理,负载均衡,这些貌似听起来有点高端的词构成了我们对Nginx的第一印象,有些小伙伴安装好nginx打开配置文件,看到一堆不知所云的代码往往心生怯意,对nginx有种害怕的心理,其实nginx虽然很强大配置多样,甚至市面上很多厚厚的书都在专门介绍怎么用好nginx,实际上我们前端小伙伴在工作当中,并不需要理解太深入或者太全面我们也可以让nginx成为我们日常开发的得力助手,用多了之后你会发现,平时要找各种包利用node实现的很多功能,在nginx这简直是小菜一碟.
本文不会是介绍式的切入nginx,而是从笔者作为一名最普通的前端开发者,开发过程中遇到的,对nginx相关功能有所实践的东西,掌握了本文,可以让你快速上手nginx,且可以有更多信心及思路去尝试其他功能。下面就一起动手吧。
模块分解
别看nginx貌似很复杂的样子,但实际上nginx的设计是严格遵循模块块思想的,各个模块各司其职,高聚低耦
总共分为三部分:
1、全局配置块
主要是配置一些影响nginx整体运行的指令,如worer_processes:1; worer_processes越 大,可以支持的并发数越多
2、event块
主要配置设计nginx服务器与用户网络的连接, 如worker_connections 1024; 支持最大连接数
3、http块
配置最频繁核心的模块,我们平时所说的反向代理,负载均衡,动静分离这些都是在http模块下进行配置
本文重点讲解http块,这也是大部分前端工作中所需要打交道的模块
常用命令
常用命令必然是少不了的了,笔者一开始就用笔记本把一些常用的的命令记下,用的时候如果不记得就去翻下,用多几遍就会熟稔于心:
以下命令需进入nginx目录下
启动nginx:
window下:start nginx 或 nginx 都是可以的
linux或mac: service nginx start
检查nginx配置文件是否有语法错误:
nginx -t
关闭nginx
nginx -s stop
重启nginx:
nginx -s reload
其他更多配置可自行查阅,一般我们的操作是打开电脑,启动nginx, 修改nginx配置, 然后执行命令nginx -t检查nginx配置是否有问题,检查这步建议不要跳过,因为有时候你发现nginx没启起来,就是nginx配错了。检查没问题后便可以重启nginx
http模块分析
先上个http配置例子:
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
#51la统计配置
upstream la {
server 127.0.0.1:7001;
keepalive 2000;
}
server {
listen 80;
server_name egg.51.la;
location / {
proxy_pass http://la/;
proxy_set_header Host $host:$server_port;
}
}
}
像include,keepalive_timeout这些称为http全局参数, 影响http全局配置,如keepalive_timeout为客户端连接超时时间,include 为导入文件集; 相关参数较多,具体功能可以自行查阅,重点在upstream块与server块
upstream 说白了就是做负载均衡,它可以帮助我们定义一组相同服务的别名,如la,当请求到来的时候可以通过相关策略帮我们选一组服务提供响应。目前只能被 proxy_pass,fastcgi_pass,uwsgi_pass,scgi_pass,memcached_pass,grpc_pass 使用。使用最多的是 proxy_pass,
而server便是虚拟服务器,这里处理请求
如上面的例子,我有个项目启动在端口7001,本地访问可通过127.0.0.1:7001访问, 但如果我想通过egg.51.la就想访问到这个服务呢?
首先想通过egg.51.la访问,这需要在hosts文件里配置映射
127.0.0.1 egg.51.la
访问egg.51.la意味着访问的是80端口,但实际上要访问7001端口时upstream就发挥作用了,我配置了一个名字为la的负载均衡配置:
upstream la {
server 127.0.0.1:7001;
keepalive 2000;
}
server {
listen 80;
server_name egg.51.la;
location / {
proxy_pass http://la/;
proxy_set_header Host $host:$server_port;
}
}
常用变量
$args:全部 URL 参数;
$query_string:与 args 变量完全相同;
$arg_参数名:URL 中某个具体参数的值;
$is_args:如果请求的 URL 中有参数则返回?,否则返回空字符串;
$content_length:HTTP 请求中标识包体长度的 Content-Length 头部的值,头部没有这个则为空;
$content_type:标识请求包体类型的 Content-Type 头部的值;
$uri:请求的 URI(不包含参数);
$document_uri:与uri变量完全相同;
$request_uri:请求的 URL(包含参数);
$scheme:协议名,HTTP/HTTPS;
$request_method:请求的方法,GET/POST 等;
$request_length:所有请求内容的大小,包括请求行、头部、包体等;
$remote_port:客户端端口
$remote_user:有 HTTP Basic Authentication 协议传入的用户名;
$request:原始的 url 请求,含有方法和协议版本;
$http_user_agent:客户端 agent 信息;
$http_cookie:客户端 cookie 信息;
条件判断
介绍了常用的变量,自然要把它用起来,最常用的就是进行条件判断,从而决定具体操作
先认识下操作符
=:等值比较;
^~:以指定字符串(非正则表达式)开头
~:匹配指定正则表达式,区分大小写;
~*:匹配指定正则表达式,不区分大小写;
!~:不匹配指定正则表达式,区分大小写;
!~*:不匹配指定正则表达式,不区分大小写;
-f/!-f:判断指定的路径是/否为存在且为文件;
-d/!-d:判断指定的路径是/否为存在且为目录;
-e/!-e:判断指定的路径是/否存在,文件或目录均可;
-x/!-x:判断指定路径的文件是/否存在且可执行;
例如:
if($request_uri ~* '/foo') {
rewrite ^(.*) $ https://www.baidu.com;
}
}
再来认识下location,就是上面例子的这玩意:
location / {
proxy_pass http://la/;
proxy_set_header Host $host:$server_port;
}
location指令的作用是根据用户请求的URI来执行不同的应用,也就是根据用户请求的网站URL进行匹配,匹配成功即进行相关的操作,location的语法是:
location [ = | ~ | ~* | ^~ ] uri { .... }
指令 | | 匹配标识 | |匹配的网站网址| |匹配URI之后要执行的配置段|
我们要进行对应的操作,便要有匹配过程,匹配符也就是用于这种情况。
匹配符:
=:等值比较;
^~:以指定字符串(非正则表达式)开头
~:匹配指定正则表达式,区分大小写;
~*:匹配指定正则表达式,不区分大小写;
@:定义一个指定名称的 location,不处理请求,一般用于内部定向,如try_files、
由于一个server里可定义多个location,所以需有个执行的优先级,即哪个的匹配权重高便匹配哪个先,依次类推,一旦匹配成功便不再往下匹配。
优先级从上到下逐渐减小
location = 完整路径
location 完整路径
location ^~ 路径
location ~,~* 正则路径
location 部分起始路径
location /
好了,nginx的基本配置需要掌握的东西已经说完了,下面列举几个日常开发常用的配置例子:
配置实例
1、进行跨域代理
需求背景: 以vue-cli构建后的项目,打包后生产静态文件,其中有个index.html文件。
在开发模式下,我们可以通过devServer下的proxy来代理跨域,然后,打包后,打开index.html, devServer可不会执行。这个时候我们便可通过nginx代理跨域, 如下:
#请求跨域,这里约定代理请求url path是以/api/开头
location ^~/api/ {
#这里重写了请求,将正则匹配中的第一个()中$1的path,拼接到真正的请求后面,并用break停止后续匹配
rewrite ^/api/(.*)$ /$1 break;
proxy_pass 172.183.23.4;
}
2、静态页面配置
server {
listen 80;
server_name localhost;
location / {
#root html;
alias /data/admin/;
index index.html index.htm;
}
}
root的处理结果是:root路径+location路径
alias的处理结果是:使用alias路径替换location路径
alias是一个目录别名的定义,root则是最上层目录的定义。
还有一个重要的区别是alias后面必须要用“/”结束,否则会找不到文件的。。。而root则可有可无~~
3、进行端口代理
这个开头例子已经说过,启动端口为非80端口的希望访问形式为80端口,如 访问自定义域名egg.51.la, 实际访问127.0.0.1, 这时候可以这样做:
首先配置本机域名映射 127.0.0.1 egg.51.la
然后配置nginx:
upstream la {
server 127.0.0.1:7001;
keepalive 2000;
}
server {
listen 80;
server_name egg.51.la;
location / {
proxy_pass http://la/;
proxy_set_header Host $host:$server_port;
}
}
这样便可实现端口代理访问
4、适配PC与移动端
location / {
# 移动、pc设备适配
if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {
set $mobile_request '1';
}
if ($mobile_request = '1') {
rewrite ^.+ http://www.mobile.com;
}
}
5、访问限制
经常会遇到希望网站让某些特定用户的群体(比如只让公司内网)访问,或者控制某个uri不让人访问, 如:
location / {
deny 192.168.1.100;
allow 192.168.1.10/200;
allow 10.110.50.16;
deny all;
}
上述配置的意思就是,首先禁止192.168.1.100访问,然后允许192.168.1.10-200 ip段内的访问(排除192.168.1.100),同时允许10.110.50.16这个单独ip的访问,剩下未匹配到的全部禁止访问
或者禁止搜索引擎蜘蛛访问
server {
......
# 禁止搜索引擎蜘蛛访问
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot") {
return 403;
}
......
}
限制访问比较灵活,可根据实际需求而定
结尾
nginx确实非常强大,可以有非常灵活的应用,上面介绍到只是nginx的冰山一角,也可能有不正确的地方,恳请指正。继续努力,探索nginx的奥秘,助力前端开发。