距離上個迭代過了很長時間,中間經歷了很多事情,也在每個空余時間構思了這個迭代的東西以及下個迭代要做的東西。時間周期稍微長了,望見諒。
而且,至今這個開源庫的start也已經到了165個了,會支持關注和研究的。
首先解決了上個迭代遇到的問題進行完善和修復:
1. 上個迭代做ajax timeout設置的時候,手抖將timeout不小心設置成timeoutEvent,這期做了修復
2. 解決全局配置中配置額外參數,批量檢查時會參數錯誤問題。
引入新的功能:
1. 增加瀏覽器發送請求的錯誤監控和搜集
應用場景:
前端開發依賴的東西比較多,比如宿主環境(瀏覽器)、以及數據接口(自己服務器或者第三方Api等等),上個迭代進行了瀏覽器錯誤搜集,可以分析用戶在不同環境下宿主的使用率和差異以及問題。但是對於用戶的數據請求一直沒有做監控,因為用戶在不同的場景、網絡狀況下乃至在開發或者發布中將接口地址寫錯了,導致出現問題。
全局配置:
errStatus: { isOpenErr: true, // 是否開啟錯誤搜集
errURL: 'http://localhost:8072', // 錯誤搜集地址
},
代碼如下:
//監控ajax請求的錯誤日志
uploadAjaxError: function (obj) { // 過濾錯誤接口
if (initParam.errStatus.isOpenErr) { if (obj.errUrl !== initParam.errStatus.errURL) { tempObj.post(initParam.errStatus.errURL, obj) } } // 記錄錯誤信息,以便策略做判斷
if (selfData.errAjax[obj.errUrl] === undefined) { selfData.errAjax[obj.errUrl] = 1 } else { selfData.errAjax[obj.errUrl] += 1 } // 判斷是否開啟服務切換,以及驗證策略切換
if (initParam.serviceSwitching.isOpen){ // 驗證策略
selfData.isNeedSwitching = initParam.serviceSwitching.strategies(selfData.errAjax) } }
覆蓋面以及數據:
請求的錯誤搜集,將覆蓋4xx、5xx、0、onerror以及timeout狀態
PS:在瀏覽器api中,只讀屬性 XMLHttpRequest.status 返回了XMLHttpRequest 響應中的數字狀態碼。status 的值是一個無符號短整型。在請求完成前,status的值為0。值得注意的是,如果 XMLHttpRequest 出錯,瀏覽器返回的 status 也為0。
數據上傳格式:
/* * 請求錯誤搜集 * type:錯誤類型 * errInfo:錯誤的請求參數 * errLine:請求狀態 * Browser:宿主環境(瀏覽器) */ tool.uploadAjaxError({ type: 'request', errInfo: JSON.stringify(ajaxSetting.data), errLine: xhr.status, Browser: navigator.userAgent })
測試結果:
a. onerror錯誤:
b. 4XX錯誤、5XX錯誤、0錯誤
c. timeout錯誤
2. 前端負載均衡(將請求均衡打到不同的服務器上)
應用場景:
現在很多公司更多使用ngx做負載均衡,使用node第一層hold住所有流量,然后通過ngx進行分發到不同的服務器上做負載,避免在一台服務器上讀寫造成資源競爭等等,結構如下圖:
但是,如果在超大流量的一種狀況下,前端作為請求的發出方,完全有能力在發出階段就將請求打到不同的負載服務器上,然后再通過ngx再進行二次負載均衡,結構如下如:
全局配置:
// 負載均衡配置
loadBalancing: { isOpen: false, // 是否開啟負載
cluster: ['http://localhost:8076','http://localhost:8099'] // 配置地址
},
代碼實現:
/* * 判斷是否為其他域的請求 * * 改方法中處理負載均衡方案 * 1. 對於前后端分離,直接請求域名的方案 支持 * 2. 對於直接請求本服務器的請求,暫時不做處理,讓ngx做負載均衡 不支持 * * */ checkRealUrl: function (param, that) { var temp; if (/http:\/\/|https:\/\//.test(param.url)) { temp = param.url; // 針對請求,負載均衡到配置域名 PS:負載均衡優先級 > 宕機切換優先級
if (param.errStatus.errURL !== temp){ // 錯誤搜集接口都不走
if (param.loadBalancing.isOpen){ // 負載打開肯定走負載
temp = param.url.replace(/^(http:\/\/|https:\/\/)/, '') .replace(/^.*?\//, param.loadBalancing.cluster[tool.random(param.loadBalancing.cluster.length - 1, 0)] + '/$`') }else{ // 如果負載沒開,宕機切換打開,則走介個
if (param.serviceSwitching.isOpen && selfData.isNeedSwitching){ temp = param.url.replace(/^(http:\/\/|https:\/\/)/, '') .replace(/^.*?\//, param.serviceSwitching.backupUrl + '/$`') } } } } else { temp = param.baseURL + param.url if (param.errStatus.errURL !== temp){ if (param.loadBalancing.isOpen){ temp = param.loadBalancing.cluster[tool.random(param.loadBalancing.cluster.length - 1, 0)] + param.baseURL + param.url }else{ // 如果負載沒開,宕機切換打開,宕機策略成功則走介個
if (param.serviceSwitching.isOpen && selfData.isNeedSwitching){ temp = param.serviceSwitching.backupUrl + param.baseURL + param.url } } } } that.currentUrl = temp return temp; },
隨機函數校驗:
因為前端需要通過一個偽隨機數隨機獲取一個數值,然后通過這個數值去取負載配置的域名,為了保證隨機打點的均衡性,這里將測試在指數級增長下隨機打點5次的狀況
測試代碼:
// 偽隨機數函數
random(max, min) { return Math.floor(Math.random() * (max - min + 1) + min); },
案例:
a. 隨機5個,10次
b. 隨機5個,100次
c. 隨機5個,1000次
d. 隨機5個,10000次
e. 隨機5個,100000次
結果:在指數級增長的過程中,打點越來越均衡,相對偽隨機數的分布取值也越來越均衡
測試結果:
3. 宕機切換(支持策略)
應用場景:
在日常用戶使用請求接口的時候,用戶在點擊一個按鈕的時候,如果一次接口請求失敗,在人性角度去看,用戶肯定會再一次去點擊觸發請求,多次按了都沒效果,才會確認這個功能是沒用的。如果,在這個時候,這個場景下,用一個正確的策略在用戶點擊時候,如果本地請求失敗,支持切換備用域名,這樣可以有效的挽回流失用戶。
全局配置:
// 宕機切換
serviceSwitching:{ isOpen: false, // 是否開啟
// 宕機策略(data為記錄的錯誤請求以及數量,如果達到策略返回true,否則false)
strategies:function (data) { let num = 0
for (var key in data){ num = data[key] } if (num === 5){ return true }else{ return false } }, backupUrl:'http://localhost:8033' // 備用域名
},
代碼實現:
同負載均衡的那一大堆代碼,可以向上看。
測試案例(在策略中我綁定了如果錯誤連續積累5次之后將切換備用接口):
總結:這一期的迭代需求中已經將ajax所能涉及的應用場景全部挖掘的快消耗殆盡了,如果還有什么使用場景,可以去github提個issues。
github地址:https://github.com/GerryIsWarrior/ajax 可以點個star,持續研究下去
號外:有一次的測試中,意外突然發現,一個使用過的請求對象是可以重復利用的,而且一套創建流程從2000多毫秒一下子降級到200毫秒了,so,下一次迭代將所一個請求連接池,重復利用每次創建完成的對象,將每次的請求速度縮短到更快的一個層次,期待中...