推薦:更多技術團隊分享文章 關注:MAYOU18技術專欄
貴金屬wap版直播間上線後,偶爾有用戶反饋,在進入wap直播間的時候,出現空白頁面,可是從新刷新又能夠正常顯示了。咱們曾一度認爲是網絡請求異常或兼容問題,直到開發PC版直播間,在進行調試中,一樣遇到了「白屏」問題,才引發了足夠重視,並進行了問題跟蹤與分析。如今跟你們分享一下,這種偶然現象出現的緣由。html
咱們的直播間落地頁在fa.163.com 系統,而直播間內容,是經過 向直播間系統 qz.fa.163.com 發起Ajax請求獲取的。在出現「白屏」的時候,能夠經過瀏覽器的調試窗口,能夠看到出現下面的報錯:nginx
從上述錯誤提示文案中能夠看到,問題首先和 跨域 有關。web
何爲跨域後端
從字面上理解爲「跨域名」,
瀏覽器不能執行其餘網站的腳本,然而,跨域不只僅侷限於域名這一項。只要協議、域名、端口有任何一個不一樣,都被看成是不一樣的域。 這是因爲>同源策略的限制,從一個域上加載的腳本不容許訪問另一個域的文檔屬性。雖然在瀏覽器中,<script>、<img>、<iframe>、<link>等標籤都>可>以加載跨域資源,而不受同源限制,但瀏覽器會限制腳本中發起的跨域請求。好比,使用 XMLHttpRequest 對象和Fetch發起 HTTP 請求就必須遵照同源策略。跨域同源策略/SOP(Same origin policy)是一種約定,它是瀏覽器最核心也最基本的安全功能,若是缺乏了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。SOP要求兩個通信地址的協議、域名、端口號必須相同,不然兩個地址的通信將被瀏覽器視爲不安全的,並被block下來。瀏覽器
舉個例子:從貴金屬主站 http://fa.163.com 發起請求訪問如下url:
緩存解決跨域tomcat
在實際應用中有多種方式來解決跨域問題,相信在實踐中都會用到其中的某些方案:安全
1.JSONP (無狀態鏈接,不能獲悉鏈接狀態和錯誤事件,並且只能走GET的形式)服務器
2.iframe形式
3.服務器代理
頁面直接向同域的服務端發請求,服務端進行跨域處理或爬蟲後,再把數據返回給客戶端頁。
4.CORS
CORS(Cross-Origin Resource Sharing)跨域資源共享,定義了必須在訪問跨域資源時,瀏覽器與服務器應該如何溝通。CORS背後的基本思想就>是使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功仍是失敗。目前,全部瀏覽器都支持該功能,IE瀏覽器不能低>於IE10。整個CORS通訊過程,都是瀏覽器自動完成,不須要用戶參與。對於開發者來講,CORS通訊與同源的AJAX通訊沒有差異,代碼徹底同樣。瀏>覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受。
CORS方式實現:
瀏覽器在發出CORS請求時會在頭信息之中增長一個Origin字段;
後端返回代碼中增長三個字段
1 |
header(「Access-Control-Allow-Origin」:「」); // 必選 容許全部來源訪問 |
5.nginx反向代理
nginx是一個高性能的web服務器,經常使用做反向代理服務器。nginx做爲反向代理服務器,就是把http請求轉發到另外一個或者一些服務器上。經過把本地一個url前綴映射到要跨域訪問的web服務器上,就能夠。
爲了解決跨域問題,咱們選擇方案d , 在直播間的過濾器中,統一添加了以下代碼:
1 |
|
從錯誤提示文案中,咱們還能夠看到錯誤提示的關鍵點 「http://fa.163.com」 that is not equal to the supplied origin. Origin ‘https://fa.163.com' is therefore not allowed access.
目前咱們的系統同時支持http訪問和https訪問,可是爲何使用 http訪問 ,返回的header中倒是 https 協議呢?
經過屢次模擬,確認出現問題的請求中,Request URL使用的協議和 response返回的headers中的 Access-Control-Allow-Origin 中的 協議確實不一致,且還有一個特性,X-Cached 爲 HIT,以下圖:
命中了緩存的請求,出現了協議不一致?
忽然想到,這個接口,咱們配置了nginx 緩存,那必然和nginx緩存有關了。
Nginx 緩存
Nginx (engine x) 是一個高性能的HTTP和反向代理服務器。
首先從源服務器(內部網絡上的web服務器)上獲取內容,而後把內容返回給用戶,同時,也會把內容保存到代理服務器上一份,這樣往後再接收一樣的信息請求時,他會把本地緩存裏的內容直接發給用戶,以此減小後端web服務器的壓力,提升響應速度。這其實就是緩存服務器所實現的功能。以下圖所示。
進入直播間後,首先須要查詢直播內容是否有更新,而這個接口客戶端會以5s間隔輪詢,爲了減小tomcat的壓力,咱們配置了nginx緩存。配置以下:
其中:
proxy_cache_methods: 用來設置HTTP哪些方法會被緩存,直播間接口配置了GET、HEAD、POST; proxy_cache_valid: 用來設置對不一樣HTTP狀態碼的不一樣緩存時間。直播間接口配置了對於 返回值爲200的狀態碼,緩存5秒; proxy_cache_min_uses: 用來設置多少次訪問後,應答值會被緩存,配置爲3次; proxy_cache_key: 設置Web緩存的key proxy_cache: 用來設置哪一個緩存區將被使用,並定義緩存區的名稱
經過上述配置,咱們能夠看到 proxy_cache_key 配置中,只配置了host + uri + 參數,但沒有配置協議,因此不管用http訪問,仍是https訪問,只要被緩存後,返回的內容都是同樣的,而不會區分http或https。從而引發了跨域問題。
至此,問題分析完畢。
跟運維同窗溝通後,經過修改nginx配置,將協議類型scheme加入到緩存查找的判斷參數中,配置以下。
問題獲得瞭解決。
上述「慘案」 ,是 跨域、nginx緩存、http/https協議 這三種條件同時出現引起的。若是不涉及跨域,混用 http/https協議 + nginx緩存,其實也是沒有問題的。可是一旦出現了跨域使用,必須 在nginx 緩存配置中,配置 scheme + host + uri + 參數。