nginx入门就看这篇文章 万字整理

什么是nginx

Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器

Nginx是一款轻量级的Web 服务器/反向代理服务器,处理高并发能力是十分强大的,并且支持热部署,启动简单,可以做到7*24不间断运行

正代和反代

学习nginx,最重要的就是反向代理

安装nginx

直接安装

初学者可以尝试这种模式

yum install -y nginx

docker安装

docker pull nginx:latest

docker run -itd --name nginx -p 80:80 nginx:latest

用docker的话,就把配置文件和目录映射出来,方便修改

常用命令

# 开启服务
nginx

# 快速停止
nginx -s stop

# 有序停止
nginx -s quit

# 重启服务:
nginx -s reload

# 检查配置文件是否有语法操作
nginx -t

nginx.conf

nginx默认配置文件

一般在/usr/local/nginx/conf/nginx.conf

nginx.conf由多个块组成,最外面的块是main,main包含Events和HTTP,HTTP包含upstream和多个Server,Server又包含多个location

user  nginx;  # 指定nginx进程的运行用户
worker_processes  auto; # 指定Nginx要开启的进程数,每个Nginx进程平均耗费10M~12M内存。建议指定和CPU的数量一致即可。

error_log  /var/log/nginx/error.log notice; # 用来定义全局错误日志文件。日志输出级别有debug、info、notice、warn、error、crit可供选择,其中,debug输出日志最为最详细,而crit输出日志最少。
pid        /var/run/nginx.pid; # 用来指定进程pid的存储文件位置


