背景
所有的應用都在本地機房部署
有大概應用在20個左右,其中微服務應用各種組件和服務在8個左右,其他的都是老系統留下來的應用
準備
服務類型 |
阿里雲ECS規格 |
內存 |
CPU |
機械硬盤 |
固態硬盤 |
外網IP和帶寬 |
數量 |
nginx代理轉發 |
計算網絡增強型 sn1ne |
8G |
4核 |
300G |
無 |
帶寬10M(根據實際使用情況調整) |
1 |
tomcat類後端服務器 |
通用型g6 |
8G |
2核 |
300G |
無 |
無 |
10 |
redis緩存隊列 |
通用型g6 |
8G |
2核 |
300G |
100G |
無 |
3 |
redis(可選配置) |
內存網絡增強型 se1ne |
16G |
2核 |
300G |
100G |
無 |
|
redis(可選配置) |
內存型(原獨享)se1 |
16G |
2核 |
300G |
100G |
無 |
|
數據庫 |
通用型g6 |
16G |
4核 |
500G |
300G |
無 |
4 |
數據庫(可選配置) |
內存型(原獨享)se1 |
32G |
4核 |
500G |
300G |
無 |
|
數據庫(可選配置) |
內存網絡增強型 se1ne |
32G |
4核 |
500G |
300G |
無 |
|
部署遷移
我們的運維小哥哥從6月2號開始進行部署和遷移,三天之後也就是6月5號的時候完成整體的遷移工作,因爲我們還在進行項目的迭代工作,所以我們的測試周期啦的比較長。到6月18號左右才完成測試工作。
6月20號,全員休息,對我們來說是一個好日子,奮鬥開始了我和我們的運維小哥哥,測試小哥哥一大早開始來到公司,掛起維護頁面。然後就開始幹起來了:
第一步:數據同步,這是一個漫長的等待時間,當然這個主要是運維小哥哥在操作。
第二步:配置更新,對於微服務來說比較輕鬆,更改nacos上的配置文件就好了。
預期規劃如下:
數據庫 | redis | |
微服務應用 | 一主多從 | 哨兵模式 |
老應用 | 多寫分離加多數據源 | 哨兵模式 |
對於的老的應用來說,用git做的配置中心,腳本拉取替換(WAR包,JAR包就別想了)的方式,其實更改起來也比較OK。所以配置更新也是相當順利
第三步:更新所有的應用到最新的版本,這個就是jenkins上操作即可,無問題。
測試與當天問題發現
問題1:與第三方應用通訊需要外網的問題。
解決方式:彈性公網IP
問題2:文件共享問題
解決方式:因爲本地機房應用是沒有專門的文件服務器的,所以採用的軟連等相關操作,阿里雲上採用的共享和掛載操作
問題3:第三方推送地址更換問題
解決方式:聯繫第三方更改推送地址
問題4:訪問白名單問題
解決方式:針對443端口開放所有的訪問權限。
其他相關功能沒有什麼問題,基本上到這來說理論上這次遷移是很成功的,雖然忙活了一天但是還是心滿意足的下班了。
悲劇的第二天
第二天,懷着很忐忑的心情,早早的就起來坐到電腦旁邊了。8點開始沒什麼問題,貌似很穩定的情況,8點50左右,我的同事們都開始上班上系統幹活了,這個時候悲劇開始了。
第一個炸彈:大量的同事都是第一次通過外網的域名訪問系統,所以大量的併發導致需要拉取大量的靜態資源。瞬間帶寬超了。這個其實好理解,只是瞬時的,而且後面訪問基本趨於平穩狀態,10M的帶寬基本上能滿足需求。OK,這個可以過了。
第二個炸彈:所有的同事都說卡,訪問系統超級慢。然後就是整個釘釘羣,微信羣就炸了。
開始排查:
排查一:redis毫無壓力,是不是redis沒起作用?
因爲redis沒有開放外網端口,登錄服務器查看。
./redis-cli -a 'pwd'
使用命令查看所有的key
keys *
redis正常緩存數據,沒有問題。那麼這個時候考慮是不是老系統不兼容哨兵配置,改回單機模式。並沒有任何效果,redis正常讀寫沒問題。排除
排查二:數據庫,是否是數據庫壓力過大。
查看主庫:沒問題,兼職就是毫無壓力
查看從庫:壓力爆滿,CPU完成超超負荷運行。那麼問題來了,爲什麼會出現這種情況?
解決方案1:分壓,既然主庫沒有任何壓力,那麼先在某些應用的節點更改主庫爲從庫,也就是主從一致。
效果:瞬間主庫壓力上來,從庫反而沒有任何壓力了。卡頓現象並沒有解決。
解決方案2:查看系統日誌,發現某些節點的日誌輸出頻率較慢。是不是因爲某些服務器的配置的問題,重啓相關服務器和從庫。
效果:依然沒有解決我們的問題。
此時時間已經走到了10點多了。但是經過這幾輪的折騰,運維小哥哥突然記起來了,老的應用爲了保持會話,是做了IP HASH的問題。以前使用的是內網環境,所以每一個的IP地址都不一樣,現在用的外網環境,而公司統一的是專線固定IP,這樣就變成了訪問系統的IP變成了全一樣的了。所以就全路由的一個服務節點上去了,其他的服務節點完全就沒起作用了。
解決方案3:去掉IP HASH策略。
效果:去掉IP HASH會造成系統整個功能失常,所以基本上這個方案不可取。瞬間感覺好像走到死衚衕了,連飯都不想吃了。
解決方案4:運維小哥哥在拿外賣的時候突然告訴我,我們可以根據IP手動指定路由節點。雖然我們的出網帶寬固定了,但是還是有區域劃分的,每個區域的IP還是不一樣的。
效果:這個貌似解決了服務節點單一路由的問題。但是還是存在某些節點負載過大的情況,但是相比之前的情況,已經是好很多了。當然問題到這裏只是萬里長征走了第一步,完全沒有實際的解決現在的系統的問題。
隨着一天的上班結束,查詢系統數據的人越來越多,查詢量增大。這裏就得說一下我們的老系統的報表相關的功能了,全是大的SQL彙總起來,有時候一個SQL包含了各種計算,函數,彙總,分組統計等功能。基本上我這麼一個程序員老司機都不願意看這些SQL。
飛昇的第三天
解決方案5:增加數據庫從庫的CPU能力,升級數據庫配置。
效果:這個時候已經是第二天了,畢竟花錢還是有流程的,當然領導很給力,直接給特事特辦了。升級數據庫配置,在增加1個從庫,這個效果是立竿見影的,速度馬上就上來。這個過程本來是個很輕鬆的過程,但是由於掛載問題,nginx所在的服務器居然重啓失敗,導致外網IP失效。最後還是聯繫阿里雲的售後解決的。
這個時候基本上系統訪問不存在的問題了,但是各位不要忘記了,IPHASH的問題我們還沒有解決。
這個時候我一直在想nginx的IP hash的這個事情,其實所謂的IP hash不就是通過客戶的IP來計算hash值,來確認他的路由保持,那麼我在想我們是不是可以找一個替代IP的東西來解決這個會話保持的問題呢。
在我們的系統裏面正好有這麼一個東西對於客戶來說是唯一的,那就是請求TOKEN,而且這個請求Token就在請求頭裏面。
解決方案6:自定義HASH策略
開啓請求頭檢測
underscores_in_headers on;
定義2個路由規則:爲什麼是兩個呢?因爲我們有的請求是不需要登錄就能獲取的也就是沒有token的,我們也希望隨機輪詢。
upstream https_prod {
hash $token;
server 172.17.150.127:8080 ;
server 172.17.150.128:8080 ;
server 172.17.150.129:10080 ;
}
upstream https_prods {
server 172.17.150.127:8080 ;
server 172.17.150.128:8080 ;
server 172.17.150.129:10080 ;
}
獲取TOKEN,這裏比較特殊的就是,websocket的連接的token我們放在的是Sec-WebSocket-Protocol上,這裏注意了,在nginx配置文件中獲取的時候,需要吧-換成_
set $token $http_Sec_WebSocket_Protocol;
if ($http_Authorization != '') {
set $token $http_Authorization;
}
定義自動的路由規則
set $group https_prod;
set $groups https_prods;
location ^~ /api/ {
if ($token != '') {
proxy_pass http://$group;
}
if ($token = '') {
proxy_pass http://$groups;
}
#proxy_pass http://$group;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
#WebScoket Support
proxy_read_timeout 600s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
到這裏,自定義路由規則就完成,重啓nginx加載策略。
效果:比較完美的解決了IP HASH的問題,理論上比IP HASH更加完美。這個時候系統訪問速度的問題已經完全解決了
第三個炸彈:老系統的導出功能是,先在服務器上生產一個Excel文件,在吧連接返回給前端,前端通過a連打開下載的。因爲a連請求是沒有Token的,所以無法保持會話,所以有可能找不到這個文件。
解決方法:臨時,運維小哥哥做了一個共享。
最終:文件下載改成流式下載。
三天已經過去,說實話,心裏是賊幾把累的,按一個正常程序員的心裏,估計已經把前任罵的的飛起,但是其實我反而覺得這次的事情我自己應該有很多值得反思的事情。
- 服務器壓力預估不足
- 未深入的去了解系統的功能
- IP HASH的替代方案應該能更快給出,對nginx等相關軟件瞭解的還是不夠深
- 定位問題的速度過慢,定位到IP的問題已經超出2個小時。
總結
借阿里的事故的一句話:敬畏每一行代碼!在成長的過程中壯大自己!