1. 介紹
近幾天有幸接觸到Nginx反向代理、負載均衡相關(guān)知識逸嘀,為了加深印象车要,感覺還是有必要自己去踩一遍坑。
2. 學(xué)習(xí)案例
EasySwoole+git+Nginx 實現(xiàn)服務(wù)的不中斷部署
- 先部署
9501
服務(wù)
- 先部署
- 單起一個進程崭倘,定時輪詢Git分支是否有新版本發(fā)布
- 如有新版本發(fā)布翼岁,clone一份
- composer update 更新庫
- 啟動
9502
服務(wù)
- 啟動
- 6 更改nginx配置為
9502
并重啟
只要有新版本發(fā)布,就輪詢上面那幾個步驟
整個過程的簡單架構(gòu)圖
image.png
3. 提前需要了解的知識點
4. Nginx 配置
nginx.conf
當(dāng)有新版本發(fā)布的時候EasySwoole自定義進程會將nginx.conf 的端口改為最新服務(wù)
worker_processes 1;
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"';
sendfile on;
keepalive_timeout 65;
// 輪詢配置(這里是重點)
upstream easyswoole.relase.com {
server 127.0.0.1:9501;
}
server {
listen 8080;
server_name localhost;
}
include servers/*;
}
es-release.conf
server {
listen 80;
server_name easyswoole.relase.com;
location / {
root html;
index index.html index.htm;
proxy_pass http://easyswoole.relase.com; // 這里是重點
}
access_log /usr/local/etc/nginx/logs/es.access.log main;
error_log /usr/local/etc/nginx/logs/es.error.log error;
}%
5. EasySwoole 代碼實現(xiàn)
只是為了學(xué)習(xí)記錄司光,代碼有些粗糙琅坡,并且這種定時檢查代碼是否有新版本,最好單獨去做飘庄,比如用shell腳本
自定義進程文件
<?php
namespace App\Relase;
use EasySwoole\Component\Process\AbstractProcess;
use Swoole\Coroutine;
class Relase extends AbstractProcess
{
protected function run($arg)
{
go(static function () {
while (true)
{
$shellLog = ' 2>> /Users/xxx/sites/shell.log';
error_log('開始檢測代碼是否更新5'.PHP_EOL, 3, '/Users/xxx/sites/es-log.log');
// 檢查Git是否有新代碼發(fā)布
$diffExec = 'cd ' .EASYSWOOLE_ROOT. '; git fetch; git diff --stat master origin/master;';
$pullResult = exec($diffExec);
error_log(json_encode($pullResult), 3, '/Users/xxx/sites/es-log.log');
if ($pullResult !== '') {
error_log('有新版本發(fā)布'.PHP_EOL, 3, '/Users/xxx/sites/es-log.log');
// 新版本項目的目錄
$newVersionPath = '/Users/xxx/sites/relase-'.time();
// 開始clone, 初始化代碼
$cloneExec = "git clone https://github.com/huizhang-Easyswoole/release.git {$newVersionPath} {$shellLog};cd {$newVersionPath} {$shellLog};composer update {$shellLog}; {$shellLog}";
$res = exec($cloneExec, $a, $b);
error_log('新版本代碼clone'.PHP_EOL, 3, '/Users/xxx/sites/es-log.log');
// 判斷當(dāng)前是哪個端口正在服務(wù)
$lsofExec = "lsof -i:9501 {$shellLog}";
$lsofResult = exec($lsofExec);
$newPort = 9501;
$oldPort = 9502;
if ($lsofResult !== '') {
$newPort = 9502;
$oldPort = 9501;
}
// 將另一個閑置的端口脑蠕,替換到新版本中
error_log('開始替換端口'.$newPort.PHP_EOL, 3, '/Users/xxx/sites/es-log.log');
$devConfig = file_get_contents($newVersionPath.'/dev.php');
$devConfig = str_replace($oldPort, $newPort, $devConfig);
file_put_contents($newVersionPath.'/dev.php', $devConfig);
// 啟動新服務(wù)(這一刻新舊服務(wù)是同時存在的)
error_log('新服務(wù)啟動'.PHP_EOL, 3, '/Users/xxx/sites/es-log.log');
$startExec = "cd {$newVersionPath}; php easyswoole start d {$shellLog}";
exec($startExec);
// 替換nginx配置
error_log('開始替換ng端口'.PHP_EOL, 3, '/Users/xxx/sites/es-log.log');
$ngConfigPath = '/usr/local/etc/nginx/nginx.conf';
$ngConfig = file_get_contents($ngConfigPath);
$ngConfig = str_replace($oldPort, $newPort, $ngConfig);
file_put_contents($ngConfigPath, $ngConfig);
// 重啟Nginx
error_log('重啟ng'.PHP_EOL, 3, '/Users/xxx/sites/es-log.log');
$reloadNgExec = "nginx -s reload {$shellLog}";
exec($reloadNgExec);
// 停掉舊服務(wù)
error_log('舊服務(wù)停掉'.PHP_EOL, 3, '/Users/xxx/sites/es-log.log');
$stopExec = "cd ".EASYSWOOLE_ROOT."; php easyswoole stop {$shellLog}";
exec($stopExec);
// 每30秒同步一次代碼
Coroutine::sleep(30);
} else {
error_log('無新版本'.PHP_EOL, 3, '/Users/xxx/sites/es-log.log');
}
}
});
}
}
進程注冊
<?php
namespace EasySwoole\EasySwoole;
use EasySwoole\EasySwoole\Swoole\EventRegister;
use EasySwoole\Http\Request;
use EasySwoole\Http\Response;
use App\Relase\Relase;
class EasySwooleEvent implements Event
{
public static function initialize()
{
// TODO: Implement initialize() method.1
date_default_timezone_set('Asia/Shanghai');
}
public static function mainServerCreate(EventRegister $register)
{
// TODO: Implement mainServerCreate() method.
$process = new Relase('Es-relase');
ServerManager::getInstance()->getSwooleServer()->addProcess($process->getProcess());
}
public static function onRequest(Request $request, Response $response): bool
{
// TODO: Implement onRequest() method.
return true;
}
public static function afterRequest(Request $request, Response $response): void
{
// TODO: Implement afterAction() method.
}
}
7. 測試
綁定host
127.0.0.1 easyswoole.relase.com
訪問easyswoole.relase.com
image.png
查看Nginx配置的端口
? nginx cat nginx.conf | grep 950
server 127.0.0.1:9501;
發(fā)布新版本
重新clone一份代碼,更改內(nèi)容提交。
查看Nginx配置的端口
? nginx cat nginx.conf | grep 950
server 127.0.0.1:9502;
這樣就簡單實現(xiàn)了利用Nginx的反向代理+負載均衡功能實現(xiàn)了EasySwoole的服務(wù)不中斷部署功能谴仙。