天天看點

如何讓網絡連接配接成功率從99.0%提升到99.999%

如何讓網絡連接配接成功率從99.0%提升到99.999%

——使用webSocket和Http切換機制提升網絡連接配接的成功率

業務背景: 開發的遊戲項目,用戶端使用js(ts/egret引擎)開發,服務端使用java,網絡通信使用websocket。項目上線後偶現使用者連接配接伺服器失敗的情況,我們自己幾乎重制不出來。通過列印日志發現使用者使用http請求php檔案可以正常請求,隻是使用websocket連接配接失敗。使用者比例大概在 0.5%-1%左右,雖然隻是偶現問題,且比例不是很高,但當推廣期幾十上百萬使用者級别時受影響的使用者數量還是很可觀的。

初步排查: 檢查伺服器配置、服務端網絡連接配接代碼、用戶端網絡連接配接代碼,都沒有發現可能的原因。最終發現通過更換域名可以連接配接成功。于是有了相容解決方案。

換域名方案: 項目的java伺服器綁定了域名s1001-game1.company.com,同時對這台伺服器綁定域名game1.company.com,預設先連接配接s1001-game1.company.com,當連接配接失敗時,就連接配接game1.company.com,通過這種方式,很多連不上的使用者連接配接成功了!我們以為問題得到了解決!但是通過日志發現,連接配接的成功率隻是從99.0%提升到約99.75%,仍然有極少數使用者連接配接不上。問題在哪裡呢?我們又增加了一個新機制。

換Http方案: 既然http能記錄日志,那就讓伺服器同時支援http請求,用長連接配接來實作伺服器向用戶端推送消息的需求。針對換域名方案也連接配接失敗的使用者再切換成http連接配接,通過這種方式這部分使用者也能連接配接成功了,最終使用者連接配接成功率為99.999%(作為程式員必須嚴謹謹慎,絕對不能說100%,哈哈)

核心代碼:

private host:string = "s1001-game1.company.com:80xx";
private closeSocket = false; //網絡連接配接方式:預設使用websocket,true表示http
private loadStep:number;
private reConnetTimer:number;
private showError:boolean;

Net.instance.addEventListener(Net.FAULT,this.fault,this);
public fault(event:egret.Event):void{
    if(this.showError) return;
    this.showError = true;

    if(this.reConnetTimer) egret.clearTimeout(this.reConnetTimer);
    if(loadStep < 100 ){//表示首次連接配接伺服器
        let errormsg = "fault=" + event.data + "_" + loadStep;
		if(loadStep == 10){ //換域名重連
            host = host.replace(/^s\d\d\d\d-/, ""); //去掉s1001-變成game1.company.com:80xx
            loadStep = 11;
            this.reConnetTimer = egret.setTimeout(()=>{ this.reConnect(true, 2); }, this, 500);
            log(errormsg + "換域名重連:" + host, false);
            return;
        }
        else if(loadStep == 11){ //websocket連結不上,切換成http通信
            closeSocket = true; //網絡連接配接配置,表示
            loadStep = 12;
            this.reConnetTimer = egret.setTimeout(()=>{ this.reConnect(true, 2); }, this, 30); 
            log(errormsg + "換HTTP重連:" + host, false);
            return;
        }
        else if(loadStep == 12){
            closeSocket = false;
        }
        log(errormsg, false);
        Alert.show("登入遇到網絡問題,請重新登入",'系統提示',()=> {},"登入");
        return;
    }
}
           

最終,這個網絡連接配接的問題得以解決。但是我們并沒有找到預設域名websocket連接配接失敗的原因,也請讀者朋友們分析分析。