vlambda博客
学习文章列表

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;       } }}


includekeepalive_timeout这些称为http全局参数, 影响http全局配置,如keepalive_timeout为客户端连接超时时间,include  为导入文件集; 相关参数较多,具体功能可以自行查阅,重点在upstream块与server块


upstream 说白了就是做负载均衡,它可以帮助我们定义一组相同服务的别名,如la,当请求到来的时候可以通过相关策略帮我们选一组服务提供响应。目前只能被 proxy_passfastcgi_passuwsgi_passscgi_passmemcached_passgrpc_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的奥秘,助力前端开发。