首页 > 技术文章 > Linux Web服务器Nginx

mayu-huangdi 2021-12-31 15:40 原文

一、web服务是什么?

image

  web服务是一种服务导向架构的技术,通过标准的Web协议提供服务,目的是保证不同平台的应用服务可以互操作。 根据W3C的定义,Web服务应当是一个软件系统,用以支持网络间不同机器的互动操作。网络服务通常是许多应用程序接口所组成的,它们透过网络,例如国际互联网的远程服务器端,执行客户所提交服务的请求。

二、常见的web服务器软件

apache

官网:https://www.apache.org/

image

  Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中。

nginx

官网:http://nginx.org/

image

  Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

网络模型及其对比

apache使用select模型
nginx使用epoll模型

image

image

image

image

三、Nginx命令

  • -v :打印版本号

    image

  • -V :打印版本号及配置项

    image

  • -t :检查配置文件

    image

  • -T :测试配置文件并启动

  • -q :打印错误日志

  • -s [选项] : 操作进程

    [root@web01 ~]# nginx -s stop # 停止
    [root@web01 ~]# nginx -s quit # 退出
    [root@web01 ~]# nginx -s reopen # 重启
    [root@web01 ~]# nginx -s reload # 重载
    
  • -p :指定nginx的工作目录

  • -e :指定错误日志路径

  • -c : 指定配置文件的路径

  • -g : 设置一个全局的Nginx配置项

    [root@web01 ~]# nginx -g 'daemon off;'
    

四、Nginx配置文件

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   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   html;
        }
    }
}
  1. user :指定nginx启动用户
  2. worker_processes :定义nginx worker进程数
  3. error_log :错误日志路径
  4. pid :pid的存放文件路径
  5. events :模块配置
    • worker_connections :每一个worker进程最多同时接入多少个请求
    • use : 指定Nginx的网络模型(此项默认不需要配置)
  6. http : web服务的模块
    • include : 加载外部的配置项
    • default_type : 如果找不到文件的类型,则按照指定默认类型处理
    • log_format : 定义日志格式
      log_format json '{"@timestamp":"$time_iso8601",'
      '"host":"$server_addr",'
      '"service":"nginxTest",'
      '"trace":"$upstream_http_ctx_transaction_id",'
      '"log":"log",'
      '"clientip":"$remote_addr",'
      '"remote_user":"$remote_user",'
      '"request":"$request",'
      '"http_user_agent":"$http_user_agent",'
      '"size":$body_bytes_sent,'
      '"responsetime":$request_time,'
      '"upstreamtime":"$upstream_response_time",'
      '"upstreamhost":"$upstream_addr",'
      '"http_host":"$host",'
      '"url":"$uri",'
      '"domain":"$host",'
      '"xff":"$http_x_forwarded_for",'
      '"referer":"$http_referer",'
      '"status":"$status"}';
      
      access_log /var/log/nginx/access.log json ;
      
    • sendfile : 高效读取文件
    • keepalive_timeout : 长连接保持连接的最大时间
    • server : 网址模块
      • listen : 监听的端口
      • server_name : 定义域名
      • location : 访问路径
        • root :指定网址路径
        • index:指定网址的索引文件

location

Nginx Location可以控制访问网站的路径, 一个server中可以有多个location配置, 多个location的优先级区如下,

匹配符 匹配规则 优先级
= 精确匹配 1
^~ 以某个字符串开头 2
~ 区分大小写的正则匹配 3
~* 不区分大小写的正则匹配 3
/ 通用匹配,任何请求都会匹配到 4

Nginx模块

image

ngx_http_log_module

该模块以指定的格式写入请求日志,下面是一段官网文档介绍:

image

可以在http, server, location, if in location, limit_except上下文中使用。


附上nginx默认日志配置(/etc/nginx/nginx.conf);

image

简单地说明日志格式化模块中地一些变量,

$remote_addr     # 客户端地址
$remote_user     # 使用auth_basic_module模块定义的用户名
$time_local      # 本地时间
$request         # 客户端请求头信息
$status          # http状态码
$body_bytes_sent # 客户端发送的http响应中包体部分的字节数
$http_referer    # 记录请求的来源地址
$http_user_agent # 访问服务器的操作系统 浏览器
$http_x_forwarded_for # 真实的客户端IP(在反向代理中生效)

