前端视角_Nginx从入门到实践一

文章首发:

在最开始,我们先明确一个认知,在大前端的环境下,Nginx不仅是运维工程师和后端工程师需要掌握的基础技能,也成为了前端工程的核心技能之一。 当然,根据「最小化」原则和自身情况,从前端视角来看,掌握的深度需要根据自身情况来调整。

前言

最近在个人站点()上,添加了基于egg.js + GitHub的第三方登录功能,千辛万苦的终于在本地调通了,结果部署到服务器上,cookies竟然失效了,简单梳理了下,就发现本地和服务器上区别就在于多了一层Nginx层,首要考虑问题是Nginx的配置问题,且在egg.js的官网上对这一块也是有说明的,见 :

如应用部署在 Nginx/HAProxy 之后,需设置插件 proxy 选项为 true, 并检查以下配置:代理附加 HTTP 头字段:x-forwarded-proto 与 x-forwarded-host 配置中 config.proxy 应设置为 true

于是开始调试Nginx的配置,由于没有系统学习Nginx基础语法, 因语法问题导致多次部署失败,就正好趁此机会将相关内容梳理下。

Nginx介绍

Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器,而且支持热部署,几乎可以做到 7 * 24 小时不间断运行,即使运行几个月也不需要重新启动,还能在不间断服务的情况下对软件版本进行热更新。性能是 Nginx 最重要的考量,其占用内存少、并发能力强、能支持高达 5w 个并发连接数,最重要的是,Nginx 是免费的并可以商业化,配置使用也比较简单。

使用场景:

静态资源服务器,通过本地文件系统提供服务;

反向代理,进一步延伸如:缓存,负载均衡等;

API服务。

Nginx和node.js的很多理念类似,如:http服务器、事件驱动以及异步非阻塞等,但各自有自己擅长的领域,Nginx擅长底层服务器端资源的代理,node.js更擅长上层具体业务逻辑的处理。

正向代理和反向代理

反向代理(Reverse Proxy)对应的是正向代理(Forward Proxy),他们的区别:

正向代理: 一般的访问流程是客户端直接向目标服务器发送请求并获取内容,使用正向代理后,客户端改为向代理服务器发送请求,并指定目标服务器(原始服务器),然后由代理服务器和原始服务器通信,转交请求并获得的内容,再返回给客户端。正向代理隐藏了真实的客户端,为客户端收发请求,使真实客户端对服务器不可见;

举个具体的例子 ,你的浏览器无法直接访问谷哥,这时候可以通过一个代理服务器来帮助你访问谷哥,那么这个服务器就叫正向代理。

反向代理: 与一般访问流程相比,使用反向代理后,直接收到请求的服务器是代理服务器,然后将请求转发给内部网络上真正进行处理的服务器,得到的结果返回给客户端。反向代理隐藏了真实的服务器,为服务器收发请求,使真实服务器对客户端不可见。一般在处理跨域请求的时候比较常用。现在基本上所有的大型网站都设置了反向代理。

举个具体的例子 ,去饭店吃饭,可以点川菜、粤菜、江浙菜,饭店也分别有三个菜系的厨师 ‍ ,但是你作为顾客不用管哪个厨师给你做的菜,只用点菜即可,小二将你菜单中的菜分配给不同的厨师来具体处理,那么这个小二就是反向代理服务器。

简单地说,一般给客户端做代理的都是正向代理,给服务器做代理的就是反向代理。

安装

Mac M1 下安装

安装和校验

arch -arm64 brew install nginxbrew info nginxnginx: stable 1.21.6, HEADHTTP(S) server and reverse proxy, and IMAP/POP3 proxy server/opt/homebrew/Cellar/nginx/1.21.6_1 (26 files, 2.2MB) *Poured from bottle on 2022-03-26 at 09:24:26From: https://mirrors.ustc.edu.cn/homebrew-core.git/Formula/nginx.rbLicense: BSD-2-Clause==> DependenciesRequired: [email protected] ✔, pcre2 ✔==> Options--HEADInstall HEAD version==> CaveatsDocroot is: /opt/homebrew/var/wwwThe default port has been set in /opt/homebrew/etc/nginx/nginx.conf to 8080 so thatnginx can run without sudo.nginx will load all files in /opt/homebrew/etc/nginx/servers/.To restart nginx after an upgrade:brew services restart nginxOr, if you dont want/need a background service you can just run:/opt/homebrew/opt/nginx/bin/nginx -g daemon off;

