本文最近更新於2020.6.7
(一)灰度發布
1.簡單介紹
Nginx的灰色發布可以通過nginx自帶的split_clients模塊對流量進行分發,按照一定的分發規則,同時提供多個版本的文件或應用服務,從而實現灰色發布.
原理是通過對"${http_user_agent}AAA" (這個是瀏覽器版本+字符串AAA的意思)使用MurmurHash2算法進行哈希.以值4294967295為界,如果"${http_user_agent}AAA"最終返回的哈希值位於4294967295的前75%,則該請求發給130,如果是后25%則發給133
可以參考http://www.ttlsa.com/nginx/nginx-ngx_http_split_clients_module/
2.配置方法
以下是我的nginx.conf配置:
split_clients "${http_user_agent}AAA" $variant{ #這個$variant應該是一個相當於標簽命名吧,方便下面proxy_pass使用 75.0% 192.168.2.130:80; 25.0% 192.168.2.133:80; } server { listen 80; server_name localhost; location / { proxy_pass http://$variant; }
3.驗證
因為這個涉及到訪問百分比問題,糾結了好久怎么去驗證,最終找到一個瀏覽器插件進行輔證
我使用的瀏覽器是firefox瀏覽器,插件名為Random User-Agent
通過切換不同的瀏覽器版本信息,實現變換http_user_agent的值,切換一個瀏覽器刷新一下頁面,多進行幾次就會發現返回的頁面內容不同.
還可以通過設置日志格式查看
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"' "$variant" ; #打印$variant的值 access_log logs/access.log main;
4.擴展知識
所謂灰度發布就是在原對外服務的系統上,先讓一部分用戶使用待正式發布的服務版本,確認沒問題后再進行逐步更替甚至全面更新.這也就是我們說的金絲雀發布.
除了灰度發布外,還有藍綠發布.和灰色發布只需要一套系統不同,藍綠發布需要使用到兩套相同系統,這兩套系統處於共存狀態.一套為正常對外提供服務的系統,我們稱之為綠色系統,還有一套是不對外提供服務的系統,我們稱之為藍色系統.藍色系統只用於做發布前的測試,測試過程中發現問題時直接修改藍色系統,不影響用戶使用.當藍色系統修改到符合上線標准時,直接將用戶切換到這個藍色系統.切換到藍色系統后,綠色系統仍保留一段時間,使得藍色系統出現問題時可以快速切回綠色系統.直到確認藍色系統正常運行后,才可以刪掉原來的綠色系統.
另外還有一個就是A/B測試,A/B測試和灰度發布和藍綠發布不是一回事.灰度/藍綠發布主要時為了避免新版本有BUG等,而A/B測試則是偏重於新發布的版本內容是否符合用戶需求,例如一個經過驗證的新功能通過A/B測試發布后,通過用戶的反饋,從而決定是否要將該功能納入正式版本中.
采用什么發布方法,取決於具體需求.例如只有一台服務器的情況下,不適合使用灰度發布,因為使用灰度發布會導致出現問題后回滾比較麻煩,而應該采用藍綠發布.相反,如果后台服務器有幾十甚至上百台,那么建議使用灰度發布,因為藍綠發布要求藍色系統可以提供和綠色系統一樣的對外服務能力,也就是說藍色系統也需要用到很多台服務器.
具體可以參考https://www.cnblogs.com/lijiaocn/p/9986880.html
(二)根據區域管控流量
通過GeoIP Module and Database實現,需要額外安裝GeoIp數據庫,並將其嵌入到Nginx.
GeoIP Module and Database是一個IP地理位置庫,根據位置庫得到IP所在國家,從而對這些國家所在的IP流量進行管控,例如我們可以直接禁止美國的用戶訪問我們的服務器.更具體的,我們還可以實現到拒絕紐約市用戶訪問.
這里我使用的是通過YUM安裝的nginx,對其進行重新編譯添加新的geopip模塊
步驟如下:
1.重新編譯安裝
添加geopip模塊
/usr/sbin/nginx -V #首先我們確定nginx版本 wget -c https://nginx.org/download/nginx-1.16.1.tar.gz #我的是1.16.1版本,所以下載一個相同的版本進行編譯 tar -zxvf nginx-1.16.1.tar.gz cd nginx-1.16.1/ yum install geoip geoip-devel -y #安裝geoip ./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --with-http_geoip_module #在原編譯配置上添加最后的geoip模塊即可,這里我省略了部分配置 make #注意不能執行make install,否則原nginx會出問題,影響業務 mv /usr/sbin/nginx /usr/sbin/nginx.bak #原nginx可執行文件進行備份 cp objs/nginx /usr/sbin/nginx #新編譯的nginx可執行文件代替現有文件 make upgrade #平滑升級 /usr/sbin/nginx -V #確認是否成功配置geoip模塊
2.配置nginx.conf
在http{}模塊內,添加以下內容,根據IP所處的國家,給其添加一個country_access標記.
geoip_country /usr/share/GeoIP/GeoIP.dat; map $geoip_country_code $country_access { #設置$country_access對應的值為1或0 "CN" 0; #ip來自中國,設置對應值為0 "RU" 0; default 1; #默認值為1 }
在server{}模塊內,添加以下內容,當country_access為1時,返回403(禁止訪問)
if ($country_access = '1') { #值為默認值時直接拒絕 return 403; }
3.驗證
CN對應值為0時
CN對應的值為1時
4.補充說明
以上是針對國家區域進行的流量管控,貌似還可以對國家里具體的城市進行流量管控,這個還沒實踐,有興趣的可以參考以下內容:
https://www.nginx.cn/doc/optional/geoip.html
(三)限制連接數
限制連接。構建一個共享內存區域,限制打開的連接數
1.配置
http {
limit_conn_zone $binary_remote_addr zone=limitbyaddr:10m; #limitbyaddr為區域命名,10m應該是共享內存大小
limit_conn_status 429; #返回過多請求數代碼429
...
server {
...
limit_conn limitbyaddr 2; #使用limitbyaddr區域,連接數最大為2(這里只是一個舉例,便於測試看到效果).則並發數超過2后,就會直接返回429
...
}
}
2.驗證
ab -n 5 -c 5 -v 2 192.168.2.129/index.html #使用ab工具進行壓力測試,-n指定請求總數,-c指定並發數,-v指定返回的信息等級
返回信息部分截圖.可以看到,部分請求返回正常的頁面內容,還有就是429狀態碼
(四)訪問限速
使用rate-limiting模塊進行限速。可用於防止拒絕式攻擊
http {
limit_req_zone $binary_remote_addr zone=limitbyaddr:10m rate=1r/s;
limit_req_status 429;
...
server {
...
limit_req zone=limitbyaddr burst=2 nodelay; #並發達到2后,立即實施延遲
...
}
}
2.檢驗
使用以下命令進行壓測
ab -n 10 -c 5 -v 2 192.168.2.129/index.html
部分請求返回結果如下
來看一下最后的壓測結果
10個請求中,失敗了六個,只成功了4個.
倒推一下,10個請求,並發數為5,那么也就是分為兩次並發量為5的請求.每次並發為5,而我們nginx配置的最大並發為2,也就是說一次並發就會有3次報錯,那么兩次並發就是2*3=6次報錯,和配置一致.
(五)下載限速
限制客戶端下載帶寬。
location /download/ {
limit_rate_after 10m; #最大訪問下載速度為10m
limit_rate 1m; #默認1m
}
未限速前
限速后.
可以看到,之前2秒就傳輸完了,先在需要幾分鍾,速度最快在10M左右,不過基本都是在1M左右