[root@web01 nginx]# tail access.log
192.168.15.1 - - [04/Jan/2022:12:25:34 +0800] "GET /mario/sounds/jump.mp3 HTTP/1.1" 404 555 "http://game.xzj.com/mario/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62" "-"

ngx_http_access_module

该模块允许限制对某些客户端地址的访问,下面是一段官网文档介绍:

image

可以在http, server, location, limit_except上下文中使用。
deny表示拒绝,allow表示接受,地址可以是单ip也可以是网段,all表示所有。
规则匹配顺序自上而下,直至匹配到符合条件的第一项停止。

ngx_http_auth_basic_module

该模块允许通过使用"HTTP 基本身份验证"协议验证用户名和密码来限制对资源的访问,下面是官网文档介绍:

image

可以在http, server, location, limit_except上下文中使用。


默认我们访问虚拟机可以直接访问,

image

此时我们下载httpd-tools软件,使用命令htpasswd -c [密码文件目录] [用户名]创建密码文件。

htpasswd -c /etc/nginx/auth test
cat /etc/nginx/auth

image

image

接着配置 /etc/nginx/nginx.conf 文件,加入以下配置项;

image

重启nginx访问虚拟机,发现需要您输入用户名密码,如果取消显示401;

image

image

ngx_http_autoindex_module

该模块处理以斜杠字符 ('') 结尾的请求,并生成一个目录列表。通常,当ngx_http_index_module模块找不到索引文件时,会将请求传递给模块,下面是官网文档介绍:

image
image

可以在http,server,location上下文中使用。

autoindex

ngx_http_auth_basic_module模块我们设置用户及密码限制访问,在此基础上我们继续修改一些配置项,如下;

image

修改好后访问通过浏览器访问虚拟机,输入用户和密码显示如下,

image

autoindex_exact_size

autoindex_exact_size配置项默认是 on,指定文件在目录列表下的大小是否以字节显示。在opt目录下创建文件夹test,使用 dd 命令创建一个大文件hello.txt,显示如下;

image

我们设置autoindex_exact_size off;,然后重载配置文件重新访问;

image

image

autoindex_format

autoindex_format 指定目录下的文件及文件夹显示格式,格式可以是 html | xml | json | jsonp,默认是autoindex_format html;

此处测试下json格式,改动如下;

image

image

autoindex_localtime

autoindex_localtime指定目录列表中的时间是应以本地时区输出还是UTC时间。默认是autoindex_localtime off;

image

接着我们开启本地时间autoindex_localtime on;,效果如下;

image

ngx_http_stub_status_module

ngx_http_stub_status_module该模块提供对基本状态信息的访问,下面是官网文档介绍:

image

可以在server,location上下文中使用。

我们在/etc/nginx/nginx.conf配置文件server中添加新location,

image

完成后重载配置文件,访问192.168.15.7/basic_status

image


根据上图显示内容,介绍字段的含义:

Active connections
   当前活动客户端连接数(包括连接数)。Waiting
accepts
   接受的客户端连接总数。
handled
  已处理连接的总数。通常,参数值与未达到某些资源限制(例如,worker_connections限制)时相同。accepts
requests
  客户端请求的总数。
Reading
  nginx 正在读取请求标头的当前连接数。
Writing
  nginx 将响应写回客户端的当前连接数。
Waiting
  等待请求的当前空闲客户端连接数。

ngx_http_limit_conn_module

该模块用于限制每个已定义键的连接数,特别是来自单个 IP 地址的连接数。ngx_http_limit_conn_module并非所有连接都计算在内。仅当连接具有服务器正在处理的请求并且已读取整个请求标头时,才会对连接进行计数。

limit_conn

设置共享内存区域和给定键值允许的最大连接数。当超过此限制时,服务器将在回复请求时返回错误。例如,

limit_conn_zone $remote_addr zone=addr:10m;