NOTE: 可以从上面的信息找到很多基础的配置信息。

TIPS:一般来说,安装好nginx之后,我们主要关注两个文件夹

/etc/nginx/conf.d/ 文件夹,是进行子配置的配置项存放处,/etc/nginx/nginx.conf 主配置文件会默认把这个文件夹中所有子配置项都引入。

windows下,是对应的安装目录下的conf目录。Mac M1下,是/opt/homebrew/etc/nginx/servers目录。

/usr/share/nginx/html/ 文件夹,通常静态文件都放在这个文件夹

windows下, 对应的目录是在安装目录下的html目录。Mac M1下,是/opt/homebrew/var/www。

其它命令

sudo nginx 启动服务

sudo nginx -s stop 停止服务(直接走)

sudo nginx -s reload 重新加载

sudo nginx -s reopen 重新启动

sudo nginx -s quit 退出(处理完事情走)

open /opt/homebrew/etc/nginx/ 查看nginx安装目录

max下使用brew安装的nginx的命令如下:

tips: 使用brew services -h查看brew services的使用帮助。

# 查看服务运行列表brew services list# nginx nonebrew servicesstart nginx# 现在可以在浏览器中访问::8080/

使用

配置语法校验

使用下面命令:

nginx -t -c /usr/local/nginx/conf/nginx.conf

-c: 指定需要检验的配置文件

-t: 测试配置文件是否正确,在运行时需要重新加载配置的时候,此命令非常重要,用来检测所修改的配置文件是否有语法错误。

语法

这里只讨论一些基础常用的配置语法。

配置语法

配置文件由指令与指令块组成。

每条指令以分号(;)结尾,指令与参数间以空格符号分割,值参数可以是一个或多个附加参数,取决于解析该条指令的模块。

指令块以大括号({})将多条指令组织在一起。

使用#添加注释。

使用$符号使用变量。

部分指令参数支持正则表达式。

一个示例,执行命令cat /opt/homebrew/etc/nginx/nginx.conf:

# worker进程运行的用户和组,如果没有提供则使用nginx的master进程的用户和用户组#usernobody;# nginx进程数,一般和cpu核数一致worker_processes1;# 错误日志,级别有debug, info, notice, warn, error和crit(debug记录了全部日志,crit仅报告关键错误)#error_loglogs/error.log;#error_loglogs/error.lognotice;#error_loglogs/error.loginfo;#pidlogs/nginx.pid;events {# 每个进程允许的最大并发数worker_connections1024;}http {# 引入其它配置,mime.types文件存储的是文件扩展名与类型映射表include mime.types;default_typeapplication/octet-stream;# 日志格式#log_formatmain$remote_addr - $remote_user [$time_local] "$request" #$status $body_bytes_sent "$http_referer" #"$http_user_agent" "$http_x_forwarded_for";#access_loglogs/access.logmain;# 开启sendfile配置提高文件的传输速率sendfileon;#tcp_nopush on;#keepalive_timeout0;# 指定KeepAlive的超时时间,即TCP可以保持的时长。keepalive_timeout65;# 开启gzip压缩#gzipon;# 服务器配置server {# 监听套接字使用的端口号listen 8080;# 指定一个或多个主机名server_namelocalhost;#charset koi8-r;# 开启访问日志#access_loglogs/host.access.logmain;# 访问地址location / {root   html;    index  index.html index.htm;}#error_page404/404.html;# redirect server error pages to the static page /50x.html#error_page 500 502 503 504/50x.html;location = /50x.html {    root   html; }#location ~ /\.ht {#denyall;#}# 另一个虚拟主机使用基于IP,名称和端口的混合配置##server {#listen 8000;#listen somename:8080;#server_namesomenamealiasanother.alias;#location / {#root html;#indexindex.html index.htm;#}    #}# HTTPS server - https服务配置##server {#listen 443 ssl;    #    server_name  localhost;#ssl_certificatecert.pem;#ssl_certificate_keycert.key;#ssl_session_cacheshared:SSL:1m;#ssl_session_timeout5m;#ssl_ciphersHIGH:!aNULL:!MD5;#ssl_prefer_server_cipherson;#location / {#root html;#indexindex.html index.htm;#}#}# 加载子配置include servers/*;}

