ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>作爱视频免费观看视频在线播放激情网 ,亚洲视频综合在线,最新国产在线视频http://www.aygfsteel.com/jelver/category/31068.html“一直很多äh说我是天才,但我却相信这个世界没有天才。如果没有卓­‘Šçš„努力和娴熟的球性,你永˜qœä¸ä¼?x¨¬)踢出精彩的­‘³çƒã€‚我从来不会(x¨¬)低估努力的重要性,而这正是我对自己的要求。â€? ----------------------------------------------------------------------------¾|—纳ž®?d¨¡ng)èé_ž®¼å¥¥(Ronaldinho)-------- “不要叫我神童!我不是神童!我所获得的一切成ž®±ï¼Œéƒ½æ˜¯æˆ‘用汗水和刻苦训¾lƒæ¢æ¥çš„åQâ€?--------------------------丁俊辉(中国斯诺克公开赛冠军)--- zh-cnFri, 16 May 2008 04:49:32 GMTFri, 16 May 2008 04:49:32 GMT60用Java实现断点¾l­ä¼ (HTTP)http://www.aygfsteel.com/jelver/articles/200827.html冰河快狼冰河快狼Fri, 16 May 2008 03:12:00 GMThttp://www.aygfsteel.com/jelver/articles/200827.htmlhttp://www.aygfsteel.com/jelver/comments/200827.htmlhttp://www.aygfsteel.com/jelver/articles/200827.html#Feedback0http://www.aygfsteel.com/jelver/comments/commentRss/200827.htmlhttp://www.aygfsteel.com/jelver/services/trackbacks/200827.html本文介绍了一¿Uåˆ©ç”?Java 来实现断点箋传的æ–ÒŽ(gu¨©)³•ã€?/blockquote>

断点¾l­ä¼ çš„原ç?/span> åŽŸæ–‡http://www.ibm.com/developerworks/cn/java/joy-down/index.html

其实断点¾l­ä¼ çš„原理很½Ž€å•,ž®±æ˜¯åœ¨Http的请求上和一般的下蝲有所不同而已ã€?
打个比方åQŒæµè§ˆå™¨è¯äh±‚服务器上的一个文æ—Óž¼Œæ‰€å‘出的请求如下:(x¨¬)
å‡è®¾æœåŠ¡å™¨åŸŸåäØ“(f¨´)wwww.sjtu.edu.cnåQŒæ–‡ä»¶åä¸ºdown.zipã€?
GET /down.zip HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
excel, application/msword, application/vnd.ms-powerpoint, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Connection: Keep-Alive

服务器收到请求后åQŒæŒ‰è¦æ±‚å¯ÀL‰¾è¯äh±‚的文ä»Óž¼Œæå–æ–‡äšg的信息,然后˜q”回¾l™æµè§ˆå™¨åQŒè¿”回信息如下:(x¨¬)

200
Content-Length=106786028
Accept-Ranges=bytes
Date=Mon, 30 Apr 2001 12:56:11 GMT
ETag=W/"02ca57e173c11:95b"
Content-Type=application/octet-stream
Server=Microsoft-IIS/5.0
Last-Modified=Mon, 30 Apr 2001 12:56:11 GMT

所谓断点箋传,也就是要从文件已¾lä¸‹è½½çš„地方开始ç‘ô¾l­ä¸‹è½½ã€‚所以在客户端浏览器传给 Web服务器的时候要多加一条信æ?-从哪里开始ã€?
下面是用自己¾~–的一ä¸?‹¹è§ˆå™?来传递请求信息给Web服务器,要求ä»?000070字节开始ã€?
GET /down.zip HTTP/1.0
User-Agent: NetFox
RANGE: bytes=2000070-
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2

仔细看一下就ä¼?x¨¬)发现多了一行RANGE: bytes=2000070-
˜q™ä¸€è¡Œçš„æ„æ€å°±æ˜¯å‘Šè¯‰æœåС噍down.zip˜q™ä¸ªæ–‡äšgä»?000070字节开始传åQŒå‰é¢çš„字节不用传了ã€?
服务器收到这个请求以后,˜q”回的信息如下:(x¨¬)
206
Content-Length=106786028
Content-Range=bytes 2000070-106786027/106786028
Date=Mon, 30 Apr 2001 12:55:20 GMT
ETag=W/"02ca57e173c11:95b"
Content-Type=application/octet-stream
Server=Microsoft-IIS/5.0
Last-Modified=Mon, 30 Apr 2001 12:55:20 GMT

和前面服务器˜q”回的信息比较一下,ž®×ƒ¼š(x¨¬)发现增加了一行:(x¨¬)
Content-Range=bytes 2000070-106786027/106786028
˜q”å›žçš„ä»£ç ä¹Ÿæ”¹äØ“(f¨´)206了,而不再是200了ã€?

知道了以上原理,ž®±å¯ä»¥è¿›è¡Œæ–­ç‚¹ç®‹ä¼ çš„¾~–程了ã€?





回页�/strong>


Java实现断点¾l­ä¼ çš„关键几ç‚?/span>

  1. (1)用什么方法实现提交RANGE: bytes=2000070-�
    当然用最原始的Socket是肯定能完成的,不过那样太费事了åQŒå…¶å®žJavaçš„net包中提供了这¿UåŠŸèƒ½ã€‚ä»£ç å¦‚ä¸‹ï¼š(x¨¬)

    URL url = new URL("http://www.sjtu.edu.cn/down.zip");
    HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection();

    //讄¡½®User-Agent
    httpConnection.setRequestProperty("User-Agent","NetFox");
    //讄¡½®æ–­ç‚¹¾l­ä¼ çš„开始位¾|?
    httpConnection.setRequestProperty("RANGE","bytes=2000070");
    //获得输入‹¹?
    InputStream input = httpConnection.getInputStream();

    从输入流中取出的字节‹¹å°±æ˜¯down.zipæ–‡äšgä»?000070开始的字节‹¹ã€‚大家看åQŒå…¶å®žæ–­ç‚¹ç®‹ä¼ ç”¨Java实现èµäh¥˜q˜æ˜¯å¾ˆç®€å•的吧。接下来要做的事ž®±æ˜¯æ€Žä¹ˆä¿å­˜èŽ·å¾—çš„æµåˆ°æ–‡ä»¶ä¸­åŽÖMº†ã€?

  2. 保存文äšg采用的方法ã€?
    我采用的是IO包中的RandAccessFile¾c…R€?
    操作相当½Ž€å•,假设ä»?000070处开始保存文ä»Óž¼Œä»£ç å¦‚下åQ?
    RandomAccess oSavedFile = new RandomAccessFile("down.zip","rw");
    long nPos = 2000070;
    //定位文äšg指针到nPos位置
    oSavedFile.seek(nPos);
    byte[] b = new byte[1024];
    int nRead;
    //从输入流中读入字节流åQŒç„¶åŽå†™åˆ°æ–‡ä»¶ä¸­
    while((nRead=input.read(b,0,1024)) > 0)
    {
    oSavedFile.write(b,0,nRead);
    }