server {
    location /download/ {
        limit_conn addr 1;
    }

一次只允许每个 IP 地址连接一个。

ngx_http_limit_req_module

该模块用于限制每个已定义键的请求处理速率,特别是来自单个 IP 地址的请求的处理速率。

limit_req_zone

limit_req_zone设置共享内存区域的参数,该区域将保留各种键的状态。特别是,状态存储当前过多请求数。
使用示例:

limit_req_zone $remote_addr zone=one:10m rate=1r/s;

此处,状态保存在 10 MB 区域"one"中,并且此区域的平均请求处理速率不能超过每秒 1 个请求。

limit_req

设置共享内存区域和请求的最大突发大小。如果请求速率超过为区域配置的速率,则其处理将延迟,以便以定义的速率处理请求。过多的请求会延迟,直到其数量超过最大突发大小,在这种情况下,请求将终止并显示错误。默认情况下,最大突发大小等于零。例如,

http {
    limit_req_zone $remote_addr zone=one:10m rate=1r/s;
    ...
    server {
        ...
        location /search/ {
            limit_req zone=one burst=5;
        }

平均每秒允许不超过 1 个请求,突发不超过 5 个请求。

此处我们可以做个压力测试,发送10000次请求,每次同时发送100次请求;

image

结果显示失败了9994次,是符合我们配置预期的。

部署网站测试

1、将准备好的代码文件放到/opt/mario目录下

image

2、编辑nginx配置文件

server {
        listen       80;
        server_name  game.xzj.com;
        location / {
            root   /opt/mario;
            index  index.html;
        }

image

3、检查配置文件是否正确,并重启nginx

[root@web01 conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@web01 conf.d]# systemctl restart nginx

4、域名解析

在本地 windows目录 C:\Windows\System32\drivers\etc\hosts 下添加域名解析

image
5、访问域名

image

LNMP架构

LNMP是一套技术的组合,L=Linux、N=Nginx、M=MySQL、P=Python

image

首先Nginx服务是不能处理动态请求,那么当用户发起动态请求时, Nginx又是如何进行处理的。

  1. 静态请求:请求的内容是静态文件就是静态请求
    1)静态文件:文件上传到服务器,永远不会改变的文件就是静态文件
    2)html就是一个标准的静态文件
  2. 动态请求:请求的内容是动态的就是动态请求
    1)不是真实存在服务器上的内容,是通过数据库或者其他服务拼凑成的数据

当用户发起http请求,请求会被Nginx处理,如果是静态资源请求Nginx则直接返回,如果是动态请求Nginx则通过uwsgi协议转交给后端的Python程序处理。

uwsgi

image

因为nginx不支持wsgi协议,无法直接调用py开发的webApp。
在nginx+uwsgi+Django的框架里,nginx代理+webServer,uwsgi是wsgiServer,Django是webApp。
nginx接收用户请求,并判定哪些转发到uwsgi,uwsgi再去调用pyWebApp。

uwsgi服务部署

1、安装依赖软件及其软件

yum install python3 libxml* python-devel gcc* pcre-devel openssl-devel python3-devel -y

pip3 install django
pip3 install uwsgi

2、创建应用目录

# 在/opt目录下创建django工程
[root@web01 opt]# cd /opt
[root@web01 opt]# django-admin startproject myapp
# 在django工程目录中创建应用app01
[root@web01 opt]# cd myapp
[root@web01 myapp]# django-admin startapp app01
# 修改配置文件
[root@web01 myapp]# vim myapp/settings.py
ALLOWED_HOSTS = ['*'] # 允许所有ip访问
DATABASES = {} # 数据库此时不配置为空

3、在/opt/myapp/目录下创建uwsgi.ini文件

[root@localhost ~]# vim /opt/myapp/uwsgi.ini
# 配置内容如下
######################################
[uwsgi]
# 端口号
socket            = :8000
# 指定项目的目录
chdir           = /opt/myapp
# wsgi文件路径
wsgi-file       = myapp/wsgi.py
# 模块wsgi路径
module          = myapp.wsgi
# 是否开启master进程
master          = true
# 工作进程的最大数目
processes       = 4
# 结束后是否清理文件
vacuum          = true

4、启动uwsgi

# -d : 以守护进程方式运行
# --ini : 指定配置文件路径
# --uid : 指定uid
[root@web01 myapp]# uwsgi -d --ini uwsgi.ini --uid 666

5、由于uwsgi是tcp连接并不是http连接,我们需要配置下nginx

[root@localhost myapp]# vim /etc/nginx/conf.d/myapp.conf
# 编辑内容如下
server {
    listen 80;
    server_name py.myapp.com;
    location / {
        include uwsgi_params;
        uwsgi_pass 127.0.0.1:8000;
        uwsgi_read_timeout 2;
        uwsgi_param UWSGI_SCRIPT myapp.wsgi;
        uwsgi_param UWSGI_CHDIR /opt/myapp;
        index  index.html index.htm;
        client_max_body_size 35m;
    }
}

6、启动或重启nginx并访问网址

image

推荐阅读