DockerCompose編排Nginx+Mysql並實現Nginx配置Mysql(TCP協議)負載均衡

霸道流氓發表於2024-08-13

場景

Nginx配置例項-負載均衡例項:平均訪問多臺伺服器:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103019576

以上實現Nginx的http協議的負載均衡,如果使用Nginx實現TCP協議的負載均衡比如配置Mysql的連線,可使用如下方式。

首先搭建兩臺mysql和一臺nginx的測試環境。這裡使用Docker Compose搭建。

注:

部落格:
https://blog.csdn.net/badao_liumang_qizhi

實現

1、測試環境搭建

Docker Compose中編排Nginx時yml的寫法

nginx:
image: nginx:latest
privileged: true
ports:
- 100:100
volumes:
- ./nginx/etc/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/logs:/var/log/nginx
- ./nginx/etc/conf.d:/etc/nginx/conf.d

注意這裡在docker-compose.yml所在的路徑下新建nginx目錄,並在目錄下新建etc和logs目錄

另外注意nginx做資料卷對映時不要直接講以上nginx的配置檔案ngin.conf進行對映,另外兩個目錄logs和conf.d可以直接進行對映。

需要先手動將nginx.conf配置檔案上傳至宿主機目錄下再啟動容器。

原因是不支援直接掛載檔案,只能掛載資料夾,想要掛載檔案,必須宿主機也要有對應的同名檔案。

如果強行直接掛載,則啟動容器後會提示

mounting "/root/nginx.conf" to rootfs at "/etc/nginx/nginx.conf" caused: mount through procfd: not a directory: unknown:

Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type.

那麼如何獲取nginx.conf資料卷對映的配置檔案?

先使用docker命令執行一個nginx容器,然後進入容器內部,將配置檔案複製出來即可。

docker中拉取nginx映象

docker pull nginx

docker中啟動nginx容器

docker run -d --name nginx nginx

docker中複製nginx容器內配置檔案到當前目錄

docker cp nginx:/etc/nginx/nginx.conf $PWD/

執行效果

配置檔案複製成功後就可以停掉並刪除容器了。

docker中停掉並刪除nginx容器

docker container stop nginx

docker container rm nginx

上面nginx.conf複製到nginx/etc目錄下之後,需要授予許可權

chmod 777 nginx.conf

Docker Compose編排mysql時yml的寫法

mysql1:
image: mysql:8.0
command: --lower_case_table_names=1
environment:
MYSQL_DATABASE: test
MYSQL_ROOT_PASSWORD: ABC@123!
MYSQL_ROOT_HOST: '%'
TZ: Asia/Shanghai
ports:
- "301:3306"
volumes:
- ./mysql1/data:/var/lib/mysql

這裡設定root密碼,並允許遠端連線,然後埠對映為301到容器內3306

同理再搭建一個mysql,對映埠302

mysql2:
image: mysql:8.0
command: --lower_case_table_names=1
environment:
MYSQL_DATABASE: test
MYSQL_ROOT_PASSWORD: ABC@123!
MYSQL_ROOT_HOST: '%'
TZ: Asia/Shanghai
ports:
- "302:3306"
volumes:
- ./mysql2/data:/var/lib/mysql

2、使nginx與兩個mysql使用自定義網路方式互通

完整yml配置檔案

version: "3.8"

services:

mysql1:
image: mysql:8.0
command: --lower_case_table_names=1
environment:
MYSQL_DATABASE: test
MYSQL_ROOT_PASSWORD: ABC@123!
MYSQL_ROOT_HOST: '%'
TZ: Asia/Shanghai
ports:
- "301:3306"
volumes:
- ./mysql1/data:/var/lib/mysql
networks:
balancenet:
ipv4_address: 192.128.0.11

mysql2:
image: mysql:8.0
command: --lower_case_table_names=1
environment:
MYSQL_DATABASE: test
MYSQL_ROOT_PASSWORD: ABC@123!
MYSQL_ROOT_HOST: '%'
TZ: Asia/Shanghai
ports:
- "302:3306"
volumes:
- ./mysql2/data:/var/lib/mysql
networks:
balancenet:
ipv4_address: 192.128.0.12

nginx:
image: nginx:latest
privileged: true
ports:
- 100:100
volumes:
- ./nginx/etc/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/logs:/var/log/nginx
- ./nginx/etc/conf.d:/etc/nginx/conf.d
networks:
balancenet:
ipv4_address: 192.128.0.13

networks:
balancenet:
ipam:
config:
- subnet: 192.128.0.0/24

3、啟動測試環境

docker compose up

這裡不新增-d,便於檢視日誌。

確保無報錯,三個容器啟動成功

4、nginx配置修改實現tcp協議負載均衡

分別連線上面啟動的301和302的mysql,建立不同的資料庫名稱為301和302。

要實現連線nginx代理的100埠的mysql時,負載均衡的連線到兩個資料庫,可以透過檢視資料庫名稱進行結果驗證。

在 NGINX 的 stream 模組內使用 upstream 程式碼塊對 TCP 伺服器實施負載均衡。

上面容器內複製出來的nginx.conf的檔案未修改之前為

新增如下配置

stream{
upstream mysql{
server 192.128.0.11:3306 weight=1;
server 192.128.0.12:3306 weight=1;
}
server {
listen 100;
server_name 192.128.0.13;
proxy_pass mysql;
}
}

新增之後完整的nginx.conf檔案


user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;


events {
worker_connections 1024;
}


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

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

include /etc/nginx/conf.d/*.conf;
}

stream{
upstream mysql{
server 192.128.0.11:3306 weight=1;
server 192.128.0.12:3306 weight=1;
}
server {
listen 100;
server_name 192.128.0.13;
proxy_pass mysql;
}
}

上面的配置的 server 程式碼塊指示 NGINX 偵聽 TCP 埠 100,並在兩個 MySQL 資料庫讀取副本之間實施負載均衡。

上面兩個mysql的root密碼是一致,下面用mysql客戶端工具比如Navicat等使用同樣的密碼連線和關閉資料庫,驗證是否顯示不同

的資料庫名稱。

總結:

http 和 stream 上下文之間的主要區別在於它們在 OSI 模型的不同層上執行。

http 上下文在應用層(七層)執行,stream 在傳輸層(四層)執行。

這並不意味著 stream 上下文不能透過一些巧妙的指令碼獲得應用感知能力,

而是說 http 上下文是專門為了完全理解 HTTP 協議而設計的,

stream 上下文預設情況下只能對資料包進行路由和負載均衡。

TCP 負載均衡由 NGINX 的 stream 模組定義。

stream 模組與 HTTP 模組一樣,允許您定義上游(upstream)伺服器池並配置偵聽伺服器。

在配置伺服器偵聽給定埠時,您必須定義待偵聽的埠或者地址加埠(可選)。

然後您必須配置目標服務,無論這是連線另一個地址的直接反向代理還是上游資源池。

配置中有許多選項可以改變 TCP 連線反向代理的屬性,包括 SSL/TLS 驗證限制、超時和 keepalive 等。

這些代理選項的一些值可以是(或者包含)變數,例如下載速率、驗證 SSL/TLS 證書時使用的名稱等。

TCP 與 HTTP 負載均衡中的 upstream 指令非常相似,它們均將上游資源定義為伺服器,

配置格式同樣為 Unix 套接字、IP 或 FQDN,此外伺服器 weight 引數、最大連線數、DNS 解析器、

連線數緩增期以及判斷伺服器是啟用狀態、故障狀態還是備用模式的引數也都相似。

相關文章