Nginx基本使用
1.Nginx简介
Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。其开发的最初目是为了解决C10K问题,即服务器同时处理10000个并发连接(10000 concurrent connection),由于其性能优异在开发出来后得到了广泛使用。
2.Nginx安装
- 包管理器安装,以debian为例:
sudo apt install nginx
- 编译安装,可以修改配置或源码,进行深度定制:
./configure ... # 预编译,进行配置的自定义
make # 编译
make install # 安装
- Docker安装,适合轻度使用:
docker pull nginx
docker run -d --name nginx -p 80:80 --restart=always nginx
3.Nginx服务启停
3.1 服务启动
在服务开启前,我们首先需要检查一下80端口是否已被占用:
lsof -i :80
如果返回为空,那么就可以通过nginx
命令启动,没有任何提示消息就表示已经启动成功;如果返回非空,那么我们就需要确定,端口被什么应用所占有,这里有两种情况:
- 通过Docker或(部分)包管理器安装,nginx后台进程会自动启动,这个时候可以查看占有端口的进程名或者打开ip:80来进行排查;
- 端口被其它进程所占用,通过进程名确定对应服务,通过修改对应配置来避免端口冲突,尽量让nginx能够占有80端口。
3.2 服务查看
nginx启动后会作为一个后台进程一直运行,可以通过:
ps -ef | grep nginx
来查看对应进程的状态,这里我们可以看到共有一主二从三个进程:
其中主进程主要负责读取配置文件,协调和管理worker进程;后者负责具体处理实际的请求,worker进程的数量可以通过配置文件来调整。
3.3 服务控制
nginx -V # 查看nginx安装目录,编译参数,配置文件目录等信息
nginx -s signal # 控制命令,signal指代下述命令
quit # 停止
stop # 立即停止
reload # 重载配置文件
reopen # 重新打开例子文件
4. 静态站点部署
通过nginx -V
找到配置文件目录并打开后,我们可以看到其中包含了一些基本信息,其中比较重要的是下述三个部分:
- 全局块:
user www-data;
worker_processes auto;
用来配置一些全局信息,例如worker进程数量等等(auto表示和服务器内核数量一致);
2. events块:
events {
worker_connections 768;
# multi_accept on;
}
用来配置服务器和客户端连接的一些配置,例如worker_connections一个worker进程可以接受多少个客户端连接;
3. http块:
http {
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
在较早的nginx本吧中,虚拟主机通常是直接配置在nginx.conf文件下的,当域名/站点较多时难以配置和管理;后期的版本对这种操作进行了规范化,所有虚拟主机的配置放在安装目录的sites-enabled
文件夹下,通过include自动导入,从而进行一对一管理和配置。初始状态下里面会有一个default站点配置,部分配置参数如下:
server {
# 端口配置
listen 80 default_server;
listen [::]:80 default_server;
# 页面配置
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
# 站点配置
server_name _;
}
如果只是想要部署一个静态站点,例如hexo或hugo博客,可以直接将root目录配置为对应的public目录,这样当生成静态文件后就可以直接通过nginx服务器进行访问。
5. 反向代理和负载均衡
反向代理:当我们访问一个网站时,其后可能是成千上万台服务器,但是对外暴露的只有一个域名;我们对网站的所有请求都会被转发(负载均衡)到后面的服务器上,从而隐藏了真实的服务器ip地址、端口等信息。这里的代理服务器代理的是服务端。
5.1 服务器配置
我们可以使用go来写一个简单的服务器代码,从命令行中读取端口号并在页面中显示进程id:
package main
import (
"flag"
"fmt"
"net/http"
"os"
"strconv"
)
func main() {
// Define a command line flag for the port number with a default value.
portFlag := flag.Int("port", 8080, "Port to run the server on")
flag.Parse() // Parse the flags
// Convert the port number to a string
port := strconv.Itoa(*portFlag)
// Define a handler function
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// Get the process ID
pid := os.Getpid()
// Write the process ID to the response
fmt.Fprintf(w, "Server process ID: %d", pid)
})
// Start the server
fmt.Printf("Starting server on port %s\n", port)
if err := http.ListenAndServe(":"+port, nil); err != nil {
fmt.Printf("Error starting server: %s\n", err)
os.Exit(1)
}
}
使用方式如下:
go run server.go -port=YOUR_DESIRED_PORT
为例能够达到反代的效果,我们先通过tmux在8080-8082端口上启动三个服务器实例,然后修改nginx配置文件。
5.2 反向代理
首先我们在安装目录下的/conf.d
文件夹中新建upstream.conf
配置文件,注意这个目录下的配置文件会被包含在http块中,因此我们直接在里面写反向代理的配置即可:
upstream goserver {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
upstream属于handler,只是他不产生自己的内容,而是通过请求后端服务器得到内容,所以才称为upstream(上游)。随后我们需要将网站的80端口指向goserver,这样我们就可以进行访问和确认:
- 在sites-available中创建配置goServer:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://goserver;
}
}
- 删除sites-enabled下的default,创建一个新的软链接指向刚才创建的配置文件:
rm default
ln -s ../sites-available/goServer ./goServer
- 最后nginx重载配置文件,就可以通过ip访问网址进行查看了:
nginx -s reload
5.3 负载均衡
在上述配置下,所有请求默认会以轮询的方式分配给配置的三个服务器,有些情况下我们会有以下需求:
- 不同服务器之间的性能不一,我们想要性能强的服务器接受和处理更多请求,这时候我们就可以配置权重:
upstream goserver {
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
权重越高的server接受到的请求就越多;
2. 对于需要服务器本地存储session的情况,我们会希望一个ip的所有请求都发送到同一个server中,这时候就可以用到ip_hash:
upstream goserver {
ip_hash;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
除此之外,还有许多其它的可配置项,具体可以参照官方文档进行学习和配置。nginx官方文档
6. HTTPS配置
首先,我们需要有个域名,之后在域名的基础上申请SSL证书并进行配置。这里推荐一个免费的证书颁发机构:Let's Encrypt。此处通过Let's Encrypt官方推荐的Certbot进行证书颁发和自动续期,具体步骤见:官方文档。在网址中选择自己的系统+Nginx后,会生详细的安装和配置命令,只需一步步执行即可,下为Debian+Nginx的配置流程(root权限下):
# 1. 安装snapd
apt install snapd
snap install core
# 2. 安装certbot
sudo apt-get remove certbot
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
# 3. (在安装目录下)修改nginx配置文件,见二级域名绑定到server上
cd sites-enabled
nano goServer # 修改server_name xxx.xxx.xxx;
# 4. 申请证书,按提示进行
certbot --nginx
# 5. 查看自动续期的定时任务(Debain下)
systemctl list-timers # 存在snap.certbot.renew.timer
全部流程走完之后,HTTPS就已经配置成功了,可以通过网址访问进行测试。反过头来,我们再看看certbot为我们配置了什么从而启用了HTTPS:
- nginx.conf
# SSL可选的加密协议
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
# 优先使用服务端的密码套件
ssl_prefer_server_ciphers on;
- sites-enabled/goServer
server {
# 监听443端口并启用SSL
listen 443 ssl;
# 指定SSL证书和密钥的位置
ssl_certificate /etc/letsencrypt/live/xxx.xxx.xxx/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxx.xxx.xxx/privkey.pem;
# Certbot推荐的SSL配置,包含密码套件、session缓存、session过期时间等
include /etc/letsencrypt/options-ssl-nginx.conf;
# Diffie-Hellman组的参数,这是提高SSL连接安全性的一种方式
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
# HTTP服务器配置,用于重定向到HTTPS
if ($host = xxx.xxx.xxx) {
return 301 https://$host$request_uri;
}
# 指定在80端口进行监听
listen 80;
server_name xxx.xxx.xxx;
return 404;
}
到此,nginx的基本操作都过了一遍,如果想要在一台主机上配置多个网站,只需要(1)在sites-available新建多个虚拟主机文件,(2)在其中配置server块(注意端口和server_name至少有一个要不一样),(3)软链接到sites-enabled,(4)最后nginx -s reload
就行了。