Nginx使用

*

Nginx使用

1.安装

Nginx 在 Windows 下的安装

Nginx( "engine x" )是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP / POP3 / SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。其将源代码以类 BSD 许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011 年 6 月 1 日,nginx 1.0.4 发布。

警告

解压路径不要有空格和中文!例如:C:\ProgramFilesD:\ProgramFiles 就是很好的就选择。

Nginx 只有解压版本,没有安装版。

1. 下载、解压

从官网 http://nginx.org/en/download.htmlopen in new window 下载最新的稳定版。例如:nginx-1.20.2

解压压缩包到 D:\ProgramFiles ,因此,后文的 NGINX_HOME 指的就是 D:\ProgramFiles\nginx-1.20.2

解压后,可到看到如下内容:

 NGINX_HOME
 ├── conf        配置文件目录
 ├── contrib
 ├── docs
 ├── html        类似 tomcat 的 webapps
 ├── logs        日志目录
 ├── temp
 └── nginx.exe   启动程序

其中 conf/nginx.conf 文件是 Nginx 的配置文件,Nginx 启动后占用哪个端口等配置信息就定义在这个文件中。

2. Nginx 的启停

启动 Nginx

在 NGINX_HOME 目录下打开 cmd 命令窗口,输入命令 start nginx 启动 Nginx 或者直接双击 nginx.exe

这里会有一个黑窗口快速地一闪而过,电脑性能强大的同学可能反而看不见,因外太快了...

判断 / 验证 Nginx 是否正在运行

在 cmd 命令窗口输入命令 tasklist /fi "imagename eq nginx.exe" 。你会看到类似如下页面:

 映像名称    PID     会话名      会话#   内存使用
 =========== ======= =========== ======= ============
 nginx.exe   17220   Console     8       7,148 K
 nginx.exe   17660   Console     8       7,508 K

如果显示有 2 条 Nginx 信息则表明有一个 Nginx 正在后台运行中。

如果出现了 4 条、6 条甚至更多的 Nginx 信息,则表明你无意之中启动了多次 Nginx ,此时有多个 Nginx 正在后台运行。这会为你正常使用 Nginx 带来麻烦和错误。

Nginx 的使用

直接在浏览器地址栏输入网址 http://localhost:80open in new window 。你会看到欢迎页面。即,NGINX_HOME 下的 html 目录中的 index.html 内容。

改变 html 目录下的内容就会影响你在 http://localhost:80open in new window 网址所看到的内容。

Nginx 的停止

下述方案有一个小缺陷

以管理员权限打开 cmd 命令行终端,进入到 NGINX_HOME 。在 NGINX_HOME 下打开 cmd 命令行,输入如下 2 条命令之一:

 # 快速停止 nginx 
 nginx -s stop
   
 # 完整有序地停止 nginx
 nginx -s quit

这种停止方式有一个小缺陷在于:它只能停止一个 Nginx 程序。

如果你像上面所说地,有意或无意中开启了多个 Nginx 进程,现在你想关闭所有的 Nginx 进程,那么你就需要不停地执行上述停止命令,直到看到错误信息为止。

如果想依靠用以地解决这个问题,你可使用如下命令一口气关闭掉所有的 nginx ,无论它有多少个进程:

 taskkill /f /t /im nginx.exe

3. 借助 WinSW 启停 Nginx

提示

有一小部分同学操作完全正确,但是仍会注册失败。原因不明,暂时无解决方案。怀疑和 Windows 系统版本有关。

第 1 步:下载 Windows Service Wrapper 工具

WinSW github( .NET 4.6.1 版 )open in new window

将下载好的 WinSW 放到 NGINX_HOME 目录下,并重命名。名字任意,例如:systemctl.exe 。

第 2 步:为 WinSW 创建配置文件

