文章目录
1. 安装、启动、连接
直接拿docker安装,拉取镜像,运行,开放端口。
docker pull nginx:stable-perl
虽然在容器中性能有所损失,但是方便,加快学习进度。
启动后浏览器访问localhost,写着Welcome等欢迎语,就是启动成功了。
在VSCode下载一些Docker常用插件,然后就可以拿VSCode直接连上’正在运行的容器’,和连接Linux服务器一样。
输入nginx -V
,查看nginx信息,包括安装目录、编译参数、配置文件位置、日志文件位置等信息。可以看到配置文件位于--conf-path=/etc/nginx/nginx.conf
。
root@f4f6c922d837:/# nginx -V
nginx version: nginx/1.26.1
built by gcc 12.2.0 (Debian 12.2.0-14)
built with OpenSSL 3.0.11 19 Sep 2023
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_v3_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -ffile-prefix-map=/data/builder/debuild/nginx-1.26.1/debian/debuild-base/nginx-1.26.1=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'
2. 快速尝试部署网站
查看nginx配置文件,可以找到如下部分。
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
这意味着,nginx 把所有对服务器根路径的请求,代理到 /usr/share/nginx/html 目录下,并且把 index.html 或 index.htm 作为默认页面。
如果你使用Vue或者Hex开发网站,它们的打包输出目录,大致结构分别如下
dist/
├── css/
│ └── app.12345.css
├── js/
│ └── app.12345.js
├── index.html
└── favicon.ico
public/
├── css/
│ └── style.css
├── js/
│ └── script.js
├── index.html
├── about/
│ └── index.html
└── archives/
└── index.html
你只需要把dist或者public下的所有文件,直接复制到/usr/share/nginx/html目录下,重启nginx即可。
3. 配置文件
这个版本的nginx自带2个配置文件,首先是nginx.conf。
如果你修改了配置文件,可以用
nginx -t
来校验配置是否合法。然后使用nginx -s reload
来重新加载配置文件。
1. nginx.conf
全局配置
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
-
user
指令:- 用法:
user <username>;
- 描述:指定 Nginx 运行时使用的系统用户。
- 示例:
user nginx;
表示使用nginx
用户。
- 用法:
-
worker_processes
指令:- 用法:
worker_processes <number|auto>;
- 描述:设置工作进程数,
auto
会自动根据 CPU 核心数设置。 - 示例:
worker_processes 4;
表示使用 4 个工作进程。
- 用法:
-
error_log
指令:- 用法:
error_log <file> <level>;
- 描述:设置错误日志的路径和日志级别。
- 日志级别选项:
debug
:调试信息info
:一般信息notice
:通知信息(默认)warn
:警告信息error
:错误信息crit
:严重错误信息alert
:需要立即处理的问题emerg
:紧急情况
- 示例:
error_log /var/log/nginx/error.log notice;
表示记录通知级别及以上的日志。
- 用法:
-
pid
指令:- 用法:
pid <file>;
- 描述:指定存储 Nginx 进程 ID 的文件路径。
- 示例:
pid /var/run/nginx.pid;
表示将 PID 存储在/var/run/nginx.pid
文件中。
- 用法:
可能改动的部分:
worker_processes auto;
自动设置为 CPU 核心数,适用于大多数情况。
可以手动设置为特定的进程数以微调性能,但一般不需要。
事件模块
events {
worker_connections 1024;
}
worker_connections
指令:- 用法:
worker_connections <number>;
- 描述:设置每个工作进程允许的最大连接数。
- 示例:
worker_connections 1024;
表示每个工作进程允许最多 1024 个连接。
- 用法:
可能改动的部分:
worker_connections 1024;
默认设置为 1024,适用于大多数小到中型网站。
对于高流量网站,可以增加连接数,以提高并发处理能力。
需要根据系统的 ulimit 设置进行调整,确保系统支持更多的连接。
HTTP 模块
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
-
include
指令:- 用法:
include <file|directory>;
- 描述:包含指定的文件或目录下的所有配置文件。
- 示例:
include /etc/nginx/mime.types;
包含 MIME 类型配置文件。
- 用法:
-
default_type
指令:- 用法:
default_type <MIME-type>;
- 描述:设置默认的 MIME 类型。
- 示例:
default_type application/octet-stream;
表示未能确定文件类型时使用application/octet-stream
。
- 用法:
-
log_format
指令:-
用法:
log_format <name> <format>;
-
描述:定义日志格式。
-
示例:
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
定义名为
main
的日志格式。
-
-
access_log
指令:- 用法:
access_log <file> <format>;
- 描述:设置访问日志的路径和日志格式。
- 示例:
access_log /var/log/nginx/access.log main;
使用main
格式记录访问日志。
- 用法:
-
sendfile
指令:- 用法:
sendfile <on|off>;
- 描述:启用或禁用
sendfile
选项,用于提高文件传输效率。 - 示例:
sendfile on;
启用sendfile
。
- 用法:
-
tcp_nopush
指令:- 用法:
tcp_nopush <on|off>;
- 描述:用于优化传输数据时的 TCP 性能,通常与
sendfile
一起使用。 - 示例:
#tcp_nopush on;
默认注释掉。
- 用法:
-
keepalive_timeout
指令:- 用法:
keepalive_timeout <timeout>;
- 描述:设置保持客户端连接的超时时间,单位是秒。
- 示例:
keepalive_timeout 65;
设置超时时间为 65 秒。
- 用法:
-
gzip
指令:- 用法:
gzip <on|off>;
- 描述:启用或禁用 gzip 压缩。
- 示例:
#gzip on;
默认注释掉。
- 用法:
-
include
指令- 用法:
include <file|directory>;
- 描述:include 指令用于包含其他配置文件或目录中的所有配置文件。这可以帮助将配置文件分割成更小的部分,以便于管理和维护。
- 示例:
include /etc/nginx/mime.types;
:包含 MIME 类型配置文件。
include /etc/nginx/conf.d/*.conf;
:包含/etc/nginx/conf.d/
目录下的所有以 .conf 结尾的配置文件。
- 用法:
可能改动的部分:
keepalive_timeout 65;
默认设置为 65 秒,适用于大多数情况。
对于高并发的场景,可以适当调低以减少资源占用。
tcp_nopush on;
通常注释掉,如果启用,可以优化数据传输,尤其是在发送大文件时。
启用
tcp_nopush
后,Nginx 会尝试将数据块一次性发送到网络,而不是逐个包地发送,从而减少包的数量,提高传输效率。通常与
sendfile on;
一起使用。启用sendfile
后,数据在内核空间中直接从一个文件描述符传输到另一个文件描述符,避免了在用户空间和内核空间之间的多次拷贝,从而提高了传输效率。
gzip on;
通常开启后,可以启用 gzip 压缩以减少传输数据量,提高传输速度。
启用后还需配置
gzip_types
和其他参数,以确保正确压缩所需的文件类型。如http { gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; }
其他 gzip 配置选项:
gzip_min_length
:设置压缩的最小文件大小。gzip_comp_level
:设置压缩级别(1-9),级别越高压缩率越大,但消耗的 CPU 资源更多。gzip_buffers
:设置用于存储压缩结果的缓冲区大小。gzip_vary
:设置Vary: Accept-Encoding
响应头,指示代理服务器和浏览器缓存可以根据请求的Accept-Encoding
头进行不同的缓存。Gzip 压缩是通过压缩算法(如 DEFLATE)将 HTTP 响应内容压缩成更小的体积,然后再发送给客户端。解压缩的过程是nginx和浏览器自动完成的。
性能优化建议
-
增加
worker_connections
:- 提高每个工作进程的最大连接数可以显著提升 Nginx 的并发处理能力。
- 需要确保系统的文件描述符限制足够高。
-
启用
gzip
压缩:-
减少传输数据量,尤其适用于文本类型的资源(如 HTML、CSS、JavaScript)。
-
配置示例:
nginx
复制代码
gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
-
-
优化
keepalive_timeout
:- 在高并发情况下,适当调低 keepalive 超时时间以减少长时间占用连接资源。
-
使用
tcp_nopush
和tcp_nodelay
:- 对于需要优化数据传输性能的场景,可以启用
tcp_nopush
和tcp_nodelay
。
- 对于需要优化数据传输性能的场景,可以启用
2. default.conf
好的,让我们对 default.conf
文件的每一行进行解析:
server
块
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
基本设置
-
server { ... }
:- 定义一个虚拟服务器块,包含服务器的配置。
-
listen 80;
:- 监听 IPv4 的 80 端口,用于处理 HTTP 请求。
-
listen [::]:80;
:- 监听 IPv6 的 80 端口,用于处理 HTTP 请求。
-
server_name localhost;
:- 定义服务器的名称为
localhost
,用于匹配请求的 Host 头。
- 定义服务器的名称为
日志设置
#access_log /var/log/nginx/host.access.log main;
:- 配置访问日志的路径和格式,此处被注释掉。如果启用,将使用
main
日志格式记录访问日志。
- 配置访问日志的路径和格式,此处被注释掉。如果启用,将使用
根路径设置
-
location / { ... }
:- 配置根路径(即所有请求)的处理方式。
-
root /usr/share/nginx/html;
:- 指定请求的根目录为
/usr/share/nginx/html
。
- 指定请求的根目录为
-
index index.html index.htm;
:- 指定默认的索引文件为
index.html
或index.htm
。
- 指定默认的索引文件为
4. 反向代理
正向代理是代理客户端,客户端对于服务端来说是不可见的。
反向代理是代理服务端,服务端对于客户端来说是不可见的。
1. 模拟3个Web
docker pull python:3.9-slim
在桌面或任意地方新建app.py,内容为
from flask import Flask
import os
app = Flask(__name__)
@app.route('/')
def hello():
return f"Hello from the backend server running on port {os.environ.get('PORT')}!"
if __name__ == "__main__":
app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 5000)))
启动3个python容器,模拟3个web服务。
C:\Users\mumu\Desktop>docker run --name web1 -d -e PORT=8081 -p 8081:8081 -v /c/Users/mumu/Desktop/app.py:/app/app.py python:3.9-slim sh -c "pip install flask && python /app/app.py"
ab2ded77eafa82fbf4027f5714e5cb71bcb9775696f0e8c5423a70a7916a80ac
C:\Users\mumu\Desktop>docker run --name web2 -d -e PORT=8082 -p 8082:8082 -v /c/Users/mumu/Desktop/app.py:/app/app.py python:3.9-slim sh -c "pip install flask && python /app/app.py"
e6c5321ea3926157dc2f2d9ed38df53c715da51c496c5ff0e7ff0c4e68c85696
C:\Users\mumu\Desktop>docker run --name web3 -d -e PORT=8083 -p 8083:8083 -v /c/Users/mumu/Desktop/app.py:/app/app.py python:3.9-slim sh -c "pip install flask && python /app/app.py"
f0bea8ac956af515fe35159fe94c86e919dfd566b782d06641472621a6299e26
需要保证nginx和3个python在同一个docker网络中,默认应该都是bridge。
2. 链接
使用docker inspect bridge
查看刚才3个容器的ip。然后修改nginx的default.conf
文件。
upstream backend {
server 172.17.0.3:8081;
server 172.17.0.4:8082;
server 172.17.0.5:8083;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /app {
proxy_pass http://backend/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
-
upstream backend
:定义了一个名为backend
的上游服务器组。 -
location /app { ... }
:配置如何处理以/app
开头的所有请求。
proxy_pass http://backend/;
:将这些请求代理到上游服务器组backend
。请求的路径/app
的前缀将被去除,然后传递给上游服务器。例如,/app/foo
将被代理为/foo
。
重启服务。
访问localhost/app
并多次刷新试试。
5. 负载均衡
在不断刷新页面会发现,反向代理是以“轮询”的方式,将请求分发到3个web服务之一的。
除了轮询之外,还有以下方式。
1. 加权轮询,Weighted Round Robin
可以为不同的服务器设置权重,权重越高,服务器被请求的概率越大。
upstream backend {
server 172.17.0.3:8081 weight=3;
server 172.17.0.4:8082 weight=2;
server 172.17.0.5:8083 weight=1;
}
weight默认为1 。
2. 最少连接,Least Connections
将请求分发给当前连接数最少的服务器,适用于处理时间长、连接占用多的请求。
upstream backend {
least_conn;
server 172.17.0.3:8081;
server 172.17.0.4:8082;
server 172.17.0.5:8083;
}
3. IP哈希,IP Hash
根据客户端 IP 地址进行哈希计算,保证同一客户端的请求总是转发到同一台服务器,适用于会话保持。
upstream backend {
ip_hash;
server 172.17.0.3:8081;
server 172.17.0.4:8082;
server 172.17.0.5:8083;
}
4. 哈希,Hash
根据自定义的键值进行哈希计算来分发请求。
upstream backend {
hash $request_uri;
server 172.17.0.3:8081;
server 172.17.0.4:8082;
server 172.17.0.5:8083;
}
可以使用以下变量作为键值:
$remote_addr
:客户端 IP 地址$request_uri
:请求的 URI$http_cookie
:请求的 Cookie
ip_hash
和hash $remote_addr
一样都可以实现同一个客户端的请求分配到同一个后端服务器。但是一般这种情况使用前者更多。
6. HTTPS
首先要安装有openssl,然后创建一个存放证书和私钥的文件夹,比如mkdir C:\nginx\ssl
执行
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout C:\nginx\ssl\nginx-selfsigned.key -out C:\nginx\ssl\nginx-selfsigned.crt
按问题填写信息,就可以。
得到2个文件后,复制到容器中,比如/etc/nginx/ssl
目录下,然后再default.conf中添加一个server块,如下
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/ssl/nginx-selfsigned.crt;
ssl_certificate_key /etc/nginx/ssl/nginx-selfsigned.key;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /app {
proxy_pass http://backend/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
打开浏览器访问https://localhost
7. 虚拟主机
一个server块就是一个虚拟主机。
新建一个conf文件和default.conf同一目录。
upstream backend2 {
server 172.17.0.3:8081 weight=2;
server 172.17.0.4:8082 weight=2;
server 172.17.0.5:8083 weight=6;
}
server {
listen 81;
listen [::]:81;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /app {
proxy_pass http://backend2/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
重启服务,浏览器访问http://localhost:81/app
。
利用这种方式,我们可以在同一台机器上部署多个网站。