Nginx基本使用

49

1.Nginx简介

Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。其开发的最初目是为了解决C10K问题,即服务器同时处理10000个并发连接(10000 concurrent connection),由于其性能优异在开发出来后得到了广泛使用。

2.Nginx安装

  1. 包管理器安装,以debian为例:
sudo apt install nginx
  1. 编译安装,可以修改配置或源码,进行深度定制:
./configure ... # 预编译,进行配置的自定义
make            # 编译
make install    # 安装
  1. 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

来查看对应进程的状态,这里我们可以看到共有一主二从三个进程:
nginx后台进程
其中主进程主要负责读取配置文件,协调和管理worker进程;后者负责具体处理实际的请求,worker进程的数量可以通过配置文件来调整。

3.3 服务控制

nginx -V        # 查看nginx安装目录,编译参数,配置文件目录等信息
nginx -s signal # 控制命令,signal指代下述命令
    quit    # 停止
    stop    # 立即停止
    reload  # 重载配置文件
    reopen  # 重新打开例子文件

4. 静态站点部署

通过nginx -V找到配置文件目录并打开后,我们可以看到其中包含了一些基本信息,其中比较重要的是下述三个部分:

  1. 全局块:
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,这样我们就可以进行访问和确认:

  1. 在sites-available中创建配置goServer:
server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://goserver;
    }
}
  1. 删除sites-enabled下的default,创建一个新的软链接指向刚才创建的配置文件:
rm default
ln -s ../sites-available/goServer ./goServer
  1. 最后nginx重载配置文件,就可以通过ip访问网址进行查看了:
nginx -s reload

5.3 负载均衡

在上述配置下,所有请求默认会以轮询的方式分配给配置的三个服务器,有些情况下我们会有以下需求:

  1. 不同服务器之间的性能不一,我们想要性能强的服务器接受和处理更多请求,这时候我们就可以配置权重:
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:

  1. nginx.conf
# SSL可选的加密协议
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE

    # 优先使用服务端的密码套件
    ssl_prefer_server_ciphers on;
  1. 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就行了。