最近有人反映,公司的產品有一部分境外用戶(主要在北美洲和歐洲)在上網高峰期有加載緩慢和失敗的情況,本來中國這種網絡的大環境就是如此,在境外用國內的服務,心里就應該有點B數,但是無奈領導說這部分用戶的收入占整體的13%,不能不管啊。無奈之下,也只好想辦法解決。
這篇隨筆包含了各種不專業並且不夠優雅的的解決方式,其實都是向歷史包袱和現實狀態的妥協。在有限的資源下盡量節省成本,解決問題。
服務主要分三部分
A, 動態服務部分 提供主要功能 特點是讀寫均衡,每個用戶的數據有橫向對比,只有為了保證數據准確性讀緩沒有寫緩(Apache 2.4 php 7.1 MySQL 5.6 Redis 3.2 不要吐槽這玩意,歷史包袱而已,小公司人少事多,時間久了問題堆積的也比較要命)
B, 網站上大部分的圖片、視頻、字體等靜態資源,以及A里面用到的一部分富文本編輯器里面引用的資源
C, 網站內容提供者上傳的多媒體課件包,體積不小。但是都比較獨立 這應該是最簡單的部分。
首先要說,這里沒有采用智能DNS的原因
- 部署多台服務器會造成管理成本,而且歷史悠久的項目細節太多,很多沒有文檔,貿然部署新服務器,有可能造成某些地區的用戶遇到BUG,或者服務中斷的情況,不到萬不得已,我是盡量不想讓用戶感受到服務有中斷的。
- SSL證書配置麻煩,因為要同一套證書,而且用的是Let's Encrypt,這樣就要在一台Let's Encrypt服務器所在地區的服務上做認證,然后同步到其他服務,想想就腦袋大
- DNS解析用的阿里雲,免費解析不支持細分區域,你問我為啥不用收費的?沒錢啊,節省成本。
然后來分塊解決問題
先說C ,這部分很好辦,開一台北美的雲主機,假設Rsync和HTTP服務,然后同步課件過去,域名配置成C1 和原來的C做鏡像,然后在A上面判斷訪客IP的來源,動態切換域名即可
這里要記錄的關鍵點
- PHP 使用geoip判斷IP的來源(只在訪問課件的部分判斷)
- rsync的搭建 (這個東西很好安裝 直接yum就行了,但是很難配置,搞了很久,主要遇到兩個問題,一個是網絡不通,后來發現是雲平台自帶一個端口過濾的規則,打開就好了。另一個問題是權限問題,怎么配置都搞不定最后放棄了,走了SSH通信的方式,導致第一個問題也不存在了)
具體做法可以自行搜索
/usr/bin/rsync -vzrtopg --progress --delete -e ssh root@源服務器:/data/iSpring_htdocs/ /data/iSpring_htdocs/
然后是B區域,這里正確的做法是CDN(成本不足放棄了)或者智能解析(同C的理由也放棄了)業務邏輯很復雜,很多資源特別混亂,外加有混合在富文本編輯器生產的內容里面引用的資源,所以也不能輕易替換域名,后來發現雲平台有個服務可以加速境外訪問,但是大概算了一下成本,乖乖一個月要14萬大洋,這肯定也不行。好吧,正常可以用的方案都不能用了,下面就從其他方面考慮。
首先明確一點,響應速度和加載速度是兩碼事,我們這里要解決的主要是加載失敗,而不是響應速度,也就是說,可以加載慢一點點(當然也不能太慢)畢竟只是上網高峰期慢,但是盡量不要讓用戶不能使用。於是我想到了基於用戶IP來源的地區在nginx上面做域名跳轉到鏡像站。這樣A區域的所有域名都不需要更改,自動會302跳轉到B的鏡像服務器域名B1上了。
這里要記錄的關鍵點
rsync同步文件(同C)
nginx重新編譯(lnmp.org 支持配置文件自定義編譯參數,添加好模塊判斷來源 寫跳轉規則)https://www.cnblogs.com/lixigang/articles/5130052.html
#安裝 MaxMind 的 GeoIP 庫 wget http://geolite.maxmind.com/download/geoip/api/c/GeoIP.tar.gz tar -zxvf GeoIP.tar.gz cd GeoIP-1.4.8 ./configure make make install
echo '/usr/local/lib' > /etc/ld.so.conf.d/geoip.conf ldconfig
#下載 IP 數據庫 wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz gunzip GeoIP.dat.gz mv GeoIP.dat /usr/local/nginx/GeoIP.dat chmod 544 /usr/local/nginx/GeoIP.dat #lnmp.conf里面 Nginx_Modules_Options=' --with-http_geoip_module' 保存 運行upgrade.sh 升級nginx 然后nginx -V 查看模塊 編輯nginx.conf http段增加 geoip_country /usr/local/nginx/GeoIP.dat; fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code; server段 vhost判斷 if ($geoip_country_code = CN) { rewrite ^(.*) https://baidu.com; } if ($geoip_country_code != CN) { rewrite ^(.*) https://163.com; }
最后是A,也是最難弄的部分,代碼沒做前后端分離,很多事情特別難搞,外加第三方服務的接入亂七八糟的,需要整理代碼,盡量把不相關的靜態資源放到B上面去,A模塊就只保留PHP業務邏輯和HTML動態輸出,開啟gzip,(apache暫時不能換成nginx,問題太多了不好一一解決),開發層面上優化和分離代碼,數據庫層面上,建立海外鏡像節點,做同步,同步的通信端口通過多個代理根據ping值來動態切換。但都是權宜之計,最終還是要做智能DNS解析,然后部署海外鏡像,不過代碼沒整理好之前,暫時不動,觀察一下用戶訪問的體驗反饋。
2018.11.29更新
發現letsencrypt續期和IP來源判斷沖突 這里需要單獨判斷一下 所以配置文件修改
1 set $flag 0; 2 if ($http_user_agent ~* (letsencrypt)){ 3 set $flag "${flag}1"; 4 } 5 if ($geoip_country_code != CN) { 6 set $flag "${flag}2"; 7 } 8 if ($flag = "02") { 9 rewrite ^(.*) http://國外鏡像服務器域名/$1 permanent; 10 }
本文未完成,細節沒有補充