æ€Žä¹ˆæ øP¼Œä¹Ÿå¾ˆ½Ž€å•吧。接下来要做的就是整合成一个完整的½E‹åºäº†ã€‚包括一¾pÕdˆ—的线½E‹æŽ§åˆ¶ç­‰½{‰ã€?





回页�/strong>


断点¾l­ä¼ å†…核的实çŽ?/span>

主要用了6个类åQŒåŒ…括一个测试类ã€?
SiteFileFetch.java负责整个文äšg的抓取,控制内部¾U¿ç¨‹(FileSplitterFetch¾c?ã€?
FileSplitterFetch.java负责部分文äšg的抓取ã€?
FileAccess.java负责文äšg的存储ã€?
SiteInfoBean.java要抓取的文äšg的信息,如文件保存的目录åQŒåå­—,抓取文äšgçš„URL½{‰ã€?
Utility.java工具¾c»ï¼Œæ”¾ä¸€äº›ç®€å•çš„æ–ÒŽ(gu¨©)³•ã€?
TestMethod.java‹¹‹è¯•¾c…R€?

下面是源½E‹åºåQ?/p>
/*
            **SiteFileFetch.java
            */
            package NetFox;
            import java.io.*;
            import java.net.*;
            public class SiteFileFetch extends Thread {
            SiteInfoBean siteInfoBean = null; //æ–‡äšg信息Bean
            long[] nStartPos; //开始位¾|?
            long[] nEndPos; //¾l“束位置
            FileSplitterFetch[] fileSplitterFetch; //子线½E‹å¯¹è±?
            long nFileLength; //æ–‡äšg长度
            boolean bFirst = true; //是否½W¬ä¸€‹Æ¡å–æ–‡äšg
            boolean bStop = false; //停止标志
            File tmpFile; //æ–‡äšg下蝲的äÍ(f¨´)æ—¶ä¿¡æ?
            DataOutputStream output; //输出到文件的输出‹¹?
            public SiteFileFetch(SiteInfoBean bean) throws IOException
            {
            siteInfoBean = bean;
            //tmpFile = File.createTempFile ("zhong","1111",new File(bean.getSFilePath()));
            tmpFile = new File(bean.getSFilePath()+File.separator + bean.getSFileName()+".info");
            if(tmpFile.exists ())
            {
            bFirst = false;
            read_nPos();
            }
            else
            {
            nStartPos = new long[bean.getNSplitter()];
            nEndPos = new long[bean.getNSplitter()];
            }
            }
            public void run()
            {
            //获得文äšg长度
            //分割文äšg
            //实例FileSplitterFetch
            //启动FileSplitterFetch¾U¿ç¨‹
            //½{‰å¾…子线½E‹è¿”å›?
            try{
            if(bFirst)
            {
            nFileLength = getFileSize();
            if(nFileLength == -1)
            {
            System.err.println("File Length is not known!");
            }
            else if(nFileLength == -2)
            {
            System.err.println("File is not access!");
            }
            else
            {
            for(int i=0;i<nStartPos.length;i++)
            {
            nStartPos[i] = (long)(i*(nFileLength/nStartPos.length));
            }
            for(int i=0;i<nEndPos.length-1;i++)
            {
            nEndPos[i] = nStartPos[i+1];
            }
            nEndPos[nEndPos.length-1] = nFileLength;
            }
            }
            //启动子线½E?
            fileSplitterFetch = new FileSplitterFetch[nStartPos.length];
            for(int i=0;i<nStartPos.length;i++)
            {
            fileSplitterFetch[i] = new FileSplitterFetch(siteInfoBean.getSSiteURL(),
            siteInfoBean.getSFilePath() + File.separator + siteInfoBean.getSFileName(),
            nStartPos[i],nEndPos[i],i);
            Utility.log("Thread " + i + " , nStartPos = " + nStartPos[i] + ", nEndPos = " + nEndPos[i]);
            fileSplitterFetch[i].start();
            }
            // fileSplitterFetch[nPos.length-1] = new FileSplitterFetch(siteInfoBean.getSSiteURL(),
            siteInfoBean.getSFilePath() + File.separator + siteInfoBean.getSFileName(),nPos[nPos.length-1],nFileLength,nPos.length-1);
            // Utility.log("Thread " + (nPos.length-1) + " , nStartPos = " + nPos[nPos.length-1] + ",
            nEndPos = " + nFileLength);
            // fileSplitterFetch[nPos.length-1].start();
            //½{‰å¾…子线½E‹ç»“æ?
            //int count = 0;
            //是否¾l“束while循环
            boolean breakWhile = false;
            while(!bStop)
            {
            write_nPos();
            Utility.sleep(500);
            breakWhile = true;
            for(int i=0;i<nStartPos.length;i++)
            {
            if(!fileSplitterFetch[i].bDownOver)
            {
            breakWhile = false;
            break;
            }
            }
            if(breakWhile)
            break;
            //count++;
            //if(count>4)
            // siteStop();
            }
            System.err.println("æ–‡äšg下蝲¾l“束åQ?);
            }
            catch(Exception e){e.printStackTrace ();}
            }
            //获得文äšg长度
            public long getFileSize()
            {
            int nFileLength = -1;
            try{
            URL url = new URL(siteInfoBean.getSSiteURL());
            HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection ();
            httpConnection.setRequestProperty("User-Agent","NetFox");
            int responseCode=httpConnection.getResponseCode();
            if(responseCode>=400)
            {
            processErrorCode(responseCode);
            return -2; //-2 represent access is error
            }
            String sHeader;
            for(int i=1;;i++)
            {
            //DataInputStream in = new DataInputStream(httpConnection.getInputStream ());
            //Utility.log(in.readLine());
            sHeader=httpConnection.getHeaderFieldKey(i);
            if(sHeader!=null)
            {
            if(sHeader.equals("Content-Length"))
            {
            nFileLength = Integer.parseInt(httpConnection.getHeaderField(sHeader));
            break;
            }
            }
            else
            break;
            }
            }
            catch(IOException e){e.printStackTrace ();}
            catch(Exception e){e.printStackTrace ();}
            Utility.log(nFileLength);
            return nFileLength;
            }
            //保存下蝲信息åQˆæ–‡ä»¶æŒ‡é’ˆä½¾|®ï¼‰
            private void write_nPos()
            {
            try{
            output = new DataOutputStream(new FileOutputStream(tmpFile));
            output.writeInt(nStartPos.length);
            for(int i=0;i<nStartPos.length;i++)
            {
            // output.writeLong(nPos[i]);
            output.writeLong(fileSplitterFetch[i].nStartPos);
            output.writeLong(fileSplitterFetch[i].nEndPos);
            }
            output.close();
            }
            catch(IOException e){e.printStackTrace ();}
            catch(Exception e){e.printStackTrace ();}
            }
            //è¯Õd–保存的下载信息(文äšg指针位置åQ?
            private void read_nPos()
            {
            try{
            DataInputStream input = new DataInputStream(new FileInputStream(tmpFile));
            int nCount = input.readInt();
            nStartPos = new long[nCount];
            nEndPos = new long[nCount];
            for(int i=0;i<nStartPos.length;i++)
            {
            nStartPos[i] = input.readLong();
            nEndPos[i] = input.readLong();
            }
            input.close();
            }
            catch(IOException e){e.printStackTrace ();}
            catch(Exception e){e.printStackTrace ();}
            }
            private void processErrorCode(int nErrorCode)
            {
            System.err.println("Error Code : " + nErrorCode);
            }
            //停止文äšg下蝲
            public void siteStop()
            {
            bStop = true;
            for(int i=0;i<nStartPos.length;i++)
            fileSplitterFetch[i].splitterStop();
            }
            }
            /*
            **FileSplitterFetch.java
            */
            package NetFox;
            import java.io.*;
            import java.net.*;
            public class FileSplitterFetch extends Thread {
            String sURL; //File URL
            long nStartPos; //File Snippet Start Position
            long nEndPos; //File Snippet End Position
            int nThreadID; //Thread's ID
            boolean bDownOver = false; //Downing is over
            boolean bStop = false; //Stop identical
            FileAccessI fileAccessI = null; //File Access interface
            public FileSplitterFetch(String sURL,String sName,long nStart,long nEnd,int id) throws IOException
            {
            this.sURL = sURL;
            this.nStartPos = nStart;
            this.nEndPos = nEnd;
            nThreadID = id;
            fileAccessI = new FileAccessI(sName,nStartPos);
            }
            public void run()
            {
            while(nStartPos < nEndPos && !bStop)
            {
            try{
            URL url = new URL(sURL);
            HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection ();
            httpConnection.setRequestProperty("User-Agent","NetFox");
            String sProperty = "bytes="+nStartPos+"-";
            httpConnection.setRequestProperty("RANGE",sProperty);
            Utility.log(sProperty);
            InputStream input = httpConnection.getInputStream();
            //logResponseHead(httpConnection);
            byte[] b = new byte[1024];
            int nRead;
            while((nRead=input.read(b,0,1024)) > 0 && nStartPos < nEndPos && !bStop)
            {
            nStartPos += fileAccessI.write(b,0,nRead);
            //if(nThreadID == 1)
            // Utility.log("nStartPos = " + nStartPos + ", nEndPos = " + nEndPos);
            }
            Utility.log("Thread " + nThreadID + " is over!");
            bDownOver = true;
            //nPos = fileAccessI.write (b,0,nRead);
            }
            catch(Exception e){e.printStackTrace ();}
            }
            }
            //打印回应的头信息
            public void logResponseHead(HttpURLConnection con)
            {
            for(int i=1;;i++)
            {
            String header=con.getHeaderFieldKey(i);
            if(header!=null)
            //responseHeaders.put(header,httpConnection.getHeaderField(header));
            Utility.log(header+" : "+con.getHeaderField(header));
            else
            break;
            }
            }
            public void splitterStop()
            {
            bStop = true;
            }
            }
            /*
            **FileAccess.java
            */
            package NetFox;
            import java.io.*;
            public class FileAccessI implements Serializable{
            RandomAccessFile oSavedFile;
            long nPos;
            public FileAccessI() throws IOException
            {
            this("",0);
            }
            public FileAccessI(String sName,long nPos) throws IOException
            {
            oSavedFile = new RandomAccessFile(sName,"rw");
            this.nPos = nPos;
            oSavedFile.seek(nPos);
            }
            public synchronized int write(byte[] b,int nStart,int nLen)
            {
            int n = -1;
            try{
            oSavedFile.write(b,nStart,nLen);
            n = nLen;
            }
            catch(IOException e)
            {
            e.printStackTrace ();
            }
            return n;
            }
            }
            /*
            **SiteInfoBean.java
            */
            package NetFox;
            public class SiteInfoBean {
            private String sSiteURL; //Site's URL
            private String sFilePath; //Saved File's Path
            private String sFileName; //Saved File's Name
            private int nSplitter; //Count of Splited Downloading File
            public SiteInfoBean()
            {
            //default value of nSplitter is 5
            this("","","",5);
            }
            public SiteInfoBean(String sURL,String sPath,String sName,int nSpiltter)
            {
            sSiteURL= sURL;
            sFilePath = sPath;
            sFileName = sName;
            this.nSplitter = nSpiltter;
            }
            public String getSSiteURL()
            {
            return sSiteURL;
            }
            public void setSSiteURL(String value)
            {
            sSiteURL = value;
            }
            public String getSFilePath()
            {
            return sFilePath;
            }
            public void setSFilePath(String value)
            {
            sFilePath = value;
            }
            public String getSFileName()
            {
            return sFileName;
            }
            public void setSFileName(String value)
            {
            sFileName = value;
            }
            public int getNSplitter()
            {
            return nSplitter;
            }
            public void setNSplitter(int nCount)
            {
            nSplitter = nCount;
            }
            }
            /*
            **Utility.java
            */
            package NetFox;
            public class Utility {
            public Utility()
            {
            }
            public static void sleep(int nSecond)
            {
            try{
            Thread.sleep(nSecond);
            }
            catch(Exception e)
            {
            e.printStackTrace ();
            }
            }
            public static void log(String sMsg)
            {
            System.err.println(sMsg);
            }
            public static void log(int sMsg)
            {
            System.err.println(sMsg);
            }
            }
            /*
            **TestMethod.java
            */
            package NetFox;
            public class TestMethod {
            public TestMethod()
            { ///xx/weblogic60b2_win.exe
            try{
            SiteInfoBean bean = new SiteInfoBean("http://localhost/xx/weblogic60b2_win.exe","L:\\temp","weblogic60b2_win.exe",5);
            //SiteInfoBean bean = new SiteInfoBean("http://localhost:8080/down.zip","L:\\temp","weblogic60b2_win.exe",5);
            SiteFileFetch fileFetch = new SiteFileFetch(bean);
            fileFetch.start();
            }
            catch(Exception e){e.printStackTrace ();}
            }
            public static void main(String[] args)
            {
            new TestMethod();
            }
            }
            


冰河快狼 2008-05-16 11:12 发表评论
]]>
从LiveJournal后台发展看大规模¾|‘站性能优化æ–ÒŽ(gu¨©)³•http://www.aygfsteel.com/jelver/articles/196656.html冰河快狼冰河快狼Sun, 27 Apr 2008 14:15:00 GMThttp://www.aygfsteel.com/jelver/articles/196656.htmlhttp://www.aygfsteel.com/jelver/comments/196656.htmlhttp://www.aygfsteel.com/jelver/articles/196656.html#Feedback0http://www.aygfsteel.com/jelver/comments/commentRss/196656.htmlhttp://www.aygfsteel.com/jelver/services/trackbacks/196656.html一、LiveJournal发展历程 LiveJournalæ˜?9òq´å§‹äºŽæ ¡å›­ä¸­çš„项目,几个人出于爱好做了这样一个应用,以实çŽîC»¥ä¸‹åŠŸèƒ½ï¼š(x¨¬)
  • 博客åQŒè®ºå?
  • ½C¾ä¼š(x¨¬)性网¾lœï¼Œæ‰‘Öˆ°æœ‹å‹
  • 聚合åQŒæŠŠæœ‹å‹çš„æ–‡ç« èšåˆåœ¨ä¸€èµ?/li>
LiveJournal采用了大量的开源èÊYä»Óž¼Œç”šè‡³å®ƒæœ¬íw«ä¹Ÿæ˜¯ä¸€ä¸ªå¼€æºèÊYä»¶ã€?

在上¾U¿åŽåQŒLiveJournal实现了非常快速的增长åQ?/p>

  • 2004òq?月䆾åQ?80万注册用戗÷€?
  • 2005òq?月䆾åQ?80万注册用戗÷€?
  • 2005òq?月䆾åQ?90万注册用戗÷€?
  • 辑ֈ°äº†æ¯¿U’钟上千‹Æ¡çš„™åµé¢è¯äh±‚å?qi¨¢ng)处理ã€?
  • 使用了大量MySQL服务器ã€?
  • 使用了大量通用¾l„äšgã€?/li>

二、LiveJournal架构现状概况

livejournal_backend.png

三、从LiveJournal发展中学�/h2>

 

LiveJournalä»?台服务器发展åˆ?00台服务器åQŒè¿™å…¶ä¸­¾låŽ†äº†æ— æ•°çš„ä¼¤ç—›åQŒä½†åŒæ—¶ä¹Ÿæ‘¸ç´¢å‡ºäº†è§£å†Œ™¿™äº›é—®é¢˜çš„æ–ÒŽ(gu¨©)³•åQŒé€šè¿‡å¯¹LiveJournal的学ä¹?f¨¤n),可以让我们避免LJ曄¡»çŠ¯è¿‡çš„é”™è¯¯ï¼Œòq¶ä¸”从一开始就对系¾lŸè¿›è¡Œè‰¯å¥½çš„设计åQŒä»¥é¿å…åŽæœŸçš„痛苦ã€?/p>

下面我们一步一步看LJ发展的脚步�/p>

1、一台服务器

一台别人捐助的服务器,LJ最初就跑在上面åQŒå°±åƒGoogleå¼€å§‹æ—¶å€™ç”¨çš„ç ´æœåŠ¡å™¨ä¸€æ øP¼Œå€¼å¾—我们ž®Šæ•¬ã€‚这个阶ŒDµï¼ŒLJçš„äh以惊人的速度熟æ?zh¨¨n)‰çš„Unix的操作管理,服务器性能出现˜q‡é—®é¢˜ï¼Œä¸è¿‡˜q˜å¥½åQŒå¯ä»¥é€šè¿‡ä¸€äº›å°ä¿®å°æ”¹åº”付过厅R€‚在˜q™ä¸ªé˜¶æ®µé‡ŒLJ把CGI升çñ”åˆîCº†FastCGIã€?/p>

最¾lˆé—®é¢˜å‡ºçŽîCº†åQŒç½‘站越来越慢,已经无法通过优过化来解决的地步,需要更多的服务器,˜q™æ—¶LJ开始提供付è´ÒŽ(gu¨©)œåŠ¡ï¼Œå¯èƒ½æ˜¯æƒ³é€šè¿‡˜q™äº›é’±æ¥è´­ä¹°æ–°çš„æœåŠ¡å™¨ï¼Œä»¥è§£å†›_½“时的困境ã€?br /> 毫无疑问åQŒå½“æ—¶LJ存在巨大的单炚w—®é¢˜ï¼Œæ‰€æœ‰çš„东西都在那台服务器的铁皮盒子里装着ã€?/p>

LJ-backend-7.png

2、两台服务器

用付è´ÒŽ(gu¨©)œåŠ¡èµšæ¥çš„é’±LJä¹îCº†ä¸¤å°æœåŠ¡å™¨ï¼š(x¨¬)一台叫做Kennyçš„Dell 6U机器用于提供Web服务åQŒä¸€å°å«åšCartmançš„Dell 6U服务器用于提供数据库服务ã€?/p>

LJ-backend-8.png

LJ有了更大的磁盘,更多的计½Ž—资源。但同时¾|‘络¾l“æž„˜q˜æ˜¯éžå¸¸½Ž€å•,每台机器两块¾|‘卡åQŒCartman通过内网为Kenny提供MySQL数据库服务ã€?br />
暂时解决了负载的问题åQŒæ–°çš„问题又出现了:(x¨¬)

  • 原来的一个单点变成了两个单点ã€?
  • 没有冷备份或热备份ã€?
  • ¾|‘站速度慢的问题又开始出çŽîCº†åQŒæ²¡åŠžæ³•åQŒå¢žé•¿å¤ªå¿«äº†ã€?
  • Web服务器上CPU辑ֈ°ä¸Šé™åQŒéœ€è¦æ›´å¤šçš„Web服务器ã€?/li>

3、四台服务器

又买了两収ͼŒKyleå’ŒStanåQŒè¿™‹Æ¡éƒ½æ˜?U的,都用于提供Web服务。目前LJ一共有3台Web服务器和一台数据库服务器。这旉™œ€è¦åœ¨3台Web服务器上˜q›è¡Œè´Ÿè²å‡æ¨ªã€?/p>

LJ-backend-9.png

LJ把Kenny用于外部的网养I¼Œä½¿ç”¨mod_backhand˜q›è¡Œè´Ÿè²å‡æ¨ªã€?/p>

然后问题又出çŽîCº†åQ?/p>

  • 单点故障。数据库和用于做¾|‘关的Web服务器都是单点,一旦ä“Qä½•ä¸€å°æœºå™¨å‡ºçŽ°é—®é¢˜å°†å¯ÆD‡´æ‰€æœ‰æœåŠ¡ä¸å¯ç”¨ã€‚è™½ç„¶ç”¨äºŽåš¾|‘关的Web服务器可以通过保持心蟩同步˜q…速切换,但还是无法解å†Ïx•°æ®åº“的单点,LJ当时也没做这个ã€?
  • ¾|‘站又变慢了åQŒè¿™‹Æ¡æ˜¯å› äØ“(f¨´)IO和数据库的问题,问题是怎么往应用里面æ·ÕdŠ æ•°æ®åº“å‘¢åQ?/li>

