微信內嵌瀏覽器sessionid丟失問題,nginx ip_hash將所有請求轉發到一台機器


 

現象
微信中打開網頁,圖形驗證碼填寫后,經常提示錯誤,即使填寫正確也會提示錯誤,並且是間歇性出現。
系統前期,用戶使用主要集中在pc瀏覽器中,一直沒有出現這樣的問題。近期有部分用戶是在微信中訪問的,才出現的這個問題。

抓包
由於只有在手機微信中出現這種情況,並且手機連的無線與pc不在一個局域網中,所以,只能在pc上用360wifi創建熱點(無線),然后手機連接熱點,再用wireshark抓360wifi網卡,查看數據。
一個頁面中的,多次請求,帶着sessionid發送的,但是回來分別返回不同的sessionid,cookie中的信息是set-cookie:jessionid=xxxxx,返回的sessionid跟發送的sessionid不同

分析
經過測試發現
1、sessionid丟失只在微信中打開網址時才會出現,尤其在安卓的微信中,丟失次數最多,iphone中幾乎不出現。
2、在非微信中,比如手機瀏覽器中,不會出現sessionid丟失
3、在pc瀏覽器中,也不會出現sessionid丟失

推理論證
至此,懷疑是服務器沒做session保持,經查證,服務器有2個tomcat,都放在騰訊雲上,做了黏性session,黏性session是通過hash ip,然后取余做的,所以懷疑是黏性session不起作用。
為了驗證這個猜測,通過不斷request,發現request一會到server1,一會又到server2,而且沒有規律可循。由於手機的ip是固定的,並且騰訊雲堅持他們的黏性session沒有問題,所以推測ip在中間傳輸過程被修改了。經過在服務器上抓包發現,騰訊雲收到的ip的確是變化的。經過以上的驗證加上網上search,原來凶手是微信內嵌瀏覽器對所有請求都做了代理,從而導致騰訊雲收到的ip發生了變化。

解決
由於微信內嵌瀏覽器對所有請求都做了代理,導致出去的ip不固定,從而導致騰訊雲服務器的黏性session(基於客戶端ip做的黏性session)失效。所以,解決方案有兩個,要么服務器端只用一台tomcat,要么tomcat做session共享,比如 session放在redis中。這樣server1產生的sessionid,即使到了server2,也能從redis中找到。

 

 

nginx ip_hash將所有請求轉發到一台機器 

 

問題描述:阿里雲nginx ip_hash將所有請求轉發到一台機器
排查:查看nginx的error.log, 發現大部分的client ip是來自於10.159.95網段

點擊(此處)折疊或打開

  1. 2015/10/25 12:01:03 [warn] 21580#0: *12412231 an upstream response is buffered to a temporary file /home/work/nginx/proxy_temp/2/55/0000075552 while reading upstream, client: 10.159.95.***, server: ***.***.***, request: "POST *** HTTP/1.0", upstream: "http://***", host: "***.***.***"

懷疑nginx未獲取到真實的用戶ip,而獲取到上游SLB集群的IP。

nginx官方網站中關於ip_hash的說明
Specifies that a group should use a load balancing method where requests are distributed between servers based on client IP addresses. The first three octets of the client IPv4 address, or the entire IPv6 address, are used as a hashing key. The method ensures that requests from the same client will always be passed to the same server except when this server is unavailable. In the latter case client requests will be passed to another server. Most probably, it will always be the same server as well.
飄紅字段的意思是,對於IPv4,ip_hash會使用IP的前3部分作為哈希的Key,一個SLB集群對應的網段都是一致的,導致ip_hash之后的請求全部落到一台upstream機器。

解決方案:讓nginx獲取到用戶的真實IP,使用real client ip做ip_hash
1. 重新編譯nginx, 增加--with-http_realip_module模塊
2. 在nginx.conf中http{}中,增加

點擊(此處)折疊或打開

  1. real_ip_header X-Forwarded-For;
  2. set_real_ip_from 0.0.0.0/0;
  3. real_ip_recursive on;

3. 重啟nginx,查看error.log檢查client: 對應日志,已經變成了用戶真實的外網出口IP
4. 檢查upstream的機器流量,已趨於均衡

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM