Featured image of post Nginx

Nginx

專案被廢,百廢待興的技術學習

安裝

Mac Homebrew

1
brew install nginx

啟動與停止

啟動

1
brew services start nginx

1
ngnix

成功後訪問

http://localhost:8080/

就可以看到以下畫面

image-20240510140421056

可以輸入

1
ps -ef |grep nginx
1
2
3
4
5
6
7
ps -ef | grep nginx 是一个用于在 macOS 或类 Unix 系统中查找正在运行的 nginx 进程的命令。它的作用如下:

ps: 这个命令用于显示当前运行的进程列表。
-ef: 这是 ps 命令的选项,其中 -e 用于显示所有进程,-f 用于显示全面的进程信息。
|: 这是管道符,它将 ps -ef 命令的输出发送到下一个命令。
grep nginx: 这个命令用于过滤包含关键字 "nginx" 的行,只显示与 nginx 相关的进程。
因此,ps -ef | grep nginx 的作用是显示所有包含 "nginx" 关键字的进程,帮助你找出当前正在运行的 nginx 进程。

看到nginx的執行狀況

image-20240510185004533

停止

image-20240510144229718

1
nginx -s signal

優雅停止

1
nginx -s quit

立刻停止

1
nginx -s stop

重載配置文件

1
nginx -s reload

重新打開日誌文件

1
nginx -s reopen

Ngnix介紹

做負載均衡、反向代理、虛擬主機的一個中間件

可以輸入以下指令查看進程

1
ps -ef |grep nginx
1
2
3
4
5
6
7
ps -ef | grep nginx 是一个用于在 macOS 或类 Unix 系统中查找正在运行的 nginx 进程的命令。它的作用如下:

ps: 这个命令用于显示当前运行的进程列表。
-ef: 这是 ps 命令的选项,其中 -e 用于显示所有进程,-f 用于显示全面的进程信息。
|: 这是管道符,它将 ps -ef 命令的输出发送到下一个命令。
grep nginx: 这个命令用于过滤包含关键字 "nginx" 的行,只显示与 nginx 相关的进程。
因此,ps -ef | grep nginx 的作用是显示所有包含 "nginx" 关键字的进程,帮助你找出当前正在运行的 nginx 进程。

image-20240510185537496

Master Process & Worker Process

iShot_2024-05-10_14.32.32

Master

負責讀取以及驗證文件、管理woker process,只有一個

Worker

負責處理實際請求,可以有很多個

如何更改Ngnix的啟動畫面,配置index.html等靜態資源

輸入,找到配置檔的位置

1
nigix -t

接著輸入打開編輯

1
code /opt/homebrew/etc/nginx/nginx.conf

這邊就是檔案配置的位置

![image-20240510151026498](/Users/hoxtonashes/Library/Application Support/typora-user-images/image-20240510151026498.png)

接著找看看Nginx的安裝目錄

1
cd /opt/homebrew/Cellar/nginx/1.25.5

image-20240510152220911

修改這個檔案

1
code /opt/homebrew/Cellar/nginx/1.25.5/html/index.html

image-20240510152842062

就可以了,如果要佈置自己的網頁也是放到一個的目錄底下即可

image-20240510153011985

調整Worker數量

1
code /opt/homebrew/etc/nginx/nginx.conf

image-20240510153641003

重新加載

1
nginx -s reload
1
ps -ef |grep nginx

Worker 數量跟cpu 核心數量一致會比較好,或是設置成auto

image-20240510154041120

image-20240510153906333

Nginx配置文件介紹

https://www.bilibili.com/video/BV1mz4y1n7PQ?p=5&spm_id_from=pageDriver&vd_source=422eafa6570139128e44a83238959fa0

底下的每個Server塊就是一個虛擬主機

image-20240510154309129

我們可以先將整個配置文件清空,從頭寫一遍配置文件來學習

image-20240510173633173

此時想啟動也啟動不了,會跟我們說少了event區塊

image-20240510173741850

補上後就可以成功啟動

1
2
3
events{

}

但啟動後會發現,我們的nginx沒有監聽任何port號

image-20240510174538169

因此我們需要再配置http 模塊

1
2
3
4
5
6
7
8
9
events{}

http{
    # 定義的是虛擬服務器,可以配置很多server
    server {
        listen 8087;
        server_name localhost;
    }
}

此時如果我們有在html/資料夾底下配置index.html 就會顯示那個html的內容,如果沒有就不顯示,顯示403這樣

image-20240510175301562

也可以配置寫死的返回值 8089

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
events{}

http{
    # 定義的是虛擬服務器,可以配置很多server
    server {
        listen 8087;
        server_name localhost;
    }
    server {
        listen 8089;
        server_name localhost;
        return  200 "Hoxton Hello";
    }
}

image-20240510175944283

配置重定向

可以用

1
2
3
4
5
6
7
 server {
        listen 8087;
        server_name localhost;
        location /temp{
            return 307 index.html;
        }
    }

的方式

或是用rewrite

1
2
3
4
5
  server {
        listen 8087;
        server_name localhost;
        rewrite /temp index.html
    }

何謂正向代理,何謂反向代理

正向代理

正向代理就是類似VPN,透過一個代理節點去幫我訪問網站,例如中國的翻牆

image-20240510155610368

反向代理

對外指暴露一個端口,但背後可能有好幾個端口,代理的是服務端

image-20240510155710024

使用Java來配置網址,理解反向代理

先配置3個不同的port (8081,8082,8083)

image-20240510162243108

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package org.hoxton;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

import java.io.IOException;
import java.io.OutputStream;

public class Main {
    public static void main(String[] args) throws Exception {
        int port = 8081;
        HttpServer server = HttpServer.create(new java.net.InetSocketAddress(port), 0);
        server.createContext("/", new MyHandler());
        server.setExecutor(null); // 使用默认的执行器
        server.start();
        System.out.println("Server is listening on port " + port);
    }

    static class MyHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            String response = "Hello, World!";
            exchange.sendResponseHeaders(200, response.getBytes().length);
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package org.hoxton;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

import java.io.IOException;
import java.io.OutputStream;

public class Main2 {
    public static void main(String[] args) throws Exception {
        int port = 8082;
        HttpServer server = HttpServer.create(new java.net.InetSocketAddress(port), 0);
        server.createContext("/", new MyHandler());
        server.setExecutor(null); // 使用默认的执行器
        server.start();
        System.out.println("Server is listening on port " + port);
    }

    static class MyHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            String response = "Hello, World!";
            exchange.sendResponseHeaders(200, response.getBytes().length);
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package org.hoxton;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

import java.io.IOException;
import java.io.OutputStream;

public class Main3 {
    public static void main(String[] args) throws Exception {
        int port = 8083;
        HttpServer server = HttpServer.create(new java.net.InetSocketAddress(port), 0);
        server.createContext("/", new MyHandler());
        server.setExecutor(null); // 使用默认的执行器
        server.start();
        System.out.println("Server is listening on port " + port);
    }

    static class MyHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            String response = "Hello, World!";
            exchange.sendResponseHeaders(200, response.getBytes().length);
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    }
}

修改配置檔案,配置如下,把8081 8082 8083 設置一下,如此一來,訪問

http://localhost:8080/app

時,就會代理到這三個port號(預設是輪詢),見下方Gif

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

#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;
    upstream backend_hoxton{
        server 127.0.0.1:8081;
        server 127.0.0.1:8082;
        server 127.0.0.1:8083;
    }

    #gzip  on;

    server {
        listen       8080;
        server_name  localhost;
    }
}

image-20240510163709808

iShot_2024-05-10_16.38.15

也可以設置權重(weight) 來調整

1
2
3
4
5
    upstream backend_hoxton{
        server 127.0.0.1:8081 weight =3; 
        server 127.0.0.1:8082;
        server 127.0.0.1:8083;
    }

也可以使用ip_hash,這樣相同的請求就會被轉到一樣的port號了,這動作也就是讓nginx把流量導到指定的服務集群

1
2
3
4
5
6
    upstream backend_hoxton{
        ip_hash;
        server 127.0.0.1:8081 weight =3; 
        server 127.0.0.1:8082;
        server 127.0.0.1:8083;
    }

配置Path要注意的內容,避免不當訪問

但這個方法非常不安全!等於說我們可以讓用戶用這樣的方式訪問我們服務器的內容。

比如說我們可能只想暴露http://localhost:8080/app/index.html這個文件,但如果寫成

1
2
3
location /app{
proxy_pass http://backend_ hoxton
}

用戶可以訪問

http://localhost:8080/apple/index.html

http://localhost:8080/app/screctKey

等等的內容,所以我們最好用全限定的方式,限定訪問的資源,也可以使用正則表達式來限定,這邊還有很多的內容,比如說前綴配對還有什麼東西之類的,就不展開了。

1
2
3
location /app{
proxy_pass http://backend_ hoxton
}

虛擬主機

目的是在一台主機上面配置多個站點,

常用命令

查看版本

1
nginx -v	

查看運行狀態

1
service nginx status

查看Nginx配置

1
nginx -V

image-20240510145507892

查看Nginx配置文件

1
nigix -t

image-20240510145620545

參考網址

https://www.bilibili.com/video/BV1mz4y1n7PQ?p=3&vd_source=422eafa6570139128e44a83238959fa0

https://www.bilibili.com/video/BV1TZ421b7SD/?spm_id_from=333.337.search-card.all.click&vd_source=422eafa6570139128e44a83238959fa0

Licensed under CC BY-NC-SA 4.0