在 NGINX_HOME 下为 WinSW 创建配置文件( 配置文件与 WinSW 程序平级 )。配置文件为 .xml 文件,且名字必须与 WinSW 程序相同。例如:systemctl.xml ,与上面的 systemctl.exe 相呼应。

systemctl.xml 配置文件内容如下:

 <service>
   <id>nginx</id>
   <name>Nginx</name>
   <description>Nginx</description>
 
   <executable>%BASE%\nginx.exe</executable>
 
   <stopexecutable>%BASE%\nginx.exe</stopexecutable>
   <stopargument>-s</stopargument>
   <stopargument>stop</stopargument>
 
   <logpath>%BASE%\logs</logpath>
   <logmode>roll</logmode>
 </service>

在上述的配置文件中,我们「告知」了 WinSW 以什么命令启停 Nginx 。未来,我们不再亲自启停 Nginx ,而是通过 WinSW 间接启停 Nginx 。

第 3 步:安装 Nginx 服务

在 NGINX_HOME 目录下打开 cmd 命令行执行如下命令:

 # 安装服务。开机启动,当前未启动,重启后生效。
 systemctl install
 
      auto  开机启动。当前未启动,重启后生效
    demand  手动启动
  disabled  禁用
  通过 Windows 的 sc 命令调整成手动启动
 sc config nginx start= demand

安装成功后,你可以在 Windows 系统的服务中看到 Nginx 。默认是开机启动,下次你的系统再开机,nginx 就自动启动了。

install 的反向操作是 uninstall ,uninstall 之后在 Windows 服务中就看不到它了。

 # uninstall 的前提是服务已停止
 systemctl uninstall

注意,install 和 uninstall 的操作只用执行一次,在日常使用中并非反复执行( 也无必要 )。

第 4 步:启停 nginx 服务

提示

你在 Windows 的 服务 点点点,也能实现下述命令的功能。就看你偏好哪种方式了。

 # 查看状态
 systemctl status
 
 # 启动服务
 systemctl start
 
 # 停止服务
 systemctl stop

提示当启动不起来时,需要自行查看log目录下的error.log日志

2.使用nginx

1. 反向代理服务器

1.1 概念

由于请求的方向是从客户端发往服务端,因此 客户端 -> 服务端 这个方向是『正向』。

所谓『反向代理服务器』指的就是:Nginx『站』在服务端的角度,分担了服务端的负担,增强了服务端的能力。

在这种情况下,在客户端看来,Nginx + 服务端 整体扮演了一个更大意义上的服务端的概念。

nginx-01

1.2 基于 Nginx 的动静分离方案

对 Nginx 的最简单的使用是将它用作静态资源服务器。

nginx-02

在这种方案种,将 .html.css.js.png 等静态资源放置在 Nginx 服务器上。

将对静态资源的访问流量就分流到了 Nginx 服务器上,从而减轻 Servlet 容器的访问压力。

1.3 基于 Nginx 的前后端分离

随着前端单页应用技术的发展,『前端』从简单的『前端页面』演进成了『前端项目』。

这种情况下,在动静分离方案的基础上进一步延伸出了『更激进』的方案:前后端分离。

nginx-03

1.4 实现原理

要实现前后端分离(涵盖动静分离),这里需要 Nginx 能提供一种能力:请求转发。

在整个过程中,所有的请求首先都是『交到了 Nginx 手里』,有一部分请求是 Nginx 自己能响应的,它就响应了;而另一部分请求则是被 Nginx 转给了 SpringBoot,而等到 Nginx 获得到 SpringBoot 的 JSON 的返回之后,Nginx 再将响应数据回复给客户端。

3.Nginx代理转发规则

所谓『代理』指的就是 Nginx『帮』真正的服务端所接收的请求,那么也就意味着这样的请求,Nginx 最终需要再交给真正的服务端去处理。

3.1 两个需要提前交代的问题

  1. 「减法」问题

    在处理转发请求时,Nginx 常常对 URL 做一个「减法」操作,即,减去 URL 中的协议、IP 和端口部分,然后再使用剩下的部分。例如:

    • URL http://127.0.0.1:8080 做减法后啥,都不剩;

    • URL http://127.0.0.1:8080/ 做减法后,还剩 /

    • URL http://127.0.0.1:8080/api 做减法后,还剩 /api

    • URL http://127.0.0.1:8080/api/ 做减法后,还剩 /api/

  2. 「规则 2 选 1」问题:

    用户的原始 URL 会被 Nginx「加工」成什么样子?请求会被转发到谁那里?有 2 套规则,具体是哪套规则起作用取决于你的 location 中的 proxy_pass 做「减法」后还剩不剩东西?例如

    上面 4 个 URL ,后 3 个 URL 使用同一个规则,而第 1 个 URL 则使用的是另一个规则。

    • URL 1:http://127.0.0.1:8080

    • URL 2:http://127.0.0.1:8080/

    • URL 3:http://127.0.0.1:8080/api

    • URL 4:http://127.0.0.1:8080/api/

3.2 两个 URL 处理规则

下述的 path 是用户请求的「原始路径做减法」之后剩下的内容。

Nginx 会使用两个 URL 处理规则的哪一个来处理用户请求?这取决于你的 proxy_pass 做「减法」之后还剩不剩东西。

  • 规则一:如果『啥都不剩』,转发路径就是 proxy_pass + path

  • 规则二:如果『还剩东西』(哪怕就剩个 /),转发路径是 proxy_pass + (path - location)。

    另外,对于第二个规则,有个配置上的小技巧,如果你的 proxy_pass 是以 / 结尾的( 无论它是长是短 ),那么你的 location 最好也以 / 结尾,以避免不必要的麻烦。

Nginx 的判断逻辑伪代码如下:

/*
 * 根据 `规则一` 和 `规则二` 的不同,它们的使用场景简而言之归纳成一句话:
 * 如果你需要转发路径被 Nginx 「截取掉」一部分,
 * 那么你就使用规则二,否则你就使用规则一。
 */
if (当前请求是否应该被我转发 == true) {  // 取决于 location 的值

    // 这个请求 URL 是 Nginx 收到的请求路径
    String originURL = “…”;                       // 比如:http://127.0.0.1:80/api/login

    // URI 是 URL 的一部分,URI = URL - 协议 - IP - 端口
    String originURI = “…”;                       // 比如:/api/login

    // 转发路径要不要 “砍掉” 一部分
    if ( proxy_pass - 协议 - ip - 端口 == “” ) {    // 规则一:不砍,URI 直接拼接
        return proxy_pass + originUri;              // 比如:http://192.172.0.110/api/login
    } 
    else {                                          // 规则二:URI 会砍掉 location ,再拼接
        String toUri = originUri - location;        // 比如:/api/login - /api/ = login
        return proxy_pass + toUri;                  // 比如:http://192.172.0.110/login
    }
}

补充两点:

  1. 无论如何配置你配置 proxy_pass 的内容最后一定会『完全地』包含在转发、去往的路径中。

  2. location 是否以 / 结尾问题不大,因为 Nginx 会认为 / 本身就是 location 的内容本身( 的一部分 )。

3.3 示例

假设 Nginx 运行在 127.0.0.1 ,它所代理的目标服务在 192.172.3.110 上。

示例一:不需要截取路径中的 /api
假设 Nginx 接收到的请求是 127.0.0.1:8080/api/login

nginx 配置如下:

location /api {
  proxy_pass http://192.172.3.110:8080;
}

用户原始请求的 URL 做减法后的剩下的内容是:/api/login 。

上述配置的 proxy_pass 做减法之后啥都不剩,因此使用上述规则一:proxy_pass + path :

http://192.172.3.110:8080 + /api/login

└──> http://192.172.3.110:8080/api/login

最终 Nginx 会将请求发给 http://192.172.3.110:8080/api/hello 。

注意,一番处理之后,这里的 /api/ 没有被截取掉,仍然还在。

示例二:需要截取路径中的 /api
假设 Nginx 接收到的请求是 127.0.0.1/api/login 。

location /api/ {
    proxy_pass http://192.172.3.110:8080/;
}

用户原始请求的 URL 做减法后的剩下的内容是:/api/login 。

上述配置的 proxy_pass 做减法之后还剩个 / ,因此使用上述规则二:proxy_pass + (path - location) 。

http://192.172.3.110:8080/ + ( /api/login - /api/ )

└──> http://192.172.3.110:8080/login
最终 Nginx 会将请求发给 http://192.172.3.110:8080/login 。

注意,一番处理之后,这里的 /api 被截取掉,还在了。

3.4. 一个完整的 http 配置片段

其中绝大多数内容都是默认配置:

error_log  logs/error.log  info;    # 打开错误日志的 INFO 级别,方便观察错误信息。
...
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;  # TCP 连接存活 65 秒
    server {
        # Nginx 监听 localhost:80 端口
        listen       80;
        server_name  localhost;

        # 访问 URI 根路径时,返回 Nginx 根目录下的 html 目录下的 index.html 或 index.htm
        location / {
            root   html;
            index  index.html index.htm;
        }

        # URI 路径以 /api 开头的将转交给『别人』处理
        location /api {
            proxy_pass http://localhost:8080/api;
        }

        # 出现 500、502、503、504 错误时,返回 Nginx 根目录下的 html 目录下的 50x.html 。
        error_page   500 502 503 504  /50x.html;    
        location = /50x.html {
            root   html;
        }
    }
}

4.Nginx 实现负载均衡

负载均衡( load balance )就是将负载分摊到多个操作单元上执行,从而提高服务的可用性和响应速度,带给用户更好的体验。

1. 负载均衡的配置

通过 Nginx 中的 upstream 指令可以实现负载均衡,再该指令中能够配置负载均衡服务器组。

目前负载均衡有 4 种典型的配置方式。分别是:

#负载均衡方式特点
1轮询方式默认方式。每个请求按照时间顺序逐一分配到不同的后端服务器进行处理。如果有服务器宕机,会自动删除。
2权重方式利用 weight 指定轮循的权重比率,与访问率成正比。用于后端服务器性能不均衡的情况。
3ip_hash 方法每个请求俺早访问 IP 的 hash 结果分配,这样可以使每个方可固定一个后端服务器,可以解决 Session 共享问题。
4第三方模块取决于所采用的第三方模块的分配规则。

在 upstream 指定的服务器组中,若每个服务器的权重都设置为 1(默认值)时,表示当前的负载均衡是一般轮循方式。

2. 准备工作

编写后台(SpringBoot)项目,简单起见,以占用不同的端口的形式启动 2 次,并在返回的信息中返回各自所占用的端口号。

@Value("${server.port}")
String port;

@RequestMapping(“/api/hello”)
public Map<String, String> index(HttpServletRequest request) {
    HashMap<String, String> map = new HashMap<>();
    map.put(“code”, “10086”);
    map.put(“msg”, “success”);
    map.put(“data”, this.port);

    return map;
}

3. 负载:轮循

轮循方式的关键配置如下:

server {
    ...
    location /api {
        proxy_pass http://xxx/api;
        ...

         
        # 解决 upstream 名称携带下划线(_)时,访问 400 问题。
        # proxy_set_header Host $http_host;
    }
}

upstream xxx {
    server 127.0.0.1:8080;
    server 127.0.0.1:9090;
}

上述的配置中有 2 点需要注意的:

  1. upstream 配置项在 http 配置项内,但是在 server 配置项外,它们 3 者整体结构如下( 不要写错地方了 ):

http {                    # http 是爹
    server { ... }        # 它们俩是两儿子
    upstream { ...}
}
  1. 你所配置的 upstream 的 name 是自定义的,但是不要出现 - 号,否则会和 tomcat 有冲突。

