一次慘痛的線下機房上雲的經歷

背景

所有的應用都在本地機房部署

有大概應用在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個小時。

總結 

    借阿里的事故的一句話:敬畏每一行代碼!在成長的過程中壯大自己!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章