events {
    worker_connections  1024;  # 用于定义Nginx每个进程的最大连接数,默认是1024
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;   # 这里设定默认类型为二进制流,也就是当文件类型未定义时使用这种方式,例如在没有配置PHP环境时,Nginx是不予解析的,此时,用浏览器访问PHP文件就会出现下载窗口。

    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和tcp_nodelay两个指令设置为on用于防止网络阻塞;

    keepalive_timeout  65;  # 设置客户端连接保持活动的超时时间。在超过这个时间之后,服务器会关闭该连接;


    include /etc/nginx/conf.d/*.conf;  # 导入其他的配置文件,注意include所在的位置
}

main(全局设置)、server(主机设置)、upstream(负载均衡服务器设置)和 location(URL匹配特定位置的设置)。

  • main块设置的指令将影响其他所有设置;
  • server块的指令主要用于指定主机和端口;
  • upstream指令主要用于负载均衡,设置一系列的后端服务器;
  • location块用于匹配网页位置。

localtion

URL地址匹配是进行Nginx配置中最灵活的部分。 location支持正则表达式匹配,也支持条件判断匹配,用户可以通过location指令实现Nginx对动、静态网页进行过滤处理

我这里准备了一个html文件,html文件引入了图片

然后配置文件如下:

server {
    listen 80;

    location / {
        root /opt/nginx_study/html; # 根目录
        index index.html; # 默认显示的页面
    }
}

此时访问服务器ip就可以正常看到页面和图片

注意啊,在html引入图片是相对路径,如果你这样写

<img src="/html/image/1.jpg" alt="">
<img src="/html/image/2.jpg" alt="">

不改nginx的情况下,页面上能看到图片吗?

答案是肯定的,肯定看不到的

那我们可以配置一下图片的访问路径

server {
    listen 80;

    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
        root /opt/nginx_study;
    }
    
    location / {
        root /opt/nginx_study/html; # 根目录
        index index.html; # 默认显示的页面
    }
}

或者

server {
    listen 80;

    location /html/ { # 后面没有/就会重定向
        root /opt/nginx_study;
        index image/1.jpg;  # 直接访问这个路径,会显示这个图片
    }
    location / {
        root /opt/nginx_study/html; # 根目录
        index index.html; # 默认显示的页面
    }


}

alias

Nginx中配置文件路径有两种方式,一种是root一种是alias

例如一个项目里面,有两个html文件要配置路由去访问

目录如下

html
    html1
       index.html
    html2
       index.html

我想实现 访问127.0.0.1:80就是 访问html1下的index.html

访问127.0.0.1:80/xxx就是 访问html2下的index.html

如果这样写,会发现/xxx/怎么也到不了/html2那里

server {
    listen 80;

    location / {
        root /opt/nginx_study/html/html1;
        index index.html;
    }
     location /xxx/ {
        root /opt/nginx_study/html/html2/;  # 会把/xxx/的路径拼接上
        index index.html;
    }
}

所以就有了路径别名

这样就可以解决这个问题了

server {
    listen 80;

    location / {
        root /opt/nginx_study/html/html1;
        index index.html;
    }
     location /xxx/ {
        alias /opt/nginx_study/html/html2/;  # 只会把/xxx/后面的路径拼接过来
        index index.html;
    }
}

域名配置

server_name

如果你的项目是用ip访问的话,这个可以不写

但是如果你的服务器上要跑很多服务,并且都想使用80端口去访问

那就使用域名

通过访问不同的子域名来访问不同的服务

准备三个目录,方便让三个子域名访问

因为演示是在内网环境,没有真正的域名可以用

所以我们只能修改访问者的hosts文件,将上面三个域名执行到 目标服务器上

例如我现在的hosts文件

192.168.100.185 doc.fengfengzhidao.com
192.168.100.185 news.fengfengzhidao.com
192.168.100.185 video.fengfengzhidao.com

然后配置nginx配置文件

server {
    listen 80;
    server_name doc.fengfengzhidao.com;

    location / {
        root /opt/nginx_study/html/doc.fengfengzhidao.com;
        index index.html;
    }
}
server {
    listen 80;
    server_name news.fengfengzhidao.com;

    location / {
        root /opt/nginx_study/html/news.fengfengzhidao.com;
        index index.html;
    }
}
server {
    listen 80;
    server_name video.fengfengzhidao.com;

    location / {
        root /opt/nginx_study/html/video.fengfengzhidao.com;
        index index.html;
    }
}

测试

C:\Users\枫枫>curl http://doc.fengfengzhidao.com
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
doc.fengfengzhidao.com
</body>
</html>


C:\Users\枫枫>curl http://news.fengfengzhidao.com
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
news.fengfengzhidao.com
</body>
</html>


C:\Users\枫枫>curl http://video.fengfengzhidao.com
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
video.fengfengzhidao.com
</body>
</html>
其他匹配模式

server_name 中支持通配符 "*", 但需要注意的是通配符不能出现在域名的中间,只能出现在首段或尾段

server_name 中可以使用正则表达式,并且使用 ~ 作为正则表达式字符串的开始标记

有些博客网站,用户创建博客之后就会得到一个自己的专属博客,我们可以使用通配符来实现这个修改

server {
    listen 80;
    server_name *.bolg.fengfengzhidao.com;

    location / {
        root /opt/nginx_study/html/doc.fengfengzhidao.com;
        index index.html;
    }
}

也可以使用正则表达式

这样就只能 zhangsan lisi wangwu三个访问

server {
    listen 80;
    server_name ~^(zhangsan)|(lisi)|(wangwu).bolg.fengfengzhidao.com$;

    location / {
        root /opt/nginx_study/html/doc.fengfengzhidao.com;
        index index.html;
    }
}

当然,前端肯定要获取当前的子域名是什么,然后发给后端查询是否有这个用户

我们的hosts文件

192.168.100.185 blog.fengfengzhidao.com
192.168.100.185 zhangsan.blog.fengfengzhidao.com
192.168.100.185 lisi.blog.fengfengzhidao.com
192.168.100.185 wangwu.blog.fengfengzhidao.com
192.168.100.185 fengfeng.blog.fengfengzhidao.com

认证

经常能看到这种输入用户名密码才能访问的网页

这种效果是怎么实现的呢

使用htpasswd生成特定的密码文件

yum install httpd-tools -y

这里我以test用户,密码123456为例

htpasswd -c  /opt/nginx_study/auth/htpasswd  test

nginx配置认证

server {
    listen 80;
    
    location / {
      # 开启功能模块,关闭为off
        auth_basic on;
        # 指定密码配置文件
        auth_basic_user_file /opt/nginx_study/auth/htpasswd;
        root /opt/nginx_study/html; # 根目录
        index index.html; # 默认显示的页面
    }

}

如果是用curl访问

curl -u test:123456 http://127.0.0.1

proxy_pass

这个就是nginx的重头戏了,nginx的代理

一般是针对特定的路由,代理到后端服务器上

例如我这里写了一个程序,匹配全部的路径,然后打印出来

package main

import (
  "encoding/json"
  "flag"
  "fmt"
  "github.com/gin-gonic/gin"
)

var name *string

// handler
func handler(c *gin.Context) {
  byteData, _ := json.Marshal(c.Request.Header)
  fmt.Println(string(byteData))
  c.String(200, fmt.Sprintf("%s %s name:%s", c.Request.URL.Path, c.ClientIP(), *name))
  return
}

func main() {
  addr := flag.String("addr", ":8080", "addr")
  name = flag.String("name", "default", "name")
  flag.Parse()
  router := gin.Default()
  router.GET("", handler)
  fmt.Println("服务运行中...")
  fmt.Printf("服务运行在:%s \n", *addr)
  router.Run(*addr)
}


build.bat

set GOOS=linux
go build -o main
set GOOS=windows

然后将编译好的文件,放在服务器上运行

然后配置proxy_pass

server {
    listen 80;

    location /a1/ {  # 匹配/a1/开始,将/a1/之后的加到/之后
        proxy_pass http://127.0.0.1:8080/;
    }
    location /a2/ {   # 匹配/a2/开始,将匹配的路径加到/之后,直观感受就是把被匹配的路径加上了
        proxy_pass http://127.0.0.1:8080;
    }
    location /b1/ {
        proxy_pass http://127.0.0.1:8080/xxx/;
    }
    location /b2/ {
        proxy_pass http://127.0.0.1:8080/xxx;
    }
}

这里这个路径会有绝对路径和相对路径的说法,演示一下就清楚了

请求路径                              实际到后端的路径
/a1/                                     /
/a1/123                                  /123

/a2/                                     /a2/
/a2/123                                  /a2/123

/b1/                                     /xxx/
/b1/123                                  /xxx/123

/b2/                                     /xxx
/b2/123                                  /xxx123

携带原始ip

这个时候,你会发现,我请求192.168.100.185这个服务器ip

但是在服务内部接收到的ip全是127.0.0.1,这是为什么呢

我们都知道,nginx的proxy就是代理,将源用户的请求代理到目标服务器上,也就是请求者变成了nginx

我们只需要将源请求的标识ip的特征,一起代理过去就行

主要配置一个特殊的请求头就可以了

server {
    listen 80;
    # proxy_set_header X-Real-IP $remote_addr; # 加在这里也可以

    location /a1/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://127.0.0.1:8080/;
    }
}

负载均衡

nginx应用场景之一就是负载均衡。在访问量较多的时候,可以通过负载均衡,将多个请求分摊到多台服务器上,相当于把一台服务器需要承担的负载量交给多台服务器处理,进而提高系统的吞吐率;另外如果其中某一台服务器挂掉,其他服务器还可以正常提供服务,以此来提高系统的可伸缩性与可靠性。

后端启动两个服务

./main -addr 127.0.0.1:8080 -name s1
./main -addr 127.0.0.1:8081 -name s2

upstream myapp1 {
  server 127.0.0.1:8080;
  server 127.0.0.1:8081;
}


server {
    listen 80;

    location /api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://myapp1/;
    }
}

然后访问 服务器ip:80/api/

你会发现分别将请求打到不同的后端服务上了

此时它们的权重是一样的

nginx给我们提供了不同的权重模式

轮询(Nginx自带、默认)

该策略是Nginx默认的负载均衡策略,每一个客户端请求按时间顺序轮流分配到不同的服务器上,如果后端服务不可以用,会自动过滤掉。

weight 权重(Nginx自带)

upstream myapp1 {
  server 127.0.0.1:8080 weight=1;  # 打中的比例是 1/3
  server 127.0.0.1:8081 weight=2;  # 打中的比例是 2/3
}

ip_hash(Nginx自带)

ip_hash是将每个请求按照访问ip的hash结果进行分配,这种方式可以保证同一个用户会固定访问一个后端服务器。优点:可以保证session会话,解决服务器之间session不能共享的问题。

upstream myapp1 {
  ip_hash;
  server 127.0.0.1:8080;
  server 127.0.0.1:8081;
}


server {
    listen 80;

    location /api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://myapp1/;
    }
}

least_conn(Nginx自带)

将请求转发给连接数较少的后端服务器。每个后端服务器配置可能不同,处理的请求也有可能不同,对于处理的请求有快有慢,least_conn是根据后端服务器的连接情况,动态的选择连接数量较少的一台服务器来处理当前的请求。

upstream myapp1 {
    least_conn;
  server 127.0.0.1:8080;
  server 127.0.0.1:8081;
}


server {
    listen 80;

    location /api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://myapp1/;
    }
}

nginx限制措施

黑名单

nginx的黑名单功能可以直接在nginx层面拦截恶意ip,让它到不了后端服务

被拦截之后的效果就是这样

它的配置也很简单

server {
    listen 80;
#     deny 192.168.100.113;  # 可以放在 server块

    location / {
        root /opt/nginx_study/html/;
        index index.html;
    }

    location /yyy/ {
        deny 192.168.100.113; # 也可以放在location块中
        alias /opt/nginx_study/html/;
        index index.html;
    }
}

deny 这个配置也是不挑地方的,可以放在不同的作用域中

也可以专门用一个文件去存放黑名单,只需要在不同的地方include即可,如下

black.conf

deny 192.168.100.113;

nginx.conf

server {
    listen 80;

    location / {
        root /opt/nginx_study/html/;
        index index.html;
    }

    include /opt/nginx_study/black.conf;
}

白名单

allow,一般和deny 连用

如下,只允许192.168.100.113访问,其他ip访问则被拒绝

server {
    listen 80;

    allow 192.168.100.113;
    deny all;

    location / {
        root /opt/nginx_study/html/;
        index index.html;
    }
}

UA黑名单

map $http_user_agent $bad_user_agent {
        default         0;
        ~*curl           1;
        ~*wget           1;
        ~*Unicornscan    1;
        ~*sqlmap         1;
        ~*nessus         1;
        ~*netsparker     1;
    }

server {
    listen 80;

     if ($bad_user_agent) {
        return 404;
    }

    location / {
        root /opt/nginx_study/html/;
        index index.html;
    }
}

注意,这个map只能写在server的外面

此时,通过 curl直接访问会得到 404

C:\Users\枫枫>curl 192.168.100.185
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.13.7</center>
</body>
</html>


C:\Users\枫枫>curl --user-agent sss 192.168.100.185
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
你会
</body>
</html>

Referer黑名单

map $http_referer $bad_referer {
        default         0;
        ~*evil\.com     1;
        ~*xxx\.com      1;
        ~*yyy\.com      1;
    }

server {
    listen 80;

     if ($bad_referer) {
        return 404;
    }

    location / {
        root /opt/nginx_study/html/;
        index index.html;
    }
}
C:\Users\枫枫>curl 192.168.100.185
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
你会
</body>
</html>


C:\Users\枫枫>curl -e xxx.com 192.168.100.185
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.13.7</center>
</body>
</html>

请求频率黑名单

黑客可以通过发送大量请求来模拟各种攻击,在一定时间内发送的请求达到某个阈值后则会被判定为恶意请求。实现请求频率限制也是黑名单的一种应用场景

这是一分钟内请求5次的示例

limit_req_zone $binary_remote_addr zone=perip:10m rate=5r/m;


server {
    listen 80;

    limit_req zone=perip burst=5 nodelay;

    location / {
        root /opt/nginx_study/html/;
        index index.html;
    }
}

这是一秒钟内请求5次的示例

limit_req_zone $binary_remote_addr zone=perip:10m rate=5r/s;


server {
    listen 80;

    limit_req zone=perip burst=10 nodelay;  # 最多可以处理10个并发请求

    location / {
        root /opt/nginx_study/html/;
        index index.html;
    }
}

https配置

自签名ssl证书
openssl genrsa -out private.key 2048
openssl req -new -key private.key  -out cert.csr
openssl x509 -req -in cert.csr -out cacert.pem -signkey private.key

server {
    listen 443 ssl;
    ssl_certificate /opt/nginx_study/ssl/cacert.pem;  # pem的路径
    ssl_certificate_key /opt/nginx_study/ssl/private.key;  # key的路径

    location / {
        root /opt/nginx_study/html/;
        index index.html;
    }
}

因为是自签的,所以浏览器会提示不安全,正常的

云平台的ssl证书

将key和pem文件放到服务器上

server {
    listen 80;  # 将80的请求重定向到443上去
    server_name www.xxx.com;
    return 301 https://$server_name$request_uri; 
}

server {
    listen 443 ssl;
    ssl_certificate /www/server/nginx/www.xxx.com.pem;  # pem的路径
    ssl_certificate_key /www/server/nginx/www.xxx.com.key;  # key的路径
    server_name www.xxx.com;
    
    location / {
        uwsgi_pass   127.0.0.1:8000;  # 这个案例是uwsgi的案例
        include uwsgi_params;
     }
    
    location /static {
        alias  /www/wwwroot/flask_deploy/static;
    }
}

gzip配置

这个配置也是不挑地方的

server {
    listen 80;

    location / {
        gzip on;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
        root /opt/nginx_study/html/;
        index index.html;
    }

     location /xxx/ {
        alias /opt/nginx_study/html/;
        index index.html;
    }
}

参考文档

官网:nginx news

nginx详解:Nginx详解(一文带你搞懂Nginx)-优快云博客

nginx常用命令操作:nginx常用操作命令_nginx命令-优快云博客

8分钟了解nginx:https://zhuanlan.zhihu.com/p/34943332

nginx常用命令和总结:nginx的常用命令和总结 - ministep88 - 博客园

nginx配置文件: Nginx安装及配置文件nginx.conf详解-优快云博客

nginx负载均衡:百度安全验证

nginx server_name: nginx 配置指令之server_name_nginx servername-优快云博客

nginx 黑名单: 如何使用Nginx实现IP黑名单-Nginx-PHP中文网

nginx请求频率限制:https://www.python100.com/html/109613.html

nginx gzip: nginx配置gzip_nginx开启gzip-优快云博客

nginx gzip具体配置: nginx的Gzip配置_nginx gzip 配置-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值