你持续访问 http://127.0.0.1/api/hello 你会发现页面的内容会是交替出现 8080 端口和 9090 端口。

4. 负载:加权轮循

加权轮循就是在轮循的基础上,为每个单点加上权值。权值越重的单点,承担的访问量自然也就越大。

upstream xxx {
    server 127.0.0.1:8080 weight=1;
    server 127.0.0.1:9090 weight=2;
}

按照上述配置,9090 端口的服务将承担 2/3 的访问量,而 8080 端口则承担 1/3 的访问量。

将配置改为上述样子并重启 Nginx 后,再持续访问 http://127.0.0.1/api/hello 你会发现 8080 端口和 9090 端口会以 1-2-1-2-... 的次数交替出现。


除了 weight 外,常见的状态参数还有:

配置方式说明
max_fails允许请求失败次数,默认为 1 。通常和下面的 fail_timeout 连用。
fail_timeout在经历了 max_fails 次失败后,暂停服务的时长。这段时间内,这台服务器 Nginx 不会请求这台 Server
backup预留的备份机器。它只有在其它非 backup 机器出现故障时或者忙碌的情况下,才会承担负载任务。
down表示当前的 server 不参与负载均衡。

例如:

upstream web_server {
    server 192.168.78.128 weight=1 max_fails=1 fail_timeout=30s;
    server 192.168.78.200 weight=2 max_fails=1 fail_timeout=30s;
    server 192.168.78.201 backup;
    server 192.168.78.210 down;
}

5. 负载:ip_hash 负载

ip_hash 方式的负载均衡,是将每个请求按照访问 IP 的 hash 结果分配,这样就可以使来自同一个 IP 的客户端固定访问一台 Web 服务器,从而就解决了 Session 共享问题。

upstream xxx {
    ip_hash;
    server 127.0.0.1:8080;
    server 127.0.0.1:9090;
}

使用上例配置后,你会发现无论你请求多少次 http://127.0.0.1/api/hello 你所看到的端口始终是 80809090 中的某一个。

目前有四种方案解决用户登录信息存储问题

1.通过ip_hash的方法判断用户ip锁定同一台服务器

2.后端无状态模式,用户登录后后端将获取的权限发送给前端,前端存储在客户端中,权限判断由前端写

3.tomcat共享session功能,每台服务器的session同步更新,缺点:服务端耗费资源,并且只有少数服务器有这种功能

4.使用redis储存用户信息,在用户首次登录时将用户信息用redis的hash类型进行存在,token做键其他权限、信息等做值,后续都从redis中进行获取

6. 将客户端浏览器的 IP 传递到后台 了解

对于后台而言,它所面对的『客户端』就是 Nginx,后台看不见『客户端』浏览器。

这就意味着,你如果你需要在后台获取客户端浏览器的 IP 地址,你需要明确指出让 Nginx 『额外地多携带』一些数据。

 location /api {
     proxy_pass http://xxx/api;
     proxy_set_header X-Real-IP $remote_addr;
 
     # 解决 nginx 不会“转发” Cookie 问题
     # proxy_set_header Cookie $http_cookie;
 
     # 解决 upstream 名称携带下划线(_)时,访问 400 问题。
     # proxy_set_header Host $http_host;
 
     # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 }

在 Spring Boot 的 Controller 中你有 2 种方式来获得这个额外的信息:

 public Map<String, String> index(
         HttpServletRequest request,
         @RequestHeader("X-Real-IP") String realIP2) {
     String realIP1 = request.getHeader("X-Real-IP");
     ...
 }



    *
    • 0
      点赞
    • 0
      收藏
      觉得还不错? 一键收藏
    • 0
      评论

    “相关推荐”对你有帮助么?

    • 非常没帮助
    • 没帮助
    • 一般
    • 有帮助
    • 非常有帮助
    提交
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值