Nginx (engine x) 是一款轻量级的 Web 服务器(软件)、反向代理服务器(软件)及电子邮件(IMAP/POP3)代理服务器(软件)。
在我们公司,Nginx 最常见的场景是用来配置域名,但“配置域名”这个说法其实过于笼统,且不严谨。为什么呢?
我们延伸一下,先来说说“域名”。
**域名(Domain Name)**说白了,就是一个字符串,比如 baidu.com。通过域名,我们能在浏览器里访问一个网站/站点,通过 IP,比如 220.181.38.148,也能访问,但 99% 的人都会选择通过域名访问网站,毕竟域名好记多了。
从技术角度来说,“网站”是一个部署在某台服务器上的软件,要访问到它,浏览器肯定得知道这台服务器在哪里。那么,为什么通过域名,浏览器就能知道网站在哪台服务器上呢?这就要提到 **DNS(Domain Name Server)**了。
顾名思义,DNS(Domain Name Server) 的意思是“域名服务器”。DNS 干的活,就是告诉浏览器,一个域名对应的 IP 地址是多少。
那 DNS 又是如何知道域名和 IP 的对应关系的呢?这就涉及到**“域名解析”**了。
域名解析,对咱们公司而言,只需关注一种类型,就是**“A 记录”类型。A 是 Address 的意思,配置一条 A 记录,就是配置一条域名和 IP 地址**的对应关系记录。很多人说“配置域名”,其实他的目的可能只是要做一下“域名解析”。
**域名解析,可以在域名注册商的管理后台进行操作。**国内主要的域名注册商有万网(阿里的)、新网、DNSPod(腾讯的)等,这些域名注册商除了提供域名购买服务,也会提供域名解析服务,一般在管理后台都能看到“域名解析”的功能。
汇总一下域名的有关流程——
-
访问域名注册商网站,选择并购买一个域名(一般是购买一级域名,比如 aaa.com)
-
购买完成后,登录域名注册商管理后台,找到“域名解析”功能,添加一条域名解析 A 记录,一般是解析二级域名或对应子域名,比如将 1.aaa.com 解析到某个公网 IP 上(对于我们公司的项目而言,这个 IP 所对应的服务器上,通常都会安装 Nginx,或者这个 IP 对应的是医院防火墙服务器,它能通过端口映射,让公网用户访问到防火墙后方的 Nginx 服务器)
说了这么多域名相关的东西,跟 Nginx 又有什么关系呢?
简单来说,用户通过浏览器访问域名,只是完成了从客户端到服务器的访问。在这之后,Nginx 就登场了,它会捕获到这些来自于公网的请求,并根据相关配置规则,将请求转交给后端某台服务器上。后端服务器处理完请求后,将响应发送给 Nginx 服务器,Nginx 服务器收到响应后,将其发回给用户客户端,这样就完成了一次完整的请求过程,这其实就是“反向代理”的通俗化解释。
Nginx 有很多优点,比如高性能(高并发支持非常给力)、高扩展性(模块化设计、庞大的第三方模块)、跨平台(二进制发布)、高可靠性(宕机概率极低)等等,所以熟悉 Nginx 的相关功能是很有必要的,尤其对于后端开发来说更是如此。
一、安装 Nginx
开发人员经常找运维分配一个域名,然后将这个域名的请求反向代理到某台服务器的某个端口上。运维人员的做法是,到 DNSPod 上(A 记录)解析一个新域名到公司的 Nginx 服务器(腾讯云 Nginx 服务器或公司内网 Nginx 服务器)的 IP 上,也就是 115.159.1.60(腾讯云)/183.129.254.168(公司内网),然后再到 Nginx 服务器上,在某个已有配置文件中新增一个 server 配置块或直接新增一个配置文件,最后重载 Nginx。
上面这个做法,是利用了公司已经有的 Nginx 来进行请求反向代理。对于某些非 SaaS 化(独立部署)的项目,可以这么做,但独立部署 Nginx 有独立部署的优势和必要性。
独立部署 Nginx,意味着——
-
不占用公司 Nginx 服务器的带宽资源
-
独立部署的项目,独占本地 Nginx 服务器的带宽资源
-
一定程度上,加快了服务访问的速度
因此,独立部署 Nginx 是个很好的选择。**但由于服务的访问都要通过 Nginx 进行反向代理,所以 Nginx 所在服务器的公网带宽得保证足够高。**对于公司项目来说,一般建议 Nginx 服务器的带宽为 20M 起。
下面讲一下如何在服务器上安装 Nginx(直接联系运维人员安装也是个好办法)。
1、Linux 上安装 Nginx
鉴于公司独立部署的项目,一般都要求客户提供 CentOS 7.x 版本(可以在服务器上输入 cat /etc/redhat-release
查看版本)的服务器,所以就单独说下 CentOS 7.x 系统如何安装 Nginx。
先决条件
首先,得确保有一个拥有 CentOS 服务器 root 权限的用户(不一定是 root 用户,普通用户也可以设置 root 权限,有 root 权限的用户,sudo 命令才能生效)。
其次,得确保 CentOS 服务器能够访问公网(主要是为了方便通过 yum 安装软件),否则就只能上传二进制源码包进行手动编译,但这种方式大概率会导致编译失败,因为你基本上无法顺利地解决复杂的软件依赖问题。
第一步——添加 Nginx yum 源
$ sudo rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
安装完 yum 源后,检查一下是否添加成功
$ sudo yum repolist
如果看到有 nginx repo,则表示 Nginx 仓库添加成功。
第二步——安装 Nginx
$ sudo yum -y install nginx
第三步——启动 Nginx
$ sudo systemctl start nginx
这里注意一下服务器的防火墙状态,如果是开启着(active)的,需要设置允许对 HTTP(默认 80 端口)、HTTPS(默认 443 端口)服务进行访问。
查看防火墙状态(CentOS7 使用的防火墙 firewalld 默认是关闭 http 服务的)——
$ sudo systemctl status firewalld
如果看到 running,则表示防火墙是开启的,就需要输入如下命令设置允许访问 HTTP、HTTPS 服务
$ sudo firewall-cmd --permanent --zone=public --add-service=http $ sudo firewall-cmd --permanent --zone=public --add-service=https$ sudo firewall-cmd --reload
输入下面的命令,查看对 HTTP、HTTPS 服务的访问是否真的开启了
$ sudo firewall-cmd --list-service
如果能看到结果列表里有 http、https 就 OK 了。
再说几个 Nginx 相关的命令。
设置 Nginx 开机启动——
$ sudo systemctl enable nginx
重载 Nginx 配置——
$ sudo systemctl reload nginx
重启 Nginx 服务——
$ sudo systemctl restart nginx
需要指出的是 CentOS 7 的 SELinux,使用反向代理需要打开网络访问权限。
2、Windows 上安装 Nginx
请注意,Nginx 官方将 Nginx Windows 版本看成是 beta 版本,因此其高性能、高扩展性无法和 Linux 版本相比。
第一步——下载最新的主线版本
最新的主线版本号是 1.17.4,官方下载地址: nginx.org/download/ng…。
第二步——解压 Nginx
我们将主线版本压缩包放到某个目录下进行解压,比如放到 C 盘根目录下,然后解压。
第三步——启动 Nginx
解压后进入 nginx-1.17.4 目录,直接双击运行文件夹里的 nginx.exe 即可启动 Nginx。
可以打开一个 cmd 窗口,运行 tasklist
命令查看 Nginx 是否正常启动,比如——
C:\nginx-1.17.4>tasklist /fi "imagename eq nginx.exe"Image Name PID Session Name Session# Mem Usage=============== ======== ============== ========== ============nginx.exe 652 Console 0 2 780 Knginx.exe 1332 Console 0 3 112 K
上面一个是 master 主进程,一个是 worker 工作进程。
如果没有显示 nginx.exe 进程,可以进入 nginx-1.17.4 目录下的 logs 目录,查看 error.log 文件,排查错误信息。
注意,Nginx 运行目录,比如 C:\nginx-1.17.4,是 Nginx 配置文件(Nginx 的配置文件是 C:\nginx-1.17.4\conf\nginx.conf)里配置的相对路径的目录前缀。
但是通过双击 nginx.exe 启动的 Nginx 只是一个控制台应用,并不是一个系统服务,这就意味着一旦关闭这个 cmd 窗口,Nginx 进程也就停止了。当然,服务器如果意外关机了,重启后 Nginx 自然也没有在运行。
所以我们得想办法将其包装成一个系统服务,这样就可以设置开机自启动,并且也能方便地重启服务或停止服务。
我们通过开源的 Windows Service Wrapper(简称为 winsw)软件或者 nssm,将 Nginx 包装成 Windows 系统服务。多说一句,这个 winsw 也可以将 Java 的 jar 包(比如一个 Spring Boot 的 jar 包)包装成 Windows 系统服务。
具体步骤:
-
下载官方的 winsw 软件,目前最新版本 v2.3.0。winsw 需要 .NET 支持(也就是说服务器上要有 .NET 库),对于是 Windows Server 2008 R2 系统的服务器来说,下载 WinSW.NET4.exe 即可。
-
将下载的 WinSW.NET4.exe 放到 Nginx 的运行目录下,比如 C:\nginx-1.17.4。为了方便表示,可以将 WinSW.NET4.exe 重命名成 nginx-service.exe。然后在这个目录下,再创建一个同名的 XML 文件,即 nginx-service.xml。也就是说,nginx-service.exe 的完整路径是 C:\nginx-1.17.4\nginx-service.exe,nginx-service.xml 的完整路径是 C:\nginx-1.17.4\nginx-service.xml。
-
在 C:\nginx-1.17.4 下创建一个 cmd 文件,文件名为 nginx-stop.cmd,顾名思义它是用来杀掉 nginx 进程的,内容如下——
@echo offcd /C %~dp0if not exist logs\nginx.pid GOTO skipnginx.exe -s quitdel logs\nginx.pid:skiptaskkill /f /IM nginx.exe
-
编辑 nginx-service.xml 文件内容,如下所示——
<?xml version="1.0" encoding="utf-8"?><service> <id>Nginx Service</id> <name>Nginx Service</name> <description>High Performance Nginx Service</description> <logpath>C:\nginx-1.17.4\logs</logpath> <log mode="roll-by-size"> <sizeThreshold>10240</sizeThreshold> <keepFiles>8</keepFiles> </log> <executable>C:\nginx-1.17.4\nginx.exe</executable> <stopexecutable>C:\nginx-1.17.4\nginx-stop.cmd</stopexecutable> </service>
-
然后以管理员身份打开一个 cmd 窗口,并切换到 C:\nginx-1.17.4 目录。
-
运行
nginx-service.exe install
命令,即可完成 Nginx 服务的注册。 -
按 win+R 键,输入
services.msc
打开 Windows 系统服务列表,找到其中的 Nginx Service,右键点击启动,并点击属性菜单将启动类型设置为“自动”,完成服务的自启动设置。
二、配置 Nginx
首先,我们要知道 CentOS 服务器上安装的 Nginx,它的全局配置文件路径是 /etc/nginx/nginx.conf
。但这个全局配置文件,一般都是用来进行 Nginx 进程运行用户(user)、Nginx 工作进程数(worker_processes)等的配置,对于开发人员来说,基本不用去修改它。
开发人员,一般只需要关注 /etc/nginx/conf.d/default.conf
以及 /etc/nginx/conf.d/自定义的.conf
等文件。我们在 conf.d
目录下自行创建的 *.conf
文件,一旦 Nginx 服务重新加载(nginx -s reload
),马上就会加载生效。
对于 Windows 版本的 Nginx,我们一般不自定义 *.conf
配置文件,而是直接修改全局配置文件 default.conf
,在文件最下面追加相关配置。
接下来说说最常用的 Nginx 配置。
1、server-反向代理配置
server 块的配置,可以说是运维及开发人员使用最多的配置了。我们常说的做一个域名配置、虚拟主机配置、服务反向代理配置,就是指新增一个 server 块的配置。
比如我们在 conf.d
目录下创建一个 hlwyy.conf
的配置文件,命令是 vi /etc/nginx/conf.d/hlwyy.conf
。然后我们按键盘上的 i
键,进入插入模式。
(1)HTTP 反向代理配置
输入如下命令——
server { listen 80; server_name foobar.com;
location / { proxy_pass http://127.0.0.1:8080/;
}}
完成后,按键盘 ESC
键退出插入模式,再按键 :wq
保存退出,这样就完成了一个最简单的 HTTP 域名反向代理配置。
我们分析一下上面的指令。
-
server:不用说,既然写的是 server,那肯定是对服务做配置,或者说是对虚拟主机做配置
-
listen:指定 Nginx 服务监听的本地端口,80 是 HTTP 服务的默认端口,443 是 HTTPS 服务的默认端口,监听 80 端口即代表监听 HTTP 连接
-
server_name:一般是域名,很少会使用 IP 地址,上面写的 “foobar.com“ 是域名,而且这个域名解析到的 IP 地址,就是当前这台安装了 Nginx 的服务器的公网 IP 地址
-
location:配置路由规则,后面可以是具体 URL 路径或者正则表达式,上面写的
/
就是表示匹配项目根目录的请求,也就是匹配访问 foobar.com/ 这个 URL 的请求 -
proxy_pass:指定将请求反向代理到哪个服务上,上面的命令就是把 foobar.com/ 的请求,反向代理到本机占用 8080 端口的服务上(对于我们公司的项目而言,基本上都是 tomcat 进程)。注意,如果 Nginx 服务器本身无法访问得通后端的服务地址(换句话说,Nginx 所在的服务器,telnet 不通 127.0.0.1:8080),那么反向代理就是失效的,还是就是服务地址最末尾的正斜杠不要忘了写!
以上命令,还需要再注意一下空格、末尾分号,避免出现不必要的 Nginx 配置语法错误。
(2)HTTPS 反向代理配置
再来看一个最简单的 HTTPS 域名反向代理配置。
server { listen 443 ssl; server_name foobar.com; ssl_certificate /etc/nginx/ssl/foobar.com.crt; ssl_certificate_key /etc/nginx/ssl/foobar.com.key; # 匹配根路径的 URL 请求 location / { proxy_pass http://127.0.0.1:8080/; } # 匹配 /admin/ 路径的 URL 请求 location /admin/ { proxy_pass http://127.0.0.1:13130/; } # 图片文件保存在 /data/images 目录下 location ~ \.(gif|jpg|png)$ { root /data/images; }}
相比 HTTP 域名的反向代理配置,HTTPS 域名的反向代理配置多了3个新指令。
-
ssl:紧跟在 listen 监听的 443 端口后面,表示监听 443 端口,开启 ssl 访问
-
ssl_certificate:指定 ssl 证书文件的路径,Nginx 类型的 ssl 证书文件,在 Linux 服务器上一般是以 .crt 结尾的文件,证书文件路径可以是相对路径,但是为了减少不必要的错误(比如文件权限问题),请设置成绝对路径,放到
/etc/nginx/ssl
目录下 -
ssl_certificate_key:指定 ssl 私钥文件的路径,Nginx 类型的 ssl 私钥文件,一般是以 .key 结尾的文件,同样使用绝对路径,如
/etc/nginx/ssl/foobar.com.key
注意上面有三个 location 的配置,1个是匹配 foobar.com/ 这个 URL 的请求,1个是匹配 foobar.com/admin/ 这个 URL 的请求,Nginx 分别将它们反向代理到不同的服务上。最后1个 location 后面跟的是正则表达式(以 ~ 符号开头),它根据正则进行匹配,上面的例子是访问 foobar.com/1.png 这个 URL 时,Nginx 会把服务器上的 /data/images/1.png 图片返回给请求端。