[置頂] 騰訊朋友網網絡報卡


騰訊朋友網網絡報卡

原理分析:

最近看騰訊朋友網網絡報卡,發現騰訊的網路服務器有不少,當用戶鏈接慢時,頁面會請求不一樣是服務器,每一個服務器相同路徑下都存儲有同一張圖片,根據加載圖片的時間長短來選擇服務器,以便達到用戶訪問最適合本身,時間最短的服務器。javascript

實例分析:

1.記錄當前頁面開始時間time1css

2.循環請求每一個服務器下面的圖片,記錄圖片開始請求時間和結束時間,html

3.根據結束時間和請求時間差,選擇請求時間最短的服務器java

文檔構建

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9" />
    <title>小診所 - 朋友網(騰訊朋友)</title>

    <script type="text/javascript">
        var startLoad=+new Date();
    </script>

    <style type="text/css">
        *{margin:0;padding:0;}
        body{font:13px/1.8em Verdana,Helvetioa,Arial,sans-serif;background-color:#D2D1D0;color:#444444;}
        a{ color:#3366CC;text-decoration:none;}
        a:hover{color:#117CFF;text-decoration:underline;}
        .wrapper{position:relative;padding:1px;width:650px;margin:20px auto 0;border:solid #bbbbbb 1px;background-color:#ffffff;box-shadow:1px 1px 2px rgba(0,0,0,0.3);}
        .wrapper .wrapper-entry{background-color:#f4f4f4;}
        .c-title{margin:0 5px;padding:8px 10px;border-bottom:dotted #E0E0E0 1px;line-height:1.2em;font-size:18px;font-weight:bold;font-family:'Microsoft YaHei';}
        .c-box{padding:15px;}
        .c-foot{padding:5px 15px;font-size:12px;border-top:solid #e5e5e5 1px;background-color:#EFEFEF;}
        .c-btn-box,.c-rs{padding:0 5px;margin:15px 0;}
        .c-btn,.c-btn:visited{
            font-size:13px;
            background-color:#85AE09;
            display:inline-block;
            padding:5px 10px 6px;
            color:#FFF;
            text-decoration:none;
            border-radius:6px;
            box-shadow:0 1px 3px rgba(0,0,0.0.6);
            border-bottom:1px solid rgba(0,0,0,0.25);
            position:relative;
            cursor:pointer;
        }
        .c-btn:hover{text-decoration:none;background-color:#111;color:#fff;background-color:#7A9F09;}
        .c-btn:active{top:1px;};
        .c-rs{color:#717171;_height:5.4em;min-height:5.4em;line-height:1.8em;}
        .c-rs .title{font-size:14px;font-weight:bold;}
        .success{color:#81A809;}
        .error{color:#BF0000;}
        .c-over{position:absolute;text-align:center;width:250px;background:#fff;border:solid #ccc 1px;}
    </style>
</head>
<body>
    <div class="wrapper">
        <div class="wrapper-entry">
            <h1 class="c-title">
                朋友網小診所</h1>
            <div class="c-box">
                <p>
                    爲了讓您天天都能順暢地瀏覽朋友網,您可使用小診所進行診斷分析。</p>
                <p>
                    若是小診所沒有解決您的問題,您還能夠下載 <a href="http://guanjia.qq.com/" target="_blank" title="QQ電腦管家">
                        QQ電腦管家</a>、<a href="http://imgcache.qq.com/tools/emu/checknetwork.signed.zip" title="QQ空間網絡情況分析工具">QQ空間網絡情況分析工具</a>進一步進行診斷。</p>
                <div class="c-btn-box">
                    <a href="javascript:void(0);" title="點擊開始診斷" class="c-btn" id="J_Start">開始診斷</a>
                </div>
                <div class="c-rs" id="J_Result" style="display: none;">
                    <div id="J_RS_ISP">
                    </div>
                    <div id="J_RS_CACHE">
                    </div>
                </div>
            </div>
            <div class="c-foot">
                <a href="http://www.pengyou.com" title="返回朋友網">«返回朋友網</a>
            </div>
            <!-- <div class="c-over"><a href="#" title="" class="btn-over">診斷完成,返回朋友網</a></div> END-->
        </div>
    </div>
    <div id="Console">
    </div>

    <script type="text/javascript">
    Clinic.init({btn:'J_Start'});
    $.speed.set(1,67,3,+new Date(),startLoad);
    $.ping('/clinic/');
    </script>

</body>
</html>

公用JS函數:

這些函數有的是跟下面的請求函數定製的,因此你們能看懂大概什麼意思,作了哪些事就好了。
數據庫

function $(d){var ele=typeof(d)==='string'?document.getElementById(d):d;return ele;}
        String.prototype.trim=function(r){return this.replace(r||/^\s+|\s+$/g,"");};
        $.cookie=function(name,value,options){
            if(typeof value!='undefined'){
                options=options||{'domain':'pengyou.com',path:'/'};
                if(value===null){
                    value='';
                    options.expires=-1;
                }
                var expires='',date;
                if(options.expires&&(typeof options.expires=="number"||options.expires.toUTCString)){
                    if(typeof options.expires=="number"){
                        date=new Date();
                        date.setTime(date.getTime()+(options.expires*24*60*60*1000));
                    }else{
                        date=options.expires;
                    }
                    expirex=';expires='+date.toUTCString();
                }
                var path=options.path?';path='+(options.path):'',domain=';domain='+(options.domain?(options.domain):'pengyou.com'),
                secure=options.secure?';secure':'';
                document.cookie=[name,'=',encodeURIComponent(value),expires,path,domain,secure].join('');
            }else{
                var cookieValue='';
                if(document.cookie){
                    var cookies=document.cookie.split(';'),cookie;
                    for(var i=0,l=cookies.length;i<l;i++){
                        cookie=cookies[i].trim();
                        if(cookie.substring(0,name.length+1)==(name+"=")){
                            cookieValue=decodeURIComponent(cookie.substring(name,length+1));
                            break;
                        }
                    }
                }
                return cookieValue;
            }
       }
       function pgvGetUserInfo(){
            var m=document.cookie.match(/(^|;|\s)*pvid=([^;]*)(;|$)/);
            if(m){
                pvid=m[2]
            }else{
                var pvid=(Math.round(Math.random()*2147483647)*(new Date().getUTCMilliseconds()))%10000000000;
                if((/^http:\/\/((.*?)\.|)pengyou\.com\/.*/i).test(location.href)){
                    document.cookie="pvid="+pvid+";path=/;domain=pengyou.com;expires=Sun, 18 Jan 2038 00:00:00 GMT;";
                }else{
                    document.cookie="pvid="+pvid+";path=/:domain=qq.com;expires=Sun, 18 Jan 2038 00:00:00 GMT;";
                }
            }
            return "&pvid="+pvid;
       }
       $.ping=function(urlx,domainx,rurlx,rdomainx){
            domainx=domainx||'app.xiaoyou.com';
            rurlx=rurlx||'-';
            rdomainx=rdomainx||'xiaoyou.qq.com';
            var Url;
            if((/^http:\/\/((.*?)\.|)pengyou\.com\/.*/i).test(location.href)){
                Url="http://pingfor.pengyou.com";
            }else{
                Url="http://pingfor.qq.com";
            }
            Url+="/pingd?dm="+domainx+"&url="+urlx+"&tt=-"+"&rdm="+rdomainx+"&rurl"+escape(rurlx)+pgvGetUserInfo()+"&scr=-&scl=-&lang=-&java=1&cc=-&pf=-&tz=-8&ct=-&vs=3.3"
            new Image().src=Url+"&emu="+Math.random();
       }
       $.speed={set:function(f2,f3,id,value,basetime){ 
            var key=f2+'_'+f3,startTime,endTime,speed,loadTimes={};
            if(!this[key]){
                this[key]=[];
            }
            startTime=basetime||this[key][0]||startLoad;
            endTime=value||(+new Date());
            if(id!==0&&startTime!==undefined&&startTime!==null){
                speed=endTime-startTime;
            }else if(id===0){
                speed=endTime-1+1;
            }
            if(speed!==undefined){
                this[key][id]=speed;
            }
           },
           send:function(f2,f3,setting){
            setting=setting||{};
            var key=f2+'_'+f3,data=this[key],_arr=[];
            if(!data||data.length<=0){ return false; }
            for(var i=1;i<data.length;i++){
                if(data[i]){
                    _arr.push(i+'='+data[i]);
                }
            }
            var flags=[[f2,f3]],urls=[],copyTo=setting.copyTo;
            if(copyTo){
                if($.isArray(copyTo[0])){
                    flags=flags.concat(copyTo);
                }else{
                    flags.push(copyTo);
                }
            }
            var i=0,cur,times=_arr.join('&');
            for(;cur=flags[i++];){
                urls.push("http://isdspeed.qq.com/cgi-bin/r.cgi?flag1=164&flag2="+cur[0]+"&flag3="+cur[1]+"&"+times);
            }
            var i=0,l=urls.length;
            for(;i<l;++i){
                var imgSendTimePoint=new Image();
                imgSendTimePoint.src=urls[i];
            }
            this[key]=[];
           }};
           //237/240行傳入的參數:800160,1,51
           $.returncode=function(flag1,flag2,flag3,sampling,delay){
                sampling=sampling||100;                                 //計算sampling值,每次計算的值可能不同
                if(sampling<100){
                    if(Math.floor(Math.random()*100)>=sampling){ return; }      //隨機數大於小於100的sampling時返回,這裏多是要求sampling不能過小(好比:1,2,3...,應該儘量的大一點,猜想多是QQ服務器這樣要求的)
                }
                sampling=Math.ceil(100/sampling);                       //取大於等於參數(100/sampling)的最小整數
                delay=delay||0;                                         //判斷賦值delay
                flag2=flag2||1;                                         //判斷賦值flag2
                var url="http://isdspeed.qq.com/cgi-bin/v.cgi?flag1="+flag1+"&flag2="+flag2+"&1="+sampling+"&2="+delay;     //拼接URL
                if(flag3){
                    url+="&flag3="+flag3;
                }
                var imgSend=new Image();                                //初始化Image對象
                setTimeout(function(){imgSend.src=url},0);              //指定Image對象的src
           }
           function ctest(msg){                                         //向層Console裏面添加指定內容的div
                var b=document.createElement('div');
                b.innerHTML=msg;
                document.getElementById("Console").appendChild(b);
           }

請求函數Clinic解析:

Clinic.ISP={
                key:{                       //設置key屬性,裏面的參數固定
                    fast:'FAST',
                    old:'OLD',
                    store:'_store',
                    isstart:'_isstart'
                },
                _timeout:10000,             //設置超時時間
                test:function(callback){    //開始與服務器的測速
                    if(this[this.key.isstart]){ return false; }     //this[this.key.isstart]==true時,返回至關於lock(object)
                    this[this.key.isstart]=true;                    //設置this[this.key.isstart]=true表示開始執行
                    var that=this;                                  //賦值that=this
                    var dms=this.getDomains(),                      //獲取子域網址
                        startTime=+new Date(),
                        fn=function(img){
                            if(dms.length){
                                setTimeout(function(){
                                    that.request(dms.shift(),{complate:fn});    //執行request函數,傳入子域對象{domain:'ctc.'+'qzonestyle.gtimg.cn',isp:'ctc'}和{complate:fn} fn指當前函數,這樣函數內部在執行fn至關於遞歸
                                },0);
                            }else{
                                that.fix(callback,{                             //所有子域執行完成後執行提示是否返回朋友網
                                    start:startTime,
                                    end:+new Date()
                                });
                            }
                        };
                        this._showMsg('正在爲您選擇更快的服務器,請耐心等候。');
                        fn();                                                   //開始執行fn函數
                },
                fix:function(success,setting){                                  //所有子域執行完成後執行的函數,success->函數,setting->{start:startTime,end:+new Date()}
                    setting=setting||{};                                        //初始化setting
                    var fast=this[this.key.fast];                               //獲取this.key.fast對象
                    if(fast){                                                   //若是fast對象存在
                        success&&success(fast);                                 //執行傳進來的函數:fn/callback
                        var old={                                               //初始化old對象
                            isp:this.get(),
                            cost:null
                        };
                        this[this.key.old]=old;                                 //本地存儲old對象
                        $.cookie('ptisp',fast.isp,{expires:1,path:'/'});        //本地cookie存儲參數:'ptisp',子域地址:'ctc.qzonestyle.gtimg.cn',{expires:1,path:'/'}
                        this._statistic(old,fast,{                              //執行_statistic函數參數分別是:old,fast,{start:setting.start,end:setting.end}
                            start:setting.start,
                            end:setting.end
                        });
                        this._showMsg('已經爲您選擇了更快的服務器','success');  //提示正在測速
                        $.returncode(800160,1,51);                              //執行returncode函數請求數據
                    }else{
                        this._showMsg('對不起,彷佛您的電腦掉線了,選擇服務器操做沒法完成。','error');  //判斷fast若是不存在則可能斷網
                        $.returncode(800160,1,51);                              //執行returncode函數請求數據
                    }
                    this.rest();                                                //初始化本地數據
                },
                get:function(){                                                 //獲取本地cookie存儲的子域地址
                    var isp=$.cookie('ptisp');
                    return isp;
                },
                //傳入子域對象{domain:'ctc.'+'qzonestyle.gtimg.cn',isp:'ctc'}和{complate:fn} 
                request:function(domainInfo,config){
                    var _timeout=this._timeout;                                 //設置超時時間
                    config=config||{};                                          //判斷賦值config
                    this._showNowcheck(domainInfo);                             //顯示請求子域提示信息
                    var src='http://'+domainInfo.domain+'/qzonestyle/xiaoyou_portal_v1/img/logo_qbar_a0a48.gif';        //不一樣域請求的相同的圖片 PS:這裏是正題的開始
                    var img=new Image(),                                        //初始化Image對象
                        start=+new Date(),                                      //初始化啓動時間
                        that=this;
                    var timer,timeStart=+new Date();
                    img.onload=function(){                                      //設置Image開始加載事件
                        var end=+new Date();                                    //初始化結束時間
                        var cost=end-start;                                     //初始化時間差
                        this.onload=this.onerror=null;                          //清除Image對象的onload,onerror事件
                        clearTimeout(timer);                                    //清除定時器
                        that._timeout=Math.min(that._timeout,cost);             //比較超時時間和加載結束時間,返回相對小的值
                        config.complate&&config.complate(this);                 //執行傳過來的函數fn
                        var rs={                                                //初始化re對象包括:isp->子域,domain->子域地址,error->是否出錯,cost->加載時間差,start->開始時間,end->加載完成時間
                            isp:domainInfo.isp,
                            domain:domainInfo.domain,
                            error:0,
                            cost:cost,
                            start:start,
                            end:end
                        };
                        that._saveResult(rs);                                   //保存rs對象
                    };
                    img.onerror=function(d){                                    //設置Image加載出錯事件
                        this.onload=this.onerror=null;                          //清除Image對象的onload,onerror事件
                        clearTimeout(timer);                                    //清除定時器
                        config.complate&&config.complate(this);                 //執行傳過來的函數fn
                        var rs={                                                //初始化rs對象
                            isp:domainInfo.isp,
                            domain:domainInfo.domain,
                            error:d&&d.timeout?'timeout':'onerror'
                        };
                        that._saveResult(rs);
                    };
                    timer=setTimeout(function(){
                        img.onerror({timeout:true});
                    },_timeout+300);
                    src=src+(src.indexOf('?')===-1?'?':'&')+'_='+(+new Date())+'&_='+Math.random();
                    img.src=src;
                },
                _saveResult:function(data){                                     //賦值this.key.store,this.key.fast
                    var key=this.key.store;
                    this[key]=this[key]||[];
                    if(!data.error){                                            //若是error=0時,若是data.cost存在賦值this.key.fast
                        this[key].push(data);
                        var keyFast=this.key.fast,
                            fast=this[keyFast];
                        if(data.cost){
                            if(!fast||data.cost<fast.cost){                     //當this.key.fast對象存在時,若是新的服務器請求時間少於this.key.fast對象存儲的時間,則替換
                                this[keyFast]=data;
                            }
                        }
                    }
                },
                _getResult:function(){
                    var key='_rsstore';
                    return this[key];
                },
                getIsps:function(){ var l=['ctc','cnc','edu','cn','cm','os','']; return l;},        //返回子域前綴數組
                getHosts:function(){ var h=['qzonestyle.gtimg.cn'];return h;},                      //返回網站網址數組
                getDomains:function(){                                                              //返回組合子域與網站網址後的網站網址
                    var isps=this.getIsps(),                                                        //獲取子域前綴數組
                        hosts=this.getHosts(),                                                      //獲取網站網址數組
                        sr=[];                                                                      //組合後的網站網址
                    while(hosts.length>0){
                        var i=0,l=isps.length,cur;
                        var h=hosts.shift();                                                        //去除第一個數組對象,並將其從數組中刪除
                        for(;i<l;i++){
                            cur=isps[i];
                            sr.push({                                                               //添加對象到數組中,組合後的數組對象爲:{domain:'ctc'+'qzonestyle.gtimg.cn',isp:'ctc'}
                                domain:(cur?cur+'.':'')+h,
                                isp:cur
                            });
                        }
                    }
                    return sr;
                },
                rest:function(){                                                                    //重置對象
                    this._timeout=10000;
                    this[this.key.fast]=null;
                    this[this.key.old]=null;
                    this[this.key.store]=null;
                    this[this.key.isstart]=null;
                },
                _showMsg:function(msg,type){                                                        //顯示提示信息,不過多介紹了,你們看看就應該能懂
                    var box=$('J_RS_ISP');
                    if(box){
                        if(type==='success'){
                            msg='\u221A '+msg;     //√
                        }else if(type==='error'){
                            msg='\u00D7 '+msg;     //×
                        }
                        box.className=type||'';
                        box.innerHTML=msg;
                    }
                },
                _showNowcheck:function(info){                                                       //顯示請求子域提示信息
                    $('J_Result').style.display='';
                    var box=$('J_RS_ISP'),
                        spid='J_RS_ISP_DETAIL',
                        sp=$(spid);
                    if(!sp){
                        sp=document.createElement('p');
                        sp.setAttribute('id',spid);
                        box.appendChild(sp);
                    }
                    sp.innerHTML=' '+info.domain;
                },
                _statistic:function(old,now,pay){
                    old.cost&&$.speed.set(1,67,1,old.end,old.start);
                    now.cost&&$.speed.set(1,67,2,now.end,now.start);
                    pay.end&&$.speed.set(1,67,4,pay.end,pay.start);
                    $.speed.send(1,67);
                    var ispf1={ctc:800152,cnc:800153,edu:800154,cn:800155,cm:800156,os:800157,v6:800158};
                    var ispid={ctc:51,cnc:52,edu:53,cn:54,cm:55,os:56,v6:57};
                    var ispf2=old.isp===now.isp?1:2;
                    ispf1=ispf1[old.isp]||8800159;
                    ispid=ispid[now.isp]||58;
                    $.returncode(ispf1,ispf2,ispid);
                }
           };
           Clinic.Cache={                                                                       //指定Clinic對象Cache事件,清除緩存
                clear:function(){
                    
                }
           };

效果展現:

結語:

但願有朝一日能把騰訊網站上的好東東都學會,若是能弄來騰訊的數據庫什麼的最好了 學習學習 偷笑
數組

相關文章
相關標籤/搜索