4、五台服务器

又买了一台数据库服务器。在两台数据库服务器上ä‹É用了数据库同æ­?Mysql支持的Master-Slave模式)åQŒå†™æ“ä½œå…¨éƒ¨é’ˆå¯¹ä¸ÀL•°æ®åº“åQˆé€šè¿‡BinlogåQŒä¸»æœåŠ¡å™¨ä¸Šçš„å†™æ“ä½œå¯ä»¥˜q…速同步到从服务器上)åQŒè¯»æ“ä½œåœ¨ä¸¤ä¸ªæ•°æ®åº“上同时进è¡?也算是负载均横的一¿Uå§)ã€?/p>

LJ-backend-10.png

实现同步时要注意几个事项åQ?/p>

  • è¯ÀL“ä½œæ•°æ®åº“选择½Ž—法处理åQŒè¦é€‰ä¸€ä¸ªå½“前负载轻一点的数据库ã€?
  • 在从数据库服务器上只能进行读操作
  • 准备好应对同步过½E‹ä¸­çš„åšg˜qŸï¼Œå¤„理不好可能ä¼?x¨¬)导致数据库同步的中断。只需要对写操作进行判断即可,è¯ÀL“ä½œä¸å­˜åœ¨åŒæ­¥é—®é¢˜ã€?/li>

5、更多服务器

有钱了,当然要多ä¹îCº›æœåŠ¡å™¨ã€‚éƒ¨¾|²åŽå¿«äº†æ²¡å¤šä¹…,又开始慢了。这‹Æ¡æœ‰æ›´å¤šçš„Web服务器,更多的数据库服务器,存在 IO与CPU争用。于是采用了BIG-IPä½œäØ“(f¨´)负蝲均衡解决æ–ÒŽ(gu¨©)¡ˆã€?/p>

LJ-backend-11.png

6、现在我们在哪里åQ?/h2>

LJ-backend-1.png

现在服务器基本上够了åQŒä½†æ€§èƒ½˜q˜æ˜¯æœ‰é—®é¢˜ï¼ŒåŽŸå› å‡ºåœ¨æž¶æž„ä¸Šã€?/p>

数据库的架构是最大的问题。由于增加的数据库都是以Slave模式æ·ÕdŠ åˆ°åº”ç”¨å†…åQŒè¿™æ ·å”¯ä¸€çš„好处就是将è¯ÀL“ä½œåˆ†å¸ƒåˆ°äº†å¤šå°æœºå™¨ï¼Œä½†è¿™æ ·å¸¦æ¥çš„后果ž®±æ˜¯å†™æ“ä½œè¢«å¤§é‡åˆ†å‘åQŒæ¯å°æœºå™¨éƒ½è¦æ‰§è¡Œï¼ŒæœåŠ¡å™¨è¶Šå¤šï¼Œ‹¹ªè´¹ž®Þp¶Šå¤§ï¼Œéšç€å†™æ“ä½œçš„增加åQŒç”¨äºŽæœåŠ¡è¯»æ“ä½œçš„èµ„æºè¶Šæ¥è¶Šž®‘ã€?/p>

LJ-backend-2.png

ç”׃¸€å°åˆ†å¸ƒåˆ°ä¸¤å°

LJ-backend-3.png

最¾lˆæ•ˆæž?/p>

现在我们发现åQŒæˆ‘ä»¬åÆˆä¸éœ€è¦æŠŠ˜q™äº›æ•°æ®åœ¨å¦‚此多的服务器上都保留一份。服务器上已¾låšäº†RAIDåQŒæ•°æ®åº“也进行了备䆾åQŒè¿™ä¹ˆå¤šçš„备份完全是对资源的‹¹ªè´¹åQŒå±žäºŽå†—余极端过度。那ä¸ÞZ»€ä¹ˆä¸æŠŠæ•°æ®åˆ†å¸ƒå­˜å‚¨å‘¢åQ?/p>

问题发现了,开始考虑如何解决。现在要做的ž®±æ˜¯æŠŠä¸åŒç”¨æˆïL(f¨¥ng)š„æ•°æ®åˆ†å¸ƒåˆîC¸åŒçš„æœåŠ¡å™¨ä¸Š˜q›è¡Œå­˜å‚¨åQŒä»¥å®žçŽ°æ•°æ®çš„åˆ†å¸ƒå¼å­˜å‚¨åQŒè®©æ¯å°æœºå™¨åªäØ“(f¨´)相对固定的用æˆähœåŠ¡ï¼Œä»¥å®žçŽ°åã^行的架构和良好的可扩展性ã€?/p>

ä¸ÞZº†å®žçŽ°ç”¨æˆ·åˆ†ç»„åQŒæˆ‘ä»¬éœ€è¦äØ“(f¨´)每一个用户分配一个组标记åQŒç”¨äºŽæ ‡è®°æ­¤ç”¨æˆ·çš„æ•°æ®å­˜æ”‘Öœ¨å“ªä¸€¾l„数据库服务器中。每¾l„数据库ç”׃¸€ä¸ªmasterå?qi¨¢ng)几个slave¾l„成åQŒåƈ且slave的数量在2-3収ͼŒä»¥å®žçŽ°ç³»¾lŸèµ„源的最合理分配åQŒæ—¢ä¿è¯æ•°æ®è¯ÀL“ä½œåˆ†å¸ƒï¼Œåˆé¿å…æ•°æ®è¿‡åº¦å†—余以å?qi¨¢ng)同步操作对¾pȝ»Ÿèµ„源的过度消耗ã€?/p>

LJ-backend-4.png

ç”׃¸€åŽÍ¼ˆä¸€¾l„)中心服务器提供用户分¾l„控制。所有用æˆïL(f¨¥ng)š„分组信息都存储在˜q™å°æœºå™¨ä¸Šï¼Œæ‰€æœ‰é’ˆå¯¹ç”¨æˆïL(f¨¥ng)š„æ“ä½œéœ€è¦å…ˆæŸ¥è¯¢˜q™å°æœºå™¨å¾—åˆ°ç”¨æˆ·çš„ç»„åøP¼Œç„¶åŽå†åˆ°ç›¸åº”的数据库¾l„中获取数据ã€?/p>

˜q™æ ·çš„用æˆähž¶æž„与目前LJ的架构已¾lå¾ˆç›¸åƒäº†ã€?/p>

在具体的实现旉™œ€è¦æ³¨æ„å‡ ä¸ªé—®é¢˜ï¼š(x¨¬)

  • 在数据库¾l„内不要使用自增IDåQŒä»¥ä¾¿äºŽä»¥åŽåœ¨æ•°æ®åº“¾l„之间迁¿Uȝ”¨æˆøP¼Œä»¥å®žçŽ°æ›´åˆç†çš„I/OåQŒç£ç›˜ç©ºé—´åŠ(qi¨¢ng)负蝲分布ã€?
  • ž®†useridåQŒpostid存储在全局服务器上åQŒå¯ä»¥ä‹É用自增,数据库组中的相应值必™åÖM»¥å…¨å±€æœåŠ¡å™¨ä¸Šçš„å€égØ“(f¨´)准。全局服务器上使用事务型数据库InnoDBã€?
  • 在数据库¾l„之间迁¿Uȝ”¨æˆäh—¶è¦ä¸‡åˆ†å°å¿ƒï¼Œå½“迁¿UÀL—¶ç”¨æˆ·ä¸èƒ½æœ‰å†™æ“ä½œã€?/li>

7、现在我们在哪里

LJ-backend-5.png

问题åQ?/p>

  • 一个全局ä¸ÀLœåС噍åQŒæŒ‚掉的话所有用æˆäh³¨å†ŒåŠ(qi¨¢ng)写操作就挂掉ã€?
  • 每个数据库组一个主服务器,挂掉的话˜q™ç»„用户的写操作ž®±æŒ‚掉ã€?
  • 数据库组从服务器挂掉的话ä¼?x¨¬)导致其它服务器负蝲˜q‡å¤§ã€?/li>

对于Master-Slave模式的单炚w—®é¢˜ï¼ŒLJ采取了Master-Master模式来解冟뀂所谓Master-Master实际上是人工实现的,òq¶ä¸æ˜¯ç”±MySQL直接提供的,实际上也ž®±æ˜¯ä¸¤å°æœºå™¨åŒæ—¶æ˜¯MasteråQŒä¹ŸåŒæ—¶æ˜¯SlaveåQŒäº’相同步ã€?/p>

Master-Master实现旉™œ€è¦æ³¨æ„ï¼š(x¨¬)

  • 一个Master出错后恢复同步,最好由服务器自动完成ã€?
  • 数字分配åQŒç”±äºŽåŒæ—¶åœ¨ä¸¤å°æœºå™¨ä¸Šå†™åQŒæœ‰äº›ID可能ä¼?x¨¬)冲½Hã€?/li>

解决æ–ÒŽ(gu¨©)¡ˆåQ?br />

  • 奇偶数分配IDåQŒä¸€å°æœºå™¨ä¸Šå†™å¥‡æ•ŽÍ¼Œä¸€å°æœºå™¨ä¸Šå†™å¶æ•?
  • 通过全局服务器进行分é…?LJ采用的做æ³?ã€?/li>

 

Master-Master模式˜q˜æœ‰ä¸€¿Uç”¨æ³•,˜q™ç§æ–ÒŽ(gu¨©)³•与前一¿Uç›¸æ¯”,仍然保持两台机器的同步,但只有一台机器提供服务(è¯Õd’Œå†™ï¼‰åQŒåœ¨æ¯å¤©æ™šä¸Šçš„æ—¶å€™è¿›è¡Œè½®æ¢ï¼Œæˆ–者出现问题的时候进行切换ã€?/p>

8、现在我们在哪里

LJ-backend-6.png

现在插播一条广告,MyISAM VS InnoDB�/p>

使用InnoDBåQ?/p>

  • 支持事务
  • 需要做更多的配¾|®ï¼Œä¸è¿‡å€¼å¾—åQŒå¯ä»¥æ›´å®‰å…¨çš„存储数据,以及(qi¨¢ng)得到更快的速度ã€?/li>

使用MyISAMåQ?/p>

  • 记录日志åQˆLJ用它来记¾|‘络讉K—®æ—¥å¿—åQ?
  • 存储只读静态数据,­‘›_¤Ÿå¿«ã€?
  • òq¶å‘性很差,无法同时è¯Õd†™æ•°æ®åQˆæ·»åŠ æ•°æ®å¯ä»¥ï¼‰
  • MySQL非正常关闭或æ­ÀLœºæ—¶ä¼š(x¨¬)坯D‡´ç´¢å¼•错误åQŒéœ€è¦ä‹É用myisamchk修复åQŒè€Œä¸”当访问量大时出现非常频繁ã€?/li>

9、缓�/h2>

åŽÕd¹´æˆ‘写˜q?a >一½‹‡æ–‡ç« ä»‹¾lmemcachedåQŒå®ƒ?y¨­u)®±æ˜¯ç”±LJ的团队开发的一‹Æ„¡¼“å­˜å·¥å…øP¼Œä»¥key-value的方式将数据存储到分布的内存中。LJ¾~“存的数据:(x¨¬)

  • 12台独立服务器åQˆä¸æ˜¯æèµ çš„åQ?
  • 28个实ä¾?
  • 30GBæ€Õd®¹é‡?
  • 90-93%的命中率åQˆç”¨˜q‡squidçš„äh可能知道åQŒsquid内存加磁盘的命中率大概在70-80%åQ?/li>