tips: 可以在阿里云、腾讯云等云服务器商申请免费的SSL证书,一般使用期是一年,个人开发者足够使用。

说明:

nginx收到http请求时,根据请求header中Host值与所有server区段比较,第一个与主机名匹配的server块将被命中,如果没有server区段与客户端请求的主机名匹配,nginx会选择第一个server区段,匹配监听参数(如listen *:80), 另外具有default选项的listen会被优先选择。

sendfile,指定nginx是否调用sendfile函数来输出文件,减少内核空间和用户空间的上下文切换。对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。

备注:

I/O在系统层面的2个阶段:第一个阶段是读取文件,将文件放入操作系统内核缓存区;第二个阶段是将内核缓冲区拷贝到应用程序地址空间。

nginx指令

文档:;

Nginx的指令非常多,不建议死记硬背,使用时查询官方文档即可,实际上,可以通过模块名称大致了解到其功能。

常用的模块:

Alphabetical index of variables - nginx提供的所有变量。

Core functionality - 核心功能,主要针对main/event context的设置。

使用nginx -V查看nginx的配置参数,看除了核心模块之外还添加了哪些模块。

以ngx_http_gzip_module举个例子:

;

该模块表示是否启用响应的gzip压缩。

示例配置:

gzipon;gzip_min_length 1000;gzip_proxiedexpired no-cache no-store private auth;gzip_typestext/plain application/xml;

$gzip_ratio变量可以记录实现的压缩率。

指令语法:

Syntax:gzip on | off;Default:gzip off;Context:http, server, location, if in location

Syntax - 表示使用语法;

Default - 默认情况下未使用;

Context - 表示该指令可以出现的位置,如上面表示可以出现在location、http和server指令块中。

如果块指令可以在括号内包含其它指令,则称其为context。

一个指令出现在多个指令块中,哪个会生效呢?

Nginx中指令继承规则是向上覆盖。 当子配置存在时,直接覆盖父配置,子配置不存在才使用父配置块或默认配置。

指令都有作用域。

配置(指令)块能相互嵌套。在某些情况下不同配置块能够相互嵌套,如在http区段,可以声明一个或多个server区段,server区段又可以插入一个或多个location区段。

字符串的值,如果指令值中包含空格、分号或者是大括号等特殊字符,需要使用单引号或双引号将其括起。

基本模块

Nginx是由一系列模块组成的,大致可以分为:

核心模块

http核心模块

其它模块

核心模块在编译时不能被禁用。 核心模块包含:main模块,events模块和includes包含指令。

main模块位于配置文件顶层,提供如:进程管理和安全的能力,使用说明见上面。

events模块,事件模块提供的指令可以用来配置网络机制。

accept_mutex:on; # 默认值on,启用或禁用使用一个接受互斥锁来打开套接字监听use epoll; # 指定nginx所使用的网络事件模型,可选值有/dev/poll,epoll,kqueue等,通常不需要显式指定它,默认情况下nginx将使用最有效方法worker_connections 1024; # 定义一个worker进程能够同时连接的数量

include指令,用来包含子配置配置文件,在配置文件的任何地方均可插入该指令。注意,如果没有指定绝对路径,那么文件路径将和配置文件的目录相关。

参考资料

官网 -。

中文网 - ;。

Nginx基础语法 -。

 4. 你不知道的 Nginx -。

大家加油 :)