Nginx 功能
反向代理(reverse proxy):
负载均衡(load banancer):
加密(Encryption):
Nginx安装和下载
如果是windows电脑,记得下载windows版。
下载解压完后,运行start nginx即可开始运行,运行tasklist命令行实用程序以查看nginx进程:
PS D:\PortableSoftware\nginx-1.23.3> start nginx
PS D:\PortableSoftware\nginx-1.23.3> tasklist /fi "imagename eq nginx.exe"
映像名称 PID 会话名 会话# 内存使用
========================= ======== ================ =========== ============
nginx.exe 6464 Console 12 9,488 K
nginx.exe 12792 Console 12 9,472 K
其中一个进程是主进程,另一个是工作进程。如果nginx没有启动,在错误日志文件logs\error.log中查找原因。
运行成功后在浏览器打开localhost或者127.0.0.1 可以看到如下页面:
Nginx/Windows作为标准控制台应用程序(而不是服务)运行,可以使用以下命令进行管理:
nginx -s stop # fast shutdow
nginx -s quit # graceful shutdown
nginx -s reload # changing configuration, starting new worker processes with a new configuration, graceful shutdown of old worker processes
nginx -s reopen # re-opening log files
如果使用的是powershell需要在nginx前加上.\来运行命令,使用 cmd 则无须加前缀。
PS D:\PortableSoftware\nginx-1.23.3> nginx -s stop
nginx : 无法将“nginx”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确。
PS D:\PortableSoftware\nginx-1.23.3> .\nginx -s stop
有的时候尝试停止nginx出现了错误,我们可以使用taskkill来强制停止。
taskkill /pid <PID> /f
# 其中,`<PID>`是找到的Nginx进程的PID。
举例:
D:\PortableSoftware\nginx-1.23.3>tasklist /fi "imagename eq nginx.exe"
映像名称 PID 会话名 会话# 内存使用
========================= ======== ================ =========== ============
nginx.exe 23136 Console 9 8,724 K
nginx.exe 3304 Console 9 9,052 K
D:\PortableSoftware\nginx-1.23.3>taskkill /pid 23136 /f
成功: 已终止 PID 为 23136 的进程。
D:\PortableSoftware\nginx-1.23.3>taskkill /pid 3304 /f
成功: 已终止 PID 为 3304 的进程。
Nignx术语
nginx.conf 这个文件是配置文件。
这种类似键值对的被叫作指令(
directive):
worker_processes 1;
花括号包裹的代码块被叫作上下文(context),上下文里面可以有指令,上下文是指令生效的环境。
events {
worker_connections 1024;
}
从零配置
接下来,删掉nginx.conf的内容,开始从零配置。
运行静态网站
首先,我们先用nginx让一个html文件能在浏览器运行起来,这里我使用nginx自带的html文件:
http {
server {
# 指定端口
listen 80;
# root表示当匹配这个请求的路径时,将会在这个文件夹内寻找相应的文件
root html;
# 当没有指定主页时,默认会选择这个指定的文件,它可以有多个,并按顺序来加载,如果第一个不存在,则找第二个,依此类推。
index index.html
}
}
events {}
然后我修改一下原来的html文件,并刷新一下浏览器,发现它work了!没想到啊,几行指令配置就可以。
在Nginx配置中,events {}块是必需的,因为它定义了Nginx服务器的全局事件模型。这个块主要用于配置与连接处理相关的参数,例如工作进程数、连接超时等。
在events {}块中,可以设置以下参数:
worker_connections:指定每个工作进程的最大连接数。use:指定事件驱动模型,如epoll、kqueue、eventport或select。multi_accept:指定是否接受多个连接。accept_mutex:指定是否使用互斥锁来接受新连接。worker_processes:指定工作进程的数量。
虽然在简单的Nginx配置中,你可能不需要在events {}块中设置任何参数,但是它仍然是必需的,因为它定义了Nginx服务器的全局事件模型。如果你不包含events {}块,Nginx配置文件将无效。
配置Mine Type
如果在想在html通过link标签中引入css,则需要配置mine type,否则nginx就把响应类型设置成了text/plain。
http {
# 指定文件后缀对应的Content-Type
types {
# 如果文件后缀是css,则配置它的Content-Type为text/css
text/css css;
# 如果文件后缀是js,则配置它的Content-Type为application/javascript
application/javascript js;
}
server {
# 指定端口
listen 80;
root html;
index index.html;
}
}
events{
}
运行nginx -s reload后,就发现此时css文件的content-type被设置成了text/css。
但实际环境下超级多的文件类型,如果一个一个的配置,会非常累。幸运的是,nginx已经给我们提供了mime.types文件,我们只需要在nginx.conf引入它即可。
http {
include mime.types;
server {
# 指定端口
listen 80;
root html;
index index.html;
}
}
events{
}
配置location context
示例一
如果我们想要访问另外一个网页呢,比如当用户访问http://localhost:80/fruits后,进入到fruits网页。
我们可以这样通过指定location来实现:
http {
include mime.types;
server {
# 指定端口
listen 80;
root html;
index index.html;
location /fruits {
# 当我们访问/fruits时,就会去访问html/fruits目录下的index.html文件
root html;
}
}
}
events {
}
示例二 alias指令
如果想要访问/carbs的时候,nginx也给我们serve fruits 页面呢?
http {
include mime.types;
server {
# 指定端口
listen 80;
root html;
index index.html;
location /fruits {
# 当我们访问/fruits时,就会去访问html/fruits目录下的index.html文件
# 也就是nginx会自动拼接root和location的路径 变成了html/fruits/index.html
root html;
}
location /carbs{
# 不能使用root,因为我们并没有创建carbs目录
alias html/fruits;
}
}
}
events {
}
示例3:try_files指令
如果我们再创建了一个vegetables目录后,但是我们的html文件不叫index.html,而叫做veggies.html。这个时候,我们可以配置try_files或者使用index直接指定主页。
http {
include mime.types;
server {
# 指定端口
listen 80;
root html;
index index.html;
location /fruits {
# 当我们访问/fruits时,就会去访问html/fruits目录下的index.html文件
# 也就是nginx会自动拼接root和location的路径 变成了html/fruits/index.html
root html;
}
location /carbs {
# 不能使用root,因为我们并没有创建carbs目录
alias html/fruits;
}
location /vegetables {
root html;
# 先去访问html/vegetables/veggies.html文件,如果没有就去访问html/index.html文件,如果还没有就返回404
try_files /vegetables/veggies.html /index.html =404;
# 直接指定主页时veggis.html
index veggies.html;
}
}
}
events {
}
示例4:正则匹配
在 location context 中,可以使用正则表达式来匹配 URI。可以使用 ~ 或 ~* 前缀来指定正则表达式匹配,其中 ~ 区分大小写,~* 不区分大小写。
http {
include mime.types;
server {
# 指定端口
listen 80;
root html;
index index.html;
# ~*表示正则匹配,如果请求的url是/count/开头的,就会去访问html/count目录下的文件
location ~* /count/[0-9] {
try_files /index.html =404;
}
}
}
events {
}
我们这里设置,如果用户访问的是/count/[0-9],则让nginx去serve 根目录下的index.html,但由于我们的这个index.html 还引入了style.css,nginx就去count/style.css去找css了,导致404。
所以我们可以这样配置:
http {
include mime.types;
server {
# 指定端口
listen 80;
root html;
index index.html;
# ~*表示正则匹配,如果请求的url是/count/开头的,就会去访问html/count目录下的文件
location ~* /count/[0-9] {
alias html/;
try_files /index.html =404;
}
location /count/style.css {
alias html/style.css;
}
}
}
events {
}
重定向和重写
现在我们已经有/fruits路由了,如果想要当用户访问/crops时,重定向到/fruits路由,可以这样配置。
http {
include mime.types;
server {
# 指定端口
listen 80;
root html;
index index.html;
location /fruits {
# 当我们访问/fruits时,就会去访问html/fruits目录下的index.html文件
# 也就是nginx会自动拼接root和location的路径 变成了html/fruits/index.html
root html;
}
location /crops {
# 307 临时重定向 302 也是临时重定向 302假设客户端会改用GET方法 307要求客户端继续使用原来的请求方法
return 307 /fruits;
}
}
}
events {}
可以看到如果用户访问了/crops,他会被重定向到/fruits路由。
但如果,我们并不想重定向,只是想要别的路由下路由,就可以使用rewrite指令。下面的示例中,如果访问/number/数字,nginx则会提供/count/数字的内容
http {
include mime.types;
server {
# 指定端口
listen 80;
root html;
index index.html;
rewrite ^/number/(\d+) /count/$1;
location ~* /count/[0-9] {
alias html/;
try_files /index.html =404;
}
}
}
events {
}
负载均衡 (load banancer)
基本概念
负载均衡是一种将网络流量分发到多个服务器上的技术,以实现更高的可用性、性能和可扩展性。在负载均衡系统中,请求会被分发到不同的服务器上,从而避免任何一台服务器过载或出现故障时影响整个系统的运行。
nginx实现负载均衡的方式有多种,下面是其中两种常用的方式:
a.基于轮询(Round Robin) 默认情况下,nginx使用轮询算法进行负载均衡,将请求均匀地分发到多个后端服务器上。例如,在下面的配置中,nginx将请求轮流转发到server1和server2两台服务器上:
upstream backend {
server server1;
server server2;
}
这种方法的优点是简单易用,可以均衡地分配请求。但是,如果某个后端服务器出现故障,则需要手动将其从upstream中删除,否则nginx仍然会将请求转发到该服务器上。
b.基于权重(Weighted Round Robin)
在轮询算法的基础上,nginx还可以使用权重算法进行负载均衡。通过为每个后端服务器分配不同的权重值,使得某些服务器能够处理更多的请求。例如,在下面的配置中,nginx将70%的请求转发到server1上,30%的请求转发到server2上:
upstream backend {
server server1 weight=7;
server server2 weight=3;
}
制作运行docker镜像
我们可以docker来运行多个server,这里就用express当作服务器。
npm init -y
npm i express
const express = require('express');
const app = express();
app.get('/',(req,res)=>{
res.send('I am a endpoint');
})
app.listen(7777,()=>{
console.log('listening on http://localhost:7777');
})
然后再创建DockerFile,跟着node官网的教程来操作:
FROM node:16
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm ci --omit=dev
# Bundle app source
COPY . .
EXPOSE 7777
CMD [ "npm", "run","start" ]
最后制作镜像:
docker build . -t myserver
可以在docker desktop看到已经制作完的镜像:
接着开始跑运行该镜像的容器,尽管我们容器是运行在7777端口的,但是我们可以映射为我们本机的任意端口。
# -p 端口映射 -d 后台运行
docker run -p 1111:7777 -d myserver
然后如果我们访问http://localhost,就可以发现运行成功了:
那我们再继续运行几个容器:
docker run -p 2222:7777 -d myserver
docker run -p 3333:7777 -d myserver
docker run -p 4444:7777 -d myserver
nginx配置负载均衡
http {
include mime.types;
upstream backendserver{
server 127.0.0.1:1111;
server 127.0.0.1:2222;
server 127.0.0.1:3333;
server 127.0.0.1:4444;
}
server {
# 指定端口
listen 80;
location /{
proxy_pass http://backendserver/;
}
}
}
events {
}
最后,这个是全部的配置:
http {
include mime.types;
upstream backendserver{
server 127.0.0.1:1111;
server 127.0.0.1:2222;
server 127.0.0.1:3333;
server 127.0.0.1:4444;
}
server {
# 指定端口
listen 80;
root html;
index index.html;
rewrite ^/number/(\d+) /count/$1;
# ~*表示正则匹配,如果请求的url是/count/开头的,就会去访问html/count目录下的文件
location ~* /count/[0-9] {
alias html/;
try_files /index.html =404;
}
location /count/ {
alias html/;
}
location /{
proxy_pass http://backendserver/;
}
location /fruits {
# 当我们访问/fruits时,就会去访问html/fruits目录下的index.html文件
# 也就是nginx会自动拼接root和location的路径 变成了html/fruits/index.html
root html;
}
location /carbs {
# 不能使用root,因为我们并没有创建carbs目录
alias html/fruits;
}
location /vegetables {
root html;
# 先去访问html/vegetables/veggies.html文件,如果没有就去访问html/index.html文件,如果还没有就返回404
try_files /vegetables/veggies.html /index.html =404;
# 直接指定主页时veggis.html
index veggies.html;
}
location /crops{
# 307 临时重定向 302 也是临时重定向 302假设客户端会改用GET方法 307要求客户端继续使用原来的请求方法
return 307 /fruits;
}
}
}
events {
}
注:本文是根据此youtu.be/7VAI73roXaY 视频