如何建立¾~“å­˜½{–ç•¥åQ?/p>

想缓存所有的东西åQŸé‚£æ˜¯ä¸å¯èƒ½çš„,我们只需要缓存已¾læˆ–者可能导致系¾lŸç“¶é¢ˆçš„地方åQŒæœ€å¤§ç¨‹åº¦çš„æäº¤¾pȝ»Ÿ˜qè¡Œæ•ˆçŽ‡ã€‚é€šè¿‡å¯¹MySQL的日志的分析我们可以扑ֈ°¾~“存的对象ã€?/p>

¾~“存的缺点?

  • 没有完美的事物,¾~“存也有¾~ºç‚¹åQ?
  • 增大开发量åQŒéœ€è¦é’ˆå¯¹ç¼“存处理编写特ŒDŠçš„代码ã€?
  • ½Ž¡ç†éš‘Öº¦å¢žåŠ åQŒéœ€è¦æ›´å¤šäh参与¾pȝ»Ÿ¾l´æŠ¤ã€?
  • 当然大内存也需要钱ã€?/li>

10、Web讉K—®è´Ÿè²å‡è¡¡

在数据包¾U§åˆ«ä½¿ç”¨BIG-IPåQŒä½†BIG-IPòq¶ä¸çŸ¥é“我们内部的处理机åˆÓž¼Œæ— æ³•åˆ¤æ–­ç”±å“ªå°æœåŠ¡å™¨å¯¹è¿™äº›è¯·æ±‚è¿›è¡Œå¤„ç†ã€‚åå‘ä»£ç†åÆˆä¸èƒ½å¾ˆå¥½çš„è“våˆîC½œç”¨ï¼Œä¸æ˜¯å·²ç»å¤Ÿå¿«äº†ï¼Œž®±æ˜¯è¾¾ä¸åˆ°æˆ‘们想要的效果ã€?/p>

所以,LJ又开发了Perlbal。特点:(x¨¬)

  • 快,ž®ï¼Œå¯ç®¡ç†çš„http web 服务å™?代理
  • 可以在内部进行è{å?
  • 使用Perlå¼€å?
  • 单线½E‹ï¼Œå¼‚æ­¥åQŒåŸºäºŽäº‹ä»Óž¼Œä½¿ç”¨epoll , kqueue
  • 支持Console½Ž¡ç†ä¸Žhttp˜qœç¨‹½Ž¡ç†åQŒæ”¯æŒåŠ¨æ€é…¾|®åŠ è½?
  • 多种模式åQšweb服务器,反向代理åQŒæ’ä»?
  • 支持插äšgåQšGIF/PNG互换åQ?/li>

11、MogileFS

LJ使用开源的MogileFSä½œäØ“(f¨´)分布式文件存储系¾lŸã€‚MogileFS使用非常½Ž€å•,它的主要设计思想是:(x¨¬)

  • æ–‡äšg属于¾c»ï¼ˆ¾cÀL˜¯æœ€ž®çš„复制单位åQ?
  • 跟踪文äšg存储位置
  • 在不同主æœÞZ¸Šå­˜å‚¨
  • 使用MySQL集群¾lŸä¸€å­˜å‚¨åˆ†å¸ƒä¿¡æ¯
  • 大容易廉ä»ïL(f¨¥ng)£ç›?/li>

åˆ°ç›®å‰äØ“(f¨´)止就˜q™ä¹ˆå¤šäº†åQŒæ›´å¤šæ–‡æ¡£å¯ä»¥åœ¨http://www.danga.com/words/扑ֈ°ã€?a >Danga.comå’?a >LiveJournal.com的同学们拿这个文档参加了两次MySQL ConåQŒä¸¤‹Æ¡OS ConåQŒä»¥å?qi¨¢ng)众多的其它会(x¨¬)è®®åQŒæ— ¿Uçš„æŠŠä»–们的¾léªŒåˆ†äín出来åQŒå€¼å¾—我们学习(f¨¤n)。在web2.0时代快速开发得到大家越来越多的重视åQŒä½†è‰¯å¥½çš„设计仍是每一个应用的基础åQŒå¸Œæœ›web2.0们在成长为Top500¾|‘站的èµ\ä¸Šï¼Œä¸è¦å› äØ“(f¨´)æž¶æž„é˜È¢äº†ç½‘站的发展ã€?/p>

参考资料:(x¨¬)http://www.danga.com/words/2005_oscon/oscon-2005.pdf

感谢向静推荐了这½‹‡æ–‡æ¡£ç»™æˆ‘ã€?/p>



]]>ç”?sh¨´)媄服务器流媒体关键技æœ?/title><link>http://www.aygfsteel.com/jelver/articles/196409.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Sun, 27 Apr 2008 02:31:00 GMT</pubDate><guid>http://www.aygfsteel.com/jelver/articles/196409.html</guid><wfw:comment>http://www.aygfsteel.com/jelver/comments/196409.html</wfw:comment><comments>http://www.aygfsteel.com/jelver/articles/196409.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/jelver/comments/commentRss/196409.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/jelver/services/trackbacks/196409.html</trackback:ping><description><![CDATA[<strong>引言</strong> <br /> <br /> ˜q‘年来,随着计算机技术、压¾~©æŠ€æœ¯ä»¥å?qi¨¢ng)网¾lœæŠ€æœ¯çš„发展åQŒç½‘¾lœä¸­çš„æµåª’体业务也得åˆîCº†é£žé€Ÿçš„发展和应用。所谓流媒体ž®±æ˜¯æŒ‡åœ¨ Internet/Intranet中ä‹É用流式传输技术的˜qžç®‹æ—¶åŸºåª’体。本文中着重介¾lè§†é¢‘流。目前在Internet上传输视频还有许多困难,其根本原因在于Internet的无˜qžæŽ¥æ¯åŒ…è½¬å‘æœºåˆ¶ä¸»è¦æ˜¯äØ“(f¨´)½Hå‘性的数据传输而设计的åQŒä¸é€‚用于对˜qžç®‹åª’体‹¹çš„ä¼ è¾“ã€‚äØ“(f¨´)了在Internet上有效地、高质量åœîC¼ è¾“视频流åQŒè¿˜éœ€è¦å¤š¿UæŠ€æœ¯çš„æ”¯æŒåQŒä¾‹å¦‚基于视频的压羃¾~–码技术、应用层QoS技术、连¾l­åª’体分布服务、流服务器、媒体同步技术和相关协议½{‰ã€?<br /> <br /> 其中åQŒåŽŸå§‹è§†/音频¾lè¿‡è§?音频压羃½Ž—法的预压羃存储在存储设备中。响应客戯‚¯·æ±‚æ—¶åQŒæµæœåŠ¡å™¨ä»Žå­˜å‚¨è®‘Ö¤‡ä¸­èŽ·å¾—è§†/音频数据åQŒåº”用层QoS控制模块æ ÒŽ(gu¨©)®¾|‘络状态和QoS要求来改变视/音频比特‹¹ã€‚然后通过传输协议把压¾~©è¿‡çš„æ¯”ç‰ÒŽ(gu¨©)µæ‰“包òq¶ä¸”发送到¾|‘ä¸Šã€‚ç”±äºŽæ‹¥å¡žæ•°æ®åŒ…å¯èƒ½å‡ºçŽ°ä¸¢åŒ…æˆ–è€…è¿‡åº¦æ—¶å»¶ã€‚äØ“(f¨´)了提高视 /音频的传输质量,¾|‘络中配¾|®äº†˜qžç®‹‹¹åª’体分布式服务。对于成功传输的数据包,它们首先通过传输层,然后在进行视/音频解码前经˜q‡åº”ç”¨å±‚å¤„ç†ã€‚äØ“(f¨´)了获得在播放中的视频和音频的同步åQŒè¿˜éœ€è¦åª’体同步机制。从上图中可以看出,˜q™å…­ä¸ªéƒ¨åˆ†æœ‰ç€ç´§å¯†çš„联¾p»è€Œä¸”都是‹¹åª’体结构的¾l„成部分ã€?br /> <br /> <strong>2 ‹¹åª’体中的关键技æœ?br /> <br /> </strong><br /> <br /> 2.1 视频压羃å?qi¨¢ng)ç¼–ç?<br /> <br /> 目前¾|‘络是异构性的åQŒç¼ºä¹QoS质量控制åQŒåƈ且带宽也在很大范围内变化。传¾lŸçš„不可扩展性视频编码的目标是将视频压羃成适合一个或者几个固定码率的码流åQŒæ˜¯é¢å‘存储的,因此不适合¾|‘ç»œä¼ è¾“ã€‚äØ“(f¨´)了适应¾|‘络带宽的变化,面向传输的可扩展性编码的思想应运而生。可扩展性编码[2]ž®±æ˜¯ž®†å¤šåª’体数据压羃¾~–码成多个流åQŒå…¶ä¸­ä¸€ä¸ªå¯ä»¥ç‹¬ç«‹è§£ç ï¼Œäº§ç”Ÿ¾_—糙质量的视频序列,它适应最低的¾|‘络带宽åQŒç§°ä¸ºåŸºæœ¬å±‚码流åQ›å…¶ä»–的码流可以按层为单位在ä»ÖM½•地点截断åQŒç§°ä¸ºå¢žå¼ºå±‚åQŒç”¨æ¥è¦†ç›–网¾lœå¸¦å®½å˜åŒ–的动态范å›ß_(d¨¢)¼Œå®ƒä»¬ä¸å¯ä»¥å•独解码,而只能与基本层和它以前的增强层联合在一赯‚§£ç ï¼Œç”¨æ¥æé«˜è§‚看效果。因此,可扩展性码‹¹å…·æœ‰ä¸€å®šçš„¾|‘络带宽适应能力ã€?<br /> <br /> 可扩展性编码主要分为时域可扩展性编码、空域可扩展性编码和质量可扩展性编码。可以选择在时间、空间和信噪比(SNRåQ‰ä¸­çš„一个或者几个方面实现扩展。考虑到编码效率和复杂性两斚w¢åQŒMPEG¾l„织采纳了精¾l†å¯æ‰©å±•性编码(F(tu¨¢n)GSåQ‰å’Œæ¸è¿›çš„ç²¾¾l†å¯æ‰©å±•性编码(PFGSåQ‰[3]。精¾l†å¯æ‰©å±•性视频编码采用位òq³é¢åQˆbitplaneåQ‰ç¼–码,它的基本层ä‹É用基于分块运动补偿和DCT变换的编码方式达到网¾lœä¼ è¾“的最低要求,增强层ä‹É用位òq³é¢¾~–码技术对DCTŒD‹å·®˜q›è¡Œ¾~–码来覆盖网¾lœå¸¦å®½çš„变化范围åQŒå®ƒæ¯ä¸€å¸§çš„增强层码‹¹å¯ä»¥åœ¨ä»ÖM½•地点截断åQŒè§£ç å™¨é‡å¾çš„视频质量和收到òq¶è§£ç çš„æ¯”特数成正比åQŒå®ƒå¯ä»¥å®žçް˜qžç®‹çš„增强层速率控制。FGS虽然å…ähœ‰å¾ˆå¥½çš„可扩展性,但是效率太低åQŒPFGS在保留了FGS所å…ähœ‰çš„网¾lœå¸¦å®½è‡ªé€‚应和错误恢复能力的同时åQŒè¿˜æœ‰æ•ˆåœ°æé«˜äº†¾~–码效率。但是可扩展性编码的效率较非可扩展性编码而言åQŒè¿˜æœ‰ä¸€å®šå·®è·ã€‚䨓(f¨´)了进一步压¾~©FGSå’ŒPFGS的基本层码流åQŒæœ‰ä¸“家提出一¿Uç§°ä¸ºç²¾¾l†çš„½IºåŸŸå¯æ‰©å±•性(F(tu¨¢n)ine-Granularity Spatially Scalable,FGSSåQ‰çš„视频¾~–码½Ž—法åQŒä‹É低分辨率和高分èöL率的增强层码‹¹éƒ½å¯ä»¥åœ¨ä“Q何地ç‚ÒŽ(gu¨©)ˆªæ–­ï¼Œå…ähœ‰æžå¼ºçš„网¾lœå¸¦å®½é€‚应能力和错误恢复功能,同时保持了空域可扩展性编码的多分辨率ç‰ÒŽ(gu¨©)€§ï¼Œå®ƒå¯ä»¥æ»¡­‘Ïx‹¥æœ‰ä¸åŒç½‘¾lœå¸¦å®½å’Œä¸åŒåˆ†èöL率接收设备的许多用户的需求,性能得到了更大的提高ã€?<br /> <br /> ¾l“合多种视频¾~–码技术来适应¾|‘络上的QoS波动是今后可扩展性视频编码的发展方向。比如,可扩展性视频编码可以适应¾|‘络带宽的变化;错误å¼ÒŽ(gu¨©)€§ç¼–码可以适应丢包åQ›DCVCåQˆDelay Cognizant Video CodingåQ‰å¯ä»¥é€‚应¾|‘络时åšg。这三种技术的¾l“合可以更好地提供一¿Uåº”对网¾lœQ(j¨¬ng)oS波动的解å†Ïx–¹æ¡ˆã€?br /> <br /> 2.2 应用层QoS控制技术由于目前的Internet只提供Best-effort的服务,所以需要通过应用层的机制来实现QoS的控制。QoS控制技术主要集中在对网¾lœå¸¦å®½çš„变化˜q›è¡Œå“åº”和处理分¾l„丢å¤Þqš„æŠ€æœ¯ä¸ŠåQŒä¸»è¦å¯ä»¥åˆ†ä¸ÞZ¸¤¾c»ï¼š(x¨¬)拥塞控制技术和差错控制技术ã€?<br /> <br /> 拥塞控制的目的是采用某种机制应对和避免网¾lœé˜»å¡žï¼Œé™ä½Žæ—¶åšg和丢包率。常用的拥塞控制机制有速率控制和速率整åŞ。对于视频流åQŒæ‹¥å¡žæŽ§åˆ¶çš„主要æ–ÒŽ(gu¨©)³•是速率控制。速率控制机制试图使一个视频连接的需求与整个˜qžæŽ¥é“¾èµ\的可用带宽相匚w…åQŒè¿™æ ·å¯ä»¥åŒæ—¶ä‹É¾|‘络拥塞和包丢失率达到最ž®ã€‚速率控制机制主要包括åŸÞZºŽæºç«¯çš„、基于目的的以及(qi¨¢ng)混合速率控制。在åŸÞZºŽæºç«¯çš„æŽ§åˆ¶æœºåˆ¶ä¸­åQŒè§†é¢‘源端收集反馈信息,˜q›è¡ŒæŽ§åˆ¶è®¡ç®—òq‰™‡‡å–相应的控制动作。这¿Uæ–¹æ³•在因特¾|‘中被率先采ç”?但是在异构网¾lœä¸­çš„è¿è¡Œæƒ…å†µåÆˆä¸æ˜¯å¾ˆå¥½ã€‚åŸºäºŽç›®çš„ç«¯çš„æŽ§åˆ¶æœºåˆ¶åˆ™ä¸»è¦æ ÒŽ(gu¨©)®æ‰€æŽ¥æ”¶çš„视频流的状况向上层反映相应的统计信息,实时调整¾~“冲å?qi¨¢ng)播攑ֆ…容,òq¶åЛ图ä‹É节奏均匀åQŒè¿™¿Uæœºåˆ¶ä‹É用较?y¨­u)®‘ã€‚æØœåˆæ€§é€ŸçŽ‡æŽ§åˆ¶çš„æ–¹æ³•å…¼æœ‰å‰äºŒè€…çš„ç‰¹ç‚¹åQŒå³ç›®çš„端增加减ž®‘通道åQŒè€Œæºç«¯åŒæ—¶æ ¹æ®åé¦ˆè°ƒæ•´å„ä¸ªé€šé“çš„é€ŸçŽ‡ã€‚æØœåˆé€ŸçŽ‡æŽ§åˆ¶æ–ÒŽ(gu¨©)³•的一个例子是目标集分¾l„çš„æ–ÒŽ(gu¨©)³•ã€?<br /> <br /> 拥塞控制只能减少数据包的丢失åQŒä½†æ˜¯ç½‘¾lœä¸­ä¸å¯é¿å…çš„会(x¨¬)存在数据包丢失,而且到达时åšg˜q‡å¤§çš„分¾l„也ä¼?x¨¬)被认äØ?f¨´)没有用而被丢弃åQŒä»Žè€Œé™ä½Žäº†è§†é¢‘质量。要改善视频质量ž®±éœ€è¦ä¸€å®šçš„差错控制机制。差错控制机制包括:(x¨¬) <br /> <br /> åQ?åQ‰å‰å‘纠错(F(tu¨¢n)ECåQ‰ï¼š(x¨¬)FEC是通过在传输的码流中加入用于纠错的冗余信息åQŒåœ¨é‡åˆ°åŒ…丢å¤Þqš„æƒ…况æ—Óž¼Œåˆ©ç”¨å†—余信息恢复丢失的信息。它的不­‘Ïx˜¯å¢žåŠ äº†ç¼–ç æ—¶å»¶å’Œä¼ è¾“å¸¦å®½ã€?<br /> <br /> åQ?åQ‰åšg˜qŸçº¦æŸçš„重传。通常‹¹çš„æ’­æ”¾æœ‰æ—¶é—´é™åˆÓž¼Œå› æ­¤åQŒä»…有当重传的时间小于正常的播放旉™—´æ—Óž¼Œé‡ä¼ æ‰æ˜¯æœ‰ä­h(hu¨¢n)值的ã€?<br /> <br /> åQ?åQ‰é”™è¯¯å¼¹æ€§ç¼–码(Error-Resilient EncodingåQ‰ï¼š(x¨¬)在编码中通过适当的控制ä‹É得发生数据的丢失后能够最大限度的减少对质量的影响。在Internet环境下,最典型的方法是多描˜q°ç¼–码(MDCåQ‰ã€‚MDC把原始的视频序列压羃成多位流åQŒæ¯ä¸ªæµå¯¹åº”一¿Uæ˜qŽÍ¼Œéƒ½å¯ä»¥æä¾›å¯æŽ¥å—的视觉质量。多个描˜q°ç»“合è“v来提供更好的质量。该æ–ÒŽ(gu¨©)³•的优ç‚ÒŽ(gu¨©)˜¯å®žçŽ°äº†å¯¹æ•°æ®ä¸¢å¤±çš„é²‹‚’性和增强的质量。其¾~ºç‚¹æ˜¯ç›¸æ¯”单描述¾~–码åQˆSDCåQ‰ï¼Œå®ƒåœ¨åŽ‹ç¾ƒçš„æ•ˆçŽ‡ä¸Šå—åˆ°å½±å“ã€‚è€Œä¸”ç”׃ºŽåœ¨å¤šæè¿°ä¹‹é—´å¿…须加入一定的相关性信息,˜q™è¿›ä¸€æ­¥é™ä½Žäº†åŽ‹ç¾ƒçš„æ•ˆçŽ‡ã€?<br /> <br /> åQ?åQ‰é”™è¯¯çš„取消åQˆconcealmentåQ‰ï¼š(x¨¬)错误的取消是指当错误已经发生后,接受端通过一定的æ–ÒŽ(gu¨©)³•ž®½é‡å‰Šå¼±å¯¹äh的视觉媄响。主要的æ–ÒŽ(gu¨©)³•是时间和½Iºé—´çš„æ’å€û|¼ˆInterpolationåQ‰ã€‚è¿‘òq´æ¥çš„ç ”½I¶è¿˜åŒ…括最大åã^滑恢复,˜qåŠ¨è¡¥å¿æ—‰™—´é¢„测½{‰ã€?br /> <br /> 2.3 ˜qžç®‹åª’体分布服务 <br /> <br /> ˜qžç®‹åª’体分布服务åQˆcontinuous media distribution servicesåQ‰çš„目的是在Internet ž®½åŠ›æœåŠ¡çš„åŸº¼‹€ä¸Šæä¾›QoS和高效的éŸ?视频传输åQŒåŒ…括网¾lœè¿‡æ»¤ï¼ˆNetwork FilteringåQ‰ã€åº”用层¾l„æ’­åQˆApplication-Level MulticaståQ‰ã€å†…容复åˆÓž¼ˆContent ReplicationåQ‰ç­‰åQŒä¸‹é¢åˆ†åˆ«è¿›è¡Œè¯¦¾l†ä»‹¾lã€?br /> <br /> ¾|‘络˜q‡æ×o(h¨´)åQšç½‘¾lœè¿‡æ»¤æ˜¯æ‹¥å¡žæŽ§åˆ¶çš„一¿Uï¼Œä¸ä»…可以提高视频质量åQŒè¿˜å¯ä»¥æé«˜å¸¦å®½åˆ©ç”¨çŽ‡ã€‚ä¸åŒäºŽå‘é€ç«¯çš„é€ŸçŽ‡æ•´åÅžåQŒç½‘¾lœè¿‡æ»¤æ˜¯åœ¨æµæœåŠ¡å™¨å’Œå®¢æˆ·ç«¯ä¹‹é—´çš„ä¼ è¾“è·¯å¾„ä¸Šé€šè¿‡è™šæ‹Ÿä¿¡é“˜qžå…¥˜q‡æ×o(h¨´)器,该过滤器æ ÒŽ(gu¨©)®¾|‘络的拥塞状态实现速率的整形。网¾lœè¿‡æ»¤é€šå¸¸é‡‡ç”¨çš„æ˜¯ä¸¢å“á˜q‡æ×o(h¨´)器(frame-dropping filteråQ‰ï¼Œå…¶åŸºæœ¬æ–¹æ³•是客户端根据网¾lœä¸¢åŒ…率向过滤器发送请求来增减丢å“á速率åQŒä»¥è°ƒèŠ‚åª’ä½“‹¹çš„带宽。这¿Ué€ŸçŽ‡æ•´åŞ可以在拥塞点˜q›è¡ŒåQŒè¿™æ ·å¯ä»¥æé«˜é€ŸçŽ‡æŽ§åˆ¶çš„æ•ˆçŽ‡å’Œæ‹¥å¡žæŽ§åˆ¶çš„å“åº”æ—¶é—´ã€?br /> <br /> 应用层组播:(x¨¬)IP层的¾l„播存在诸如可扩展性、网¾lœç®¡ç†å’Œå¯šw«˜å±‚应用的支持åQˆä¾‹å¦‚差错控åˆÓž¼Œ‹¹é‡æŽ§åˆ¶å’Œæ‹¥å¡žæŽ§åˆÓž¼‰½{‰å±éšœã€‚应用层¾l„播机制打破了IP¾l„播的一些障¼„ï¼Œå…¶ç›®çš„在于构建网¾lœä¸Šçš„组播服务,可以以更灉|´»çš„æ–¹å¼å®žçŽ°ç»„æ’­æŽ§åˆ¶ã€‚å®ƒå…è®¸ç‹¬ç«‹çš?CSPså’ŒASPs½{‰å¾ç«‹å®ƒä»¬çš„Internet¾l„æ’­¾|‘络åQŒè¿™äº›ç»„播网¾lœå¯ä»¥äº’˜qžæˆä¸ºæ›´å¤§çš„媒体¾l„æ’­¾|‘络。媒体组播网¾lœå¯ä»¥åˆ©ç”¨å†…容分布网¾lœçš„互连åQŒé€šè¿‡åœ¨ä¸åŒç§¾cÈš„æœåŠ¡æä¾›è€…ï¼ˆæ¯”å¦‚ISPs、CSPså’ŒASPs½{‰ï¼‰ä¹‹é—´çš„应用层的对½{‰å…³¾pÀL¥æž„徏。媒体组播网¾lœä¸­æ¯ä¸ªå…ähœ‰¾l„播能力的节点称为媒体桥åQˆMediaBridgeåQ‰ï¼Œå®ƒåšä¸ºåº”用层的èµ\由。每个媒体桥和一个或多个盔R‚»çš„媒体桥通过明确的配¾|®äº’˜qžï¼Œ˜q™ä¸ªäº’连建立了应用层重叠拓扑。媒体桥在媒体组播网¾lœä¸­ç”¨åˆ†å¸ƒå¼åº”用层组播èµ\ç”Þq®—法来¼‹®å®šä¸€æ¡ä¼˜åŒ–的虚拟¾l„播路径。如果网¾lœä¸é€šæˆ–者过度拥挤,媒体¾l„æ’­¾|‘络ä¼?x¨¬)自动的æ Ò?gu¨©)®åº”用层èµ\ç”Þp§„则来重新¼‹®å®šè·¯å¾„ã€‚åÆˆä¸”ï¼Œåªæœ‰å½“ä¸‹æ¸¸å®¢æˆïL(f¨¥ng)«¯éœ€è¦æŸåª’体内容æ—Óž¼Œåª’体桥才ä¼?x¨¬)传输它。这ž®Þq¡®ä¿äº†ä¸ç®¡å®¢æˆ·ç«¯çš„æ•°ç›®è€Œåªæœ‰ä¸€ä¸ªåª’体流åQŒä»Žè€ŒèŠ‚¾U¦äº†¾|‘络带宽ã€?br /> <br /> 内容复制åQšå†…å®?媒体复制是提高媒体传输系¾lŸå¯æ‰©å±•性的一™åšw‡è¦æŠ€æœ¯ã€‚内容复制具有以下优点:(x¨¬) <br /> <br /> åQ?åQ‰é™ä½Žç½‘¾lœè¿žæŽ¥çš„带宽消耗ã€?<br /> <br /> åQ?åQ‰å‡è½ÀLµæœåŠ¡å™¨è´Ÿè—÷€?<br /> <br /> åQ?åQ‰ç¾ƒçŸ­å®¢æˆïL(f¨¥ng)«¯æ—¶åšgã€?<br /> <br /> åQ?åQ‰æé«˜æœ‰æ•ˆæ€§ã€‚它主要有两¿UåŞ式:(x¨¬)cachingåQˆç¼“存)和mirroringåQˆé•œåƒï¼‰ã€‚镜像是把原始媒体内å®ÒŽ(gu¨©)‹·è´åˆ°¾|‘络上其他分散的备䆾服务器中。用户可以从最˜q‘的备䆾服务器上获得媒体数据。缓存则是从原服务器中获得媒体文ä»Óž¼Œç„¶åŽä¼ è¾“¾l™å®¢æˆïL(f¨¥ng)«¯åQŒåŒæ—¶åœ¨æœ¬åœ°åšå¤‡ä»½ã€‚如果缓存中已经存在客户端需要的数据åQŒç¼“存就ä¼?x¨¬)把本地拯‚´ä¼ ç»™ç”¨æˆ·è€Œä¸æ˜¯ä»Žä¼ é€åŽŸæœåŠ¡å™¨ä¸­çš„åª’ä½“æ•°æ®ã€?br /> <br /> 2.4 ‹¹æœåŠ¡å™¨è§†é¢‘æœåŠ¡å™¨åœ¨‹¹åª’体服务中èµïL(f¨¥ng)€éžå¸¸é‡è¦çš„作用。当视频服务器响应客æˆïL(f¨¥ng)š„视频‹¹è¯·æ±‚以后,它从存储¾pȝ»Ÿè¯Õd…¥ä¸€éƒ¨åˆ†è§†é¢‘数据到对应于˜q™ä¸ªè§†é¢‘‹¹çš„特定¾~“存中,再把¾~“存的内定w€šè¿‡¾|‘络接口发送给相应客户åQŒä¿è¯è§†é¢‘流的连¾l­è¾“出。目前存在三¿Uç±»åž‹çš„视频服务器结构[4]åQ?<br /> <br /> åQ?åQ‰é€šç”¨ä¸ÀLœºæ–ÒŽ(gu¨©)³•。采用计½Ž—机ä¸ÀLœºä½œäØ“(f¨´)视频服务器。它的主要功能是存储、选择、传送数据。缺ç‚ÒŽ(gu¨©)˜¯¾pȝ»Ÿæˆæœ¬é«˜è€Œä¸”不利于发挥主机功能ã€?<br /> <br /> åQ?åQ‰ç´§è€¦åˆå¤šå¤„理机。把一些可以大量完成某指ä×o(h¨´)或者专门功能的¼‹¬äšg单元¾l„合成的专用¾pȝ»Ÿ¾U§è”èµäh¥åQŒå°±æž„成了紧耦合多处理机实现的视频服务器。这¿UæœåŠ¡å™¨è´¹ç”¨ä½Žã€æ€§èƒ½é«˜ã€åŠŸèƒ½å¼ºåQŒä½†æ˜¯æ‰©å±•性较差ã€?<br /> <br /> åQ?åQ‰è°ƒè°è§†é¢‘服务器。这¿UæœåС噍ä¸ÀL¿ä¸Šæœ‰ä¸€ä¸ªç‹¬ç‰¹å¾®ç çš„嵌入式仿真器控制。通过在主板中插入更多的服务通èµ\åQŒå¯ä»¥æ–¹ä¾¿åœ°˜q›è¡Œæ‰©å±•ã€?br /> <br /> 对于‹¹æœåС噍åQŒå¦‚何更有效支持VCR交互控制功能åQ›å¦‚何设计磁盘阵列上多媒体对象高效可靠的存储和检索;如何设计更好的可伸羃多媒体服务器åQ›å¦‚何设计兼有奇偶和镜像ç‰ÒŽ(gu¨©)€§çš„定w”™å­˜å‚¨¾pȝ»Ÿæ˜¯ç›®å‰ç ”½I¶çš„重点ã€?br /> <br /> 2.5 媒体同步 <br /> <br /> 所谓媒体同步是指保持一个数据流或者不同媒体流之间的时间关¾p…R€‚通常有三¿Uç±»åž‹çš„同步控制åQšæµå†…ï¼ˆintra-streamåQ‰åŒæ­¥ã€æµé—ß_(d¨¢)¼ˆinter- streamåQ‰åŒæ­¥å’Œå¯¹è±¡é—ß_(d¨¢)¼ˆinter-objectåQ‰åŒæ­¥ã€‚由于网¾lœæ—¶å»Óž¼Œå¯ÆD‡´åª’体‹¹åœ¨ä¼ è¾“˜q‡ç¨‹ä¸­å¤±åŽÕdŒæ­¥å…³¾p»ï¼Œåª’体同步机制可以¼‹®ä¿å®¢æˆ·ç«¯æ­£¼‹®åœ°æ¢å¤åª’体‹¹çš„同步。媒体同步机制实际上ž®±æ˜¯åœ¨åª’体内或者媒体间说明其时间关¾p…R€‚说明时间关¾pÈš„æ–ÒŽ(gu¨©)³•有:(x¨¬)åŸÞZºŽé—´éš”的方法、基于èáu的方法、基于控制流的方法和åŸÞZºŽäº‹äšg的方法。对于连¾l­åª’体,应用最为广泛的说明æ–ÒŽ(gu¨©)³•是基于èáu的说明或旉™—´æˆŸë€‚时间戳法是在每个媒体的数据‹¹å•元中加进¾lŸä¸€çš„æ—¶é—´æˆ³æˆ–时间码åQŒå…·æœ‰ç›¸åŒæ—¶é—´æˆ³çš„信息单元将同时予以表现。在发送时åQŒå°†å„个媒体都按旉™—´™åºåºåˆ†æˆå•å…ƒåQŒåœ¨åŒä¸€ä¸ªæ—¶é—´èáu上,¾l™æ¯ä¸ªå•元都打上一个时间戳åQŒå¤„于同一时标的各个媒体单元具有相同的旉™—´æˆŸë€‚在各个媒体到达¾lˆç«¯åŽï¼Œè®©å…·æœ‰ç›¸åŒæ—¶é—´æˆ³çš„媒体单元同时进行表玎ͼŒ˜q™æ ·ž®±å¾—åˆîCº†åª’体之间同步的效果。对与终端系¾lŸè€Œè¨€åQŒåŒæ­¥æœºåˆ¶åŒ…括阻止(preventiveåQ‰æœºåˆ¶å’Œ¾U æ­£åQˆcorrectiveåQ‰æœºåˆ¶ã€‚前者是主要通过减小延迟和抖动来减少同步错误åQŒåŽè€…主要是在发生同步错误之后恢复同步。考虑到Internet传输的åšg˜qŸéšæœºæ€§ï¼ŒåŒæ­¥é”™è¯¯æ˜¯ä¸å¯é¿å…çš„。因此,在接受方的错误补偿是必须的ã€?<br /> <br /> 另外åQŒåŒæ­¥å¤šåª’体集成语言SMILåQˆSynchronized Multimedia Integration LanguageåQ‰æ˜¯ç”?W(World Wide Web Consortium)¾l„织规定的多媒体操纵语言。可以实现多个流和文本信息在播放时的旉™—´åŒæ­¥æŽ§åˆ¶å’Œç©ºé—´ä½¾|®å¸ƒ¾|®ã€‚通过SMIL˜q˜å¯ä»¥å®žçŽîC¸€å®šçš„用户交互功能ã€?br /> <br /> 2.6 ‹¹åª’体相兛_è®?br /> <br /> 2.6.1 实时传输协议åQˆRTPåQ‰ä¸Žå®žæ—¶ä¼ è¾“控制协议åQˆRTCPåQ?<br /> <br /> RTP(Real-time Transport Protocol)å’ŒRTCPåQˆReal-time Control ProtocolåQ‰éƒ½æ˜¯åŸºäºŽIP的应用层协议。RTP为实旉™Ÿ³/视频数据提供端到端的传送服务,包括有效载荷¾cÕdž‹æ ‡è¯†ã€åºåˆ—标受÷€æ—¶é—´æ ‡½{‘Ö’Œæºæ ‡è¯†ï¼Œå¯ä»¥æä¾›æ—‰™—´ä¿¡æ¯å’Œå®žçŽ°æµåŒæ­¥ã€‚ç”±äºŽTCP中重传机制会(x¨¬)引è“væ—¶åšgåQŒé€šå¸¸RTP˜qè¡ŒäºŽUDP之上åQŒä½†æ˜¯ä¹Ÿå¯ä»¥åœ¨TCP或者ATM½{‰åè®®ä¹‹ä¸Šè¿è¡Œã€‚RTP本èínòq¶ä¸æä¾›å¯é çš„传送机åˆÓž¼Œä¹Ÿä¸æä¾›‹¹é‡æŽ§åˆ¶æˆ–者拥塞控åˆÓž¼Œè€Œæ˜¯é€šè¿‡ä¸ŽRTCP配合使用åQŒä‹É传输效率最佟뀂RTCP用来监视服务质量和在ä¼?x¨¬)è®®˜q‡ç¨‹ä¸­äº¤æ¢ä¿¡æ¯ã€‚它提供QoS反馈、参与者标识、控制包¾~©æ”¾ã€åª’体间同步½{‰æœåŠ¡ã€‚RTCP包中包含已发数据包的数量、丢失数据包数量½{‰ç»Ÿè®¡èµ„料。服务器可以æ ÒŽ(gu¨©)®˜q™äº›ä¿¡æ¯åŠ¨æ€çš„æ”¹å˜ä¼ è¾“é€ŸçŽ‡ç”šè‡³æœ‰æ•ˆè½½è·¾cÕdž‹ã€?br /> <br /> 2.6.2 实时‹¹åè®®ï¼ˆRTSPåQ‰RTSPåQˆReal-time Streaming ProtocolåQ‰æ˜¯ç”±RealNetworkså’ŒNetscape共同提出的一个应用层协议。它可以在媒体服务器和客æˆïL(f¨¥ng)«¯ä¹‹é—´å»ºç«‹å’ŒæŽ§åˆ¶è¿ž¾l­çš„éŸ?视频媒体‹¹ï¼ŒååŒæ›´ä½Žå±‚协议RTP、RSVP½{‰ä¸€èµäh¥æä¾›åŸÞZºŽInternet的整套流式服务。RTSP提供了一¿Uå¯æ‰©å±•框架åQŒä‹É得可控的、点播的实时数据的传送成为可能。它提供用于音频和视频流çš?#8220;VCR模式”˜qœç¨‹æŽ§åˆ¶åŠŸèƒ½åQŒä¾‹å¦‚暂停、快˜q›ã€å¿«é€€å’Œå®šä½ã€‚支持单播和¾l„播。RTSP˜q˜æä¾›é€‰æ‹©å‘送通道的方法(如UDP、组播UDPå’ŒTCPåQ‰å’ŒåŸÞZºŽRTP的发送机制。RTSP像是媒体服务器和客户端之间的“¾|‘络˜qœç¨‹æŽ§åˆ¶”åQŒå®ƒæä¾›å¤šç§æœåŠ¡åQŒå¦‚从媒体服务器上检索媒体、邀(g¨¨)请媒体服务器˜q›å…¥ä¼?x¨¬)议、添加媒体到现成节目。RTSP在语法和操作上类ä¼égºŽHTTPåQŒå› æ­¤è®¸å¤šHTTP的扩展机刉™ƒ½å¯ä»¥¿UÀL¤äºŽRTSP上。在 RTSP中,每个节目和媒体流由RTSP URL¼‹®å®šåQŒå…¨éƒ¨èŠ‚ç›®å’Œåª’ä½“ç‰ÒŽ(gu¨©)€§éƒ½åœ¨èŠ‚ç›®æ˜q°æ–‡ä»¶ä¸­¾l™äºˆäº†æ˜qŽÍ¼ŒåŒ…括¾~–码、语­a€ã€RTSP URLs、目的地址、端口号以及(qi¨¢ng)其他参数。但是,不同于HTTP的无状态和非对¿UŽÍ¼ŒRTSP是有状态的、对¿U°çš„协议。RTSP的服务器保持ä¼?x¨¬)话状态以˜qžæŽ¥ RTSP‹¹çš„è¯äh±‚åQŒåƈ且服务器和客æˆïL(f¨¥ng)«¯éƒ½å¯ä»¥å‘凸™¯·æ±‚ã€?br /> <br /> 2.6.3 资源预留协议åQˆRSVPåQ‰èµ„源预留协议[5]åQˆResource Reserve ProtocolåQ‰æ˜¯˜qè¡ŒäºŽä¼ è¾“层的一个网¾lœæŽ§åˆ¶åè®®ã€‚RSVP允许数据‹¹çš„æŽ¥å—方请求特ŒDŠçš„端到端QoS。RSVP是非路由协议åQŒå®ƒåŒèµ\由器协同工作åQŒåœ¨ä¼ è¾“路径的èµ\由器上预留必要的带宽åQŒå‡ž®‘网¾lœçš„æ—¶åšg和抖动。RSVP的流½E‹æ˜¯å•一的,òq¶ä¸åŒºåˆ†å‘送方和接受方åQŒä¸”支持单播和组播,适应于可变成员个数和路由。RSVP领域的发展非常迅速,但是目前它的应用只限于在‹¹‹è¯•的小Intranet¾|‘络上ã€?br /> <br /> <strong>3 ¾l“论</strong>技术的˜q›æ­¥å’Œç”¨æˆïL(f¨¥ng)š„需求促˜q›äº†‹¹åª’体应用的˜q…速发展。在˜qœç¨‹æ•™è‚²ã€æ•°å­—图书馆、电(sh¨´)子商务、视频点播、交互电(sh¨´)视、远½E‹åŒ»ç–—、网¾lœéŸ³/视频、实时多媒体ä¼?x¨¬)è®®½{‰æ–¹é¢ï¼Œ‹¹åª’体技术都起到很重要的作用。本文对¾|‘络中流媒体业务的关键技术和相关协议做了研究åQŒåƈ探讨了未来流媒体技术发展的方向。我们相信,随着‹¹åª’体应用的不断普及(qi¨¢ng)åQŒå®½å¸¦æµåª’体技术及(qi¨¢ng)其应用必然会(x¨¬)在未来的¾|‘络中发挥更重要的作用,òq¶åœ¨ä¸€å®šç¨‹åº¦ä¸Šæ”¹å˜äºÞZ»¬ä½¿ç”¨¾|‘络的方式ã€? <img src ="http://www.aygfsteel.com/jelver/aggbug/196409.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/jelver/" target="_blank">冰河快狼</a> 2008-04-27 10:31 <a href="http://www.aygfsteel.com/jelver/articles/196409.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一¿Ué«˜æ•ˆæµåª’体ç”?sh¨´)媄服务器的设è®?è½?http://www.aygfsteel.com/jelver/articles/196400.html冰河快狼冰河快狼Sun, 27 Apr 2008 01:53:00 GMThttp://www.aygfsteel.com/jelver/articles/196400.htmlhttp://www.aygfsteel.com/jelver/comments/196400.htmlhttp://www.aygfsteel.com/jelver/articles/196400.html#Feedback0http://www.aygfsteel.com/jelver/comments/commentRss/196400.htmlhttp://www.aygfsteel.com/jelver/services/trackbacks/196400.html1 引言

     随着¾|‘络技术的发展åQŒä¸»òq²ç½‘与宽带网接入技术的日臻成熟åQŒç½‘¾lœè§†é¢‘çš„ä¼ è¾“æˆäØ“(f¨´) Internet应用的一个亮炏V€‚䨓(f¨´)了提高视频数据在¾|‘上的传输效率,òq¶å®žçŽ°è§†é¢‘çš„å®žæ—¶æ’­æ”¾åQŒæµåª’体技术的研究与应用得åˆîCº†å¾ˆå¤§å‘展。其中,‹¹åª’体服务器技术在‹¹åª’体的应用中发挥了关键的作用ã€?br />
     传统的网¾lœä¼ è¾“数据的æ–ÒŽ(gu¨©)³•是文件下载:(x¨¬)用户需要准备大量的¼‚ç›˜½Iºé—´åQŒåƈ花大量的旉™—´½{‰å¾…下蝲¾l“束。但是,当数据变成æ“v量的视频数据æ—Óž¼Œåœ¨æ•°æ®å¤„理量大,数据吞吐量高åQŒè§†é¢‘播攑֮žæ—¶æ€§ï¼Œå®¢æˆ·˜qžæŽ¥è¯äh±‚数目大,˜qžæŽ¥æ—‰™—´é•¿ç­‰ä¸€äº›æƒ…况下åQŒä¼ ¾lŸçš„æœåŠ¡å™¨æŠ€æœ¯å·²¾læ— æ³•高效的满èƒö要求。面对这æ ïL(f¨¥ng)š„æŠ€æœ¯è¦æ±‚,本文ä»?CPU调度åQŒèµ„源控制内存分配,IåQOæ€Èº¿½Ž¡ç†˜q™ä¸‰ä¸ªæ–¹é¢å‡ºå‘,¾l¼åˆçš„ç»™å‡ÞZº†ä¸€¿Ué«˜æ•ˆçš„æœåŠ¡å™¨è®¾è®¡æ–¹æ³•ï¼Œä»Žè€Œæœ‰æ•ˆçš„æé«˜äº†è§†é¢‘æµå¼ä¼ è¾“æ—¶çš„æ•ˆçŽ‡ã€‚è¯¥æ–ÒŽ(gu¨©)³•也具有很强的可扩展性,当服务器的CPU数目增加æ—Óž¼ŒæœåŠ¡å™¨çš„æ€§èƒ½ž®†èƒ½å¾—到成倍的增长ã€?br /> 2 ‹¹åª’体服务器的设è®?/strong>

2åQ? ‹¹åª’体服务器的功èƒ?br />
‹¹åª’体在播放前不是完全下载整个文ä»Óž¼Œè€Œæ˜¯æŠŠå¼€å§‹éƒ¨åˆ†å†…容存入内存,数据‹¹æ˜¯éšæ—¶ä¼ é€éšæ—¶æ’­æ”¾ã€?br />
‹¹åª’体服务器提供的流式传输方式有两种åQšé¡ºåºæµå¼ä¼ è¾“和实时‹¹å¼ä¼ è¾“两种方式。顺序流式传输是™åºåºä¸‹è²åQŒåœ¨ä¸‹è²æ–‡äšg的同时用户可观看在线媒体。实时流式传输与™åºåº‹¹å¼ä¼ è¾“不同åQŒå®žæ—¶æµå¼ä¼ è¾“æ€ÀL˜¯å®žæ—¶ä¼ é€ï¼Œç‰¹åˆ«é€‚合现场事äšg。实时流式传输必™åÕdŒ¹é…è¿žæŽ¥å¸¦å®½ï¼Œ˜q™æ„å‘³ç€å›‘Öƒè´¨é‡ä¼?x¨¬)å› ¾|‘络速度降低而变差ã€?br />
在流式传输时åQŒæµåª’体数据å…ähœ‰å®žæ—¶æ€§ï¼Œ½{‰æ—¶æ€§ç­‰åŸºæœ¬ç‰¹ç‚¹åQŒæµæœåŠ¡æœŸå’Œå®¢æˆ·¾lˆç«¯è¦ä¿è¯å„¿Uåª’体间的同步关¾p»ï¼Œå› æ­¤åQŒæµåª’体传输å¯?#8220;最大åšgæ—?#8221;åQ?#8220;延时抖动”½{‰QoS参数都有严格要求ã€?br />
2åQ? ‹¹åª’体服务器协议栈的设计

在TCPåQIP参考模型中åQŒä¼ è¾“层通信协议TCPå’ŒUDP都不能满­‘Ïxµåª’体传输的QoS要求。由于TCP协议采用滑动½H—口控制机制åQŒæ•°æ®ä¼ é€éšç€‹¹æŽ§½H—口动态的启动和关闭,难以满èƒö‹¹åª’体实时和½{‰æ—¶çš„传送要求。UDP协议的无˜qžæŽ¥ç‰¹ç‚¹èƒ½å¤Ÿæé«˜ä¼ è¾“速率åQŒè™½ç„¶å¯ä»¥åœ¨æŸç§½E‹åº¦ä¸Šæ»¡­‘Ïxµåª’体的实时性要求,但是ç”׃ºŽå…¶æœ¬íw«çš„不可靠性,也无法满­‘Ïxµåª’体传输的需要ã€?br />
针对传输层协议的矛盾åQŒäØ“(f¨´)了实现流媒体在IP上的实时传送播放,设计‹¹åª’体服务器旉™œ€è¦åœ¨ä¼ è¾“层协议(TCPåQUDPåQ‰å’Œåº”用层之间增加一个通信控制层。在增加的通信控制层,采用相应的实时传输协议,主要有:(x¨¬)数据‹¹éƒ¨åˆ†çš„实时传输协议RTPåQˆRealåQtime Transport ProtocolåQ‰ï¼Œç”¨äºŽæŽ§åˆ¶éƒ¨åˆ†çš„实时传输控制协议RTCPåQˆRealåQtime Transportå›? ‹¹åª’体服务协议栈Streaming ProtocolåQ‰ã€‚RTP协议主要是用来传送实时的‹¹åª’体信息,数据报主要包括多媒体数据åQŒä»¥å?qi¨¢ng)所携带负蝲的时间戳åQŒé¡ºåºå·½{‰ã€‚RTCP协议的数据报主要包括了接收者收到某个多媒体‹¹çš„æœåŠ¡è´¨é‡ä¿¡æ¯åQŒç”¨äºŽå¯¹æœåŠ¡å™¨ç«¯çš„åé¦ˆã€?br />
‹¹åª’体服务器的协议栈如图1所½Cºã€?



当服务器收到RTSPè¯äh±‚åQŒå®ƒé¦–先产生RTSPè¯äh±‚对象。服务器通过RTSP协议的应½{”信息将è¯äh±‚的内容以‹¹ä¼š(x¨¬)话(streaming sessionåQ‰çš„形式描述åQŒå†…容包括数据流包含多少个流、媒体类型、和¾~–解码格式。一个流ä¼?x¨¬)话ç”׃¸€ä¸ªæˆ–多个数据‹¹ç»„成,如视频流和音频流½{‰ã€‚实际的数据‹¹é€šè¿‡RTP协议传递到客户端。RTP在一对一或一对多的传输情况下工作åQŒå…¶ç›®çš„æ˜¯æä¾›æ—¶é—´ä¿¡æ¯å’Œå®žçް‹¹åŒæ­¥ã€‚RTP本èínòq¶ä¸èƒ½äØ“(f¨´)™åºåºä¼ é€æ•°æ®åŒ…提供可靠的传送机åˆÓž¼Œå®ƒä¾é RTCP一èµähä¾›æµé‡æŽ§åˆ¶å’Œæ‹¥å¡žæŽ§åˆ¶æœåŠ¡ã€‚åœ¨RTPä¼?x¨¬)话期间åQŒå„˜qžæŽ¥è€…监视下层网¾lœçš„æ€§èƒ½åQŒåƈž®†ç›¸å…³ä¿¡æ¯æ”¾å…¥RTCP包,周期性地传é€?RTCP包来通知发送方。发送方也可以用RTCP包提供每‹Æ¡çš„ä¼?x¨¬)话信息åQŒåŒ…中含有已发送的数据包的数量、丢å¤Þqš„æ•°æ®åŒ…的数量½{‰ç»Ÿè®¡èµ„料。因此服务器可以利用˜q™äº›ä¿¡æ¯åŠ¨æ€åœ°æ”¹å˜ä¼ è¾“é€ŸçŽ‡åQŒç”šè‡Ïx”¹å˜æœ‰æ•ˆè²èïL(f¨¥ng)±»åž‹ã€‚RTPå’ŒRTCP配合使用åQŒå› æœ‰æ•ˆçš„反馈和最ž®çš„开销使传输效率最ä½?j¨©ng)_Œ–ã€?br />
‹¹åª’体服务器的功能框囑֦‚å›?所½Cºã€?/p>



2åQ? 高效‹¹åª’体服务器的设è®?br />
通过‹¹åª’体服务器的协议栈的设计,可以明确‹¹åª’体服务器是在传输层协议(TCPåQŒUDPåQ‰ä¸Šè§£é‡ŠRTPåQŒRTCPåQŒRTSP协议的,所有的客户˜qžæŽ¥è¯äh±‚都是以TCP的端口获得的åQŒæµåª’体数据也都是打成RTP包,通过UDP端口发出åŽÈš„åQŒå› æ­¤ï¼Œå¯¹äºŽTCPåQŒUDP端口事äšg的调度以å?qi¨¢ng)如何把大量的流媒体数据从磁盘空间传递到¾|‘络上成为制¾U¦æµåª’体服务器性能的主要因素ã€?br />
‹¹åª’ä½“æœåŠ¡å™¨é¢å¯¹ä¸€ä¸ªå•ä¸€çš„å®¢æˆøP¼Œå®Œæˆçš„过½E‹å¦‚下:(x¨¬)

1åQ‰åœ¨å®¢æˆ·ç«¯å‘出RTSP˜qžæŽ¥è¯äh±‚后,服务器通过对TCP端口的监听,è¯Õd…¥è¯äh±‚ã€?br />
2åQ‰è§£æžè¯·æ±‚内容,调入相应的流媒体文äšgã€?br />
3åQ‰åŞ成RTP包,分发数据‹¹åŒ…åQŒèŽ·å¾—RTCP包ã€?br />
4åQ‰æ•°æ®åŒ…发送完毕,关闭˜qžæŽ¥ã€?br />
上述˜q‡ç¨‹å¦‚果采用传统的服务器设计æ–ÒŽ(gu¨©)³•实现åQŒä¸€èˆ¬çš„办法是用一个线½E‹ä¸æ–­çš„è¯Õd…¥ç”¨æˆ·çš„连接请求,然后ž®†è¿™äº›è¯·æ±‚分‹z„¡»™å…¶å®ƒçš„工作线½E‹ï¼Œ˜q™äº›å·¥ä½œ¾U¿ç¨‹åˆ™åˆ†åˆ«åó@环往复的完成以下的工作:(x¨¬)

1åQ‰è§£æžè¯·æ±‚内宏V€?br />
2åQ‰å‘送RTP包,发送接收RTCPåŒ?br />
3åQ‰åˆ¤æ–­æ•°æ®å‘送完毕,关闭˜qžæŽ¥ã€‚服务器的结构如å›?所½Cºã€?/p>



操作¾pȝ»Ÿåœ¨å¯¹‹¹åª’体服务器的功能实çŽîC¸Šé‡‡ç”¨ä»¥åº”用进½E‹ï¼ˆ¾U¿ç¨‹åQ‰äØ“(f¨´)中心的系¾lŸèµ„源管理方式。操作系¾lŸé‡‡ç”¨è™šæ‹Ÿå†…存方式,应用½E‹åºçš„虚拟内存空间映ž®„到物理内存åQŒç‰©ç†å†…存与CPU之间有Cache。当‹¹åª’体数据从¼‚ç›˜ä¸Šåˆ°¾|‘络上进行传递时åQŒè¦åœ¨ä¸åŒçš„¾pȝ»Ÿ½Iºé—´ä¸­è¿›è¡Œå¤š‹Æ¡ä¼ é€’拷贝,如图4所½Cºã€?/p>



å›?昄¡¤ºäº†ç£ç›˜æ•°æ®åˆ°¾|‘络接口的传递èµ\径:(x¨¬)首先åQŒæ•°æ®å¯¹è±¡ä»Ž¼‚ç›˜æ‹¯‚´åˆ°å†…存中åQŒç„¶åŽï¼Œæ•°æ®åœ¨å†…存中ç”׃ºŽæ¯ä¸ªå·¥ä½œ¾U¿ç¨‹çš„空间不同,˜q›è¡Œ½Iºé—´æ‹¯‚´åQŒå³ä»Žæ ¸å¿ƒç©ºé—´æ‹·è´åˆ°˜q›ç¨‹½Iºé—´åQŒæŽ¥ç€åQŒæ•°æ®å†ä»Žè¿›½E‹ç©ºé—´æ‹·è´åˆ°æ ¸å¿ƒ½Iºé—´åQŒæœ€åŽæ•°æ®å†æ‹¯‚´åˆ°ç½‘¾lœä¸Šã€‚由于流媒体数据要经˜q‡RTP的打包处理,因此åQŒæ•°æ®åœ¨æ‹¯‚´åˆ°ç½‘¾lœä¸Šä¹‹å‰åQŒè¿˜è¦æ‹·è´åˆ°CacheåQŒå†ä»ŽCache中拷贝到CPU寄存器,˜q›è¡Œæ‰“包处理ã€?br />
从图3可以看出åQŒéšç€å·¥ä½œ¾U¿ç¨‹æ•°n的增大,¾pȝ»Ÿåœ¨å„¾U¿ç¨‹ä¹‹é—´çš„切换开销ž®†æ€¥å‰§å¢žåŠ åQŒä»Žæ“ä½œ¾pȝ»Ÿçš„角度来看,ç”׃ºŽæ¯ä¸ª¾U¿ç¨‹éƒ½æ¶‰å?qi¨¢ng)对¼‹¬ç›˜è§†é¢‘数据的读取,各自独立的线½E‹è¶Šå¤šï¼Œå¯¹ç¡¬ç›˜è¯»å†™çš„æ•°æ®é‡å°±­‘Šå¤§åQŒæ•°æ®åœ¨ä¸åŒ½Iºé—´çš„æ‹·è´å¢žåŠ ï¼Œæ“ä½œ¾pȝ»Ÿž®†ä¸æ–­çš„˜q›è¡Œ™åµé¢åˆ‡æ¢åQŒæœåŠ¡å™¨çš„æ€§èƒ½éšç€å®¢æˆ·˜qžæŽ¥æ•°çš„增多åQŒæ•ˆçŽ‡å°†æ€¥å‰§ä¸‹é™ã€?br />
ä¸ÞZº†æ”¹å–„上述设计的缺点,需重新设计服务器的服务½E‹åº¾l“构。根据服务器在流媒体传输中所要完成的功能åQŒå¯ä»¥çœ‹å‡ºï¼Œ<服务器在客户有连接请求时åQŒè§£æžè¿žæŽ¥è¯·æ±‚和关闭˜qžæŽ¥è¯äh±‚是很短的˜q‡ç¨‹æœåŠ¡å™¨çš„å¤§éƒ¨åˆ†æ—¶é—´éƒ½ç”¨äºŽ¾l™æ¯ä¸ªå®¢æˆ·å‘送RTP数据‹¹åŒ…。发送RTP数据‹¹åŒ…包括服务器把相应的媒体文件调入内存,打包发送,以及(qi¨¢ng)获得RTCP包的反馈。因此,可以设计一个单独的处理¾U¿ç¨‹åQŒä¸“门用于给客户发送RTP的数据流包ã€?br />
改进的流媒体服务器设计如å›?所½Cºï¼Œå®Œæˆä¸»è¦çš„功能通过两个¾U¿ç¨‹æ¥å®žçްã€?br />
事äšg¾U¿ç¨‹è´Ÿè´£‹‚€(g¨¨)‹¹‹å®¢æˆ¯‚¿žæŽ¥ï¼Œä»¥åŠ(qi¨¢ng)客户发的RTCP包的到来。事件线½E‹é€šè¿‡å¯¹TCP端口的检‹¹‹ï¼Œåœ¨æœ‰˜qžæŽ¥è¯äh±‚时徏立可¾l´æŠ¤å®¢æˆ·ä¿¡æ¯çš„RTSPä¼?x¨¬)话åQŒåœ¨æ¯ä¸€ä¸ªå®¢æˆïL(f¨¥ng)š„RTSPä¼?x¨¬)话的存‹(g¨°u)zÀLœŸå†…,事äšg¾U¿ç¨‹ä¸æ–­çš„æŠŠå‘客户发送RTP包这一ä»ÕdŠ¡æ”‘Ö…¥å¤„理¾U¿ç¨‹çš„队列,直到RTSPä¼?x¨¬)话¾lˆæ­¢åQŒäº‹ä»¶çº¿½E‹å†æŠŠå…³é—­è¿žæŽ¥çš„ä»ÕdŠ¡æ”‘Ö…¥é˜Ÿåˆ—ã€?br />
事äšg¾U¿ç¨‹æŠŠå¯¹ä¸åŒå®¢æˆ·çš„æœåŠ¡ï¼ˆå‘é€RTP数据包)以ä“Q务的形式攑օ¥é˜Ÿåˆ—后,处理¾U¿ç¨‹å¯¹å¯¹åˆ—中的ä“Q务依‹Æ¡è¿›è¡Œå¤„理,也就是说åQŒå¤„理线½E‹æ ¹æ®å®¢æˆïL(f¨¥ng)š„不同åQŒä¸æ–­çš„æŠŠç›¸åº”çš„‹¹åª’体文件åŞ成RTP包,依次发出åQŒç›´åˆ°è§†é¢‘服务的¾lˆæ­¢ã€?br />
可以看的出来åQŒå¤„理线½E‹è™½ç„¶å¯¹æ‰€æœ‰çš„客户提供服务åQŒä½†æ˜¯æ‰§è¡Œçš„ä»ÕdŠ¡å§‹ç»ˆæ˜¯å‘é€RTP数据‹¹åŒ…åQŒåŒæ—Óž¼Œè¯¥çº¿½E‹æ‰€è®‰K—®çš„媒体文件被调入内存后,可以被同一¾U¿ç¨‹çš„其它ä“Q务重复调用,˜q™æ ·çš„设计,不但减少了随着客户数增加而造成的系¾lŸé¢‘¾Jåˆ‡æ¢çš„资源损失åQŒä¹Ÿå‡å°‘了访问硬盘数据的‹Æ¡æ•°åQŒç¾ƒçŸ­äº†è®‰K—®æ—‰™—´åQŒä¹Ÿå‘挥了指令局部性效率提高的优点。设å›? 改进后的处理‹¹ç¨‹è®¡ä¸­åQŒè§£æžå®¢æˆïL(f¨¥ng)š„˜qžæŽ¥è¯äh±‚也放入处理线½E‹çš„队列中,在处理线½E‹ä¸­˜q›è¡Œå¤„理åQŒè™½ç„¶è§£æžè¿žæŽ¥çš„ä»ÕdŠ¡ä¸åŒäºŽå¤§éƒ¨åˆ†å‘é€RTP包的ä»ÕdŠ¡åQŒä½†æ˜¯è¯¥ä»ÕdŠ¡æ¶ˆè€—æ—¶é—´å°‘åQŒæ‰€ä»¥å¯¹å¯¹ç³»¾lŸæ€§èƒ½çš„åª„å“åÆˆä¸å¤§ã€?



