天天看点

如何让网络连接成功率从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连接失败的原因,也请读者朋友们分析分析。