采用å›?的设计方法,服务器还可以æ ÒŽ(gu¨©)®å®¢æˆ·ç«¯åé¦ˆçš„RTCP包得知客æˆïL(f¨¥ng)«¯çš„网¾lœçŠ¶å†µï¼Œé‡‡å–ä¸€å®šçš„½{–略针对不同的客æˆïL(f¨¥ng)½‘¾lœè´¨é‡è¿›è¡ŒRTP包发送ä“Q务的调度åQŒå¯¹äºŽå¸¦å®½è´¨é‡å¥½çš„å®¢æˆøP¼Œäº‹äšg¾U¿ç¨‹å¯ä»¥å¤šæ”¾ä¸€äº›RTP包到队列中;对于ç”׃ºŽ¾|‘络质量造成的即ž®†è¶…时的客户˜qžæŽ¥åQŒæœåŠ¡å™¨ä¹Ÿå¯ä»¥é€šè¿‡ä»ÕdŠ¡è°ƒåº¦çš„æ–¹å¼è¿›è¡Œç‰¹ŒDŠå¤„理,最大限度的提供不同质量的客戯‚¿žæŽ¥æœåŠ¡ã€?br />
上述的设计是在硬件具有一个CPU的情况下åQŒå½“¾pȝ»Ÿ¼‹¬äšgå…ähœ‰çš„CPU个数为næ—Óž¼ˆnåQ?åQŒäº‹å®žä¸ŠåšäØ“(f¨´)‹¹åª’体服务器的硬仉™œ€æ±‚,一个CPU是远˜qœä¸èƒ½æ»¡­‘³ç³»¾lŸéœ€æ±‚çš„åQ‰ï¼Œ½E‹åºž®†é‡‡ç”¨n个处理线½E‹æ¥åˆ†æ‹…事äšg¾U¿ç¨‹è°ƒåº¦çš„ä“Q务,利用¾pȝ»Ÿçš„可扩展性来提高性能ã€?br />
2åQ? 性能分析

新设计的æ–ÒŽ(gu¨©)¡ˆå……分发挥了指令局部性和数据局部性的优点。处理线½E‹åœ¨å¤„理队列ä»ÕdŠ¡æ—Óž¼Œç”׃ºŽé˜Ÿåˆ—ä¸­æ¯ä¸€ä¸ªæ“ä½œæ‰€ä½œçš„äº‹éƒ½ä¸€æ øP¼ˆå¦‚不停的发RTP 包)åQŒå› æ­¤æ¯ä¸ªæ“ä½œçš„æŒ‡ä×o(h¨´)序列都是完全相同的;而且åQŒå½“客户在连接后要求获得热点节目的媒体文件时åQŒæŒ‡ä»¤æ“ä½œçš„æ•°æ®ä¹Ÿå°†éžå¸¸ç›¸è¿‘åQŒéƒ½åœ¨ä¸€ä¸ªèŒƒå›´å¾ˆž®çš„åŒºåŸŸå†…ã€‚è¿™æ øP¼Œ¾lè¿‡å‡ æ¬¡æ“ä½œåŽï¼Œå½“指令被加蝲到Cache中,数据加蝲到内存中后,ž®×ƒ¸å†éœ€è¦ä»Ž¼‚ç›˜ä¸­åŽ»è°ƒï¼Œæžå¤§æé«˜äº†ç¨‹åºçš„æ€§èƒ½ã€?br />
新设计的æ–ÒŽ(gu¨©)¡ˆå¯ä»¥å®žçް‹¹åª’体数据在内存中连¾l­å­˜æ”¾ï¼Œå¿«é€Ÿå­˜å–以å?qi¨¢ng)Cache预取åQŒèµ„源管理方式从以应用线½E‹äØ“(f¨´)中心的资源管理与分配转变ä¸ÞZ»¥æ•°æ®ä¸ÞZ¸­å¿ƒçš„资源½Ž¡ç†ä¸Žåˆ†é…ã€?br />
衡量‹¹åª’体服务器的性能可以æ ÒŽ(gu¨©)®æœåŠ¡CPU的负载情冉|¥è¡¡é‡ã€‚CPUçš„ä‹É用情况主要和˜qžæŽ¥çš„客æˆäh•°ç›®ï¼Œå®¢æˆ·ç«¯çš„æ“ä½œå¦‚读取,快进åQŒæœç´¢ç­‰ç›¸å…³ã€‚对于一ä¸?2kbps的文仉™›†åQŒæ”¹˜q›çš„æœåŠ¡å™¨è®¾è®¡æ–¹æ¡ˆä¸Žä¼ ç»Ÿçš„æœåŠ¡å™¨è®¾è®¡æ–ÒŽ(gu¨©)¡ˆçš„æ€§èƒ½ä¼˜åŠ£æ¯”è¾ƒæ›²çº¿åQŒå¦‚å›?所½Cºã€?br />
å›?体现了随着CPU数的增加åQŒä¼ ¾lŸè®¾è®¡æ–¹æ¡ˆçš„æ€§èƒ½å˜åŒ–不大åQŒæ”¹˜q›çš„设计æ–ÒŽ(gu¨©)¡ˆåœ¨å¤šä¸ªCPU的系¾lŸé‡ŒåQŒå……分利用了CPU所带的Cache的强大功能,CPUçš„æ€ÖM½“负蝲明显下降åQŒå¯ä»¥èŽ·å¾—æ€§èƒ½çš„æžå¤§æé«˜ã€?/p>



3 ¾l“束è¯?br />
本文从系¾lŸå¯æ‰©å±•æ–šw¢æå‡ºäº†å®žçŽ°é«˜æ•ˆçš„‹¹åª’体服务器的解å†Ïx–¹æ¡ˆã€‚除了系¾lŸå¯æ‰©å±•æ–šw¢åQŒè®¾è®¡ä¸€ä¸ªå®Œå–„的高效‹¹åª’体服务器åQŒè¿˜éœ€è¦åœ¨å®žæ—¶çš„æœåŠ¡å™¨æ“ä½œ¾pȝ»ŸåQŒç³»¾lŸèµ„源管理(CPU½Ž¡ç†åQŒå†…存管理,¼‚ç›˜èµ„源½Ž¡ç†åQ‰ï¼Œæ–‡äšg½Ž¡ç†åQŒæœåС噍¼‚ç›˜è°ƒåº¦æ–šw¢˜q›è¡Œé«˜æ•ˆçš„设计,˜q™éœ€è¦æˆ‘们进一步研½I¶å’Œè®¾è®¡ã€?/p>

]]>
Ö÷Õ¾Ö©Öë³ØÄ£°å£º ³Â°Í¶û»¢Æì| Ç­Î÷ÏØ| Ä®ºÓÏØ| ÐËÉ½ÏØ| ³¤Ë³ÏØ| º£ÁÖÊÐ| ±ö´¨ÏØ| ººÊÙÏØ| ÓÈÏªÏØ| ÓñÃÅÊÐ| ƽ½­ÏØ| ¿­ÀïÊÐ| ÌÒÔ°ÊÐ| ¼ª°²ÊÐ| °²Î÷ÏØ| ÐÞË®ÏØ| ³¤ÎäÏØ| Âí¹ØÏØ| ºº¹ÁÇø| Õã½­Ê¡| Æ½ÒØÏØ| ÇàÖÝÊÐ| ÇൺÊÐ| ½úÖÝÊÐ| ´ó·½ÏØ| ×Ͳ©ÊÐ| Ñô¸ßÏØ| Î÷ÎÚ| ÇàÉñÏØ| Ôæ×¯ÊÐ| ÃçÀõÏØ| ÁÙãðÏØ| ÅíÑôÏØ| º£ÄÏÊ¡| °¢¶ûɽÊÐ| ºá·åÏØ| ²ÔÏªÏØ| ƽ°²ÏØ| ͼÃÇÊÐ| ÎäÂ¡ÏØ| ÓÀ´¨ÊÐ|