• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            教父的告白
            一切都是紙老虎
            posts - 82,  comments - 7,  trackbacks - 0

            VS2008Sp1+SilverLight3+Blend3

            首先安裝Visual Studio 2008 專業版(只要空間夠,與VS2005共存完全沒有問題),打上 Microsoft Visual Studio 2008 Service Pack 1。安裝Sp1的時候可能花的時間有點久,>=安裝VS2008的時間,考驗耐心的時間到了。。

            要注意的是電腦里有的是VS2008 Beta ,那就麻煩 了,升級到VS2008正式版比想象中的困難,實在不行就只能用第2種組合了。

            下面就開始配置SilverLight了,首先安裝

            Microsoft® Silverlight™ 3 Tools for Visual Studio 2008 SP1

            ,注意語言選擇要與VS2008的對應。

            接著是Silverlight 3 Toolkit July 2009,Xaml的界面設計Microsoft Expression Blend 3 Preview目前只有英文版,所有的都用最新的嘗嘗鮮。。

            VS2010Beta 1+SilverLight2+SilverLight3

            vs2010Beta1是基于WPF的,因此界面與很多新特性比以前看起來是舒服多了,不過性能方面那就嚴重地有待提高,無響應的幾率相對于 VS2008至少增加了20%。安裝過程中會重啟(Framework 4),鏡像只有1288M,但安裝系統盤的大小基本要求還是很高的,曾經試過最小也要2.4G。

            SilverLight2自帶就已經安裝了,但現在還不能創建SL2的項目并且F5調試的時候也會報Debug manage,這時就要安裝依次下面的的就可以OK了

            Microsoft® Silverlight™ 2 軟件開發工具包

            Microsoft® Silverlight™ 3 SDK

            Silverlight.3.0_Developer

            。在裝Silverlight.3.0_Developer安裝的過程中可能會提示已經安裝更新版本,老老實實去卸載吧Silverlight3吧,不然調試功能就沒有機會享用 了。。

            至此為止,以上兩種組合的SilverLight開發環境已經完成了,希望對大家有幫助。下次將發布“使用Silverlight技術,Bing搜索API和遠端WCF/WPF實現Ink手寫搜索框”開發過程與源碼。

            posted @ 2009-10-22 12:25 暗夜教父 閱讀(300) | 評論 (0)編輯 收藏

            apt-get 使用指南

            原文出處:https://help.ubuntu.com/community/AptGetHowto

            原文作者:UbuntuWiki

            授權許可:

            • 創作共享協議Attribution-ShareAlike 2.0
            • GNU自由文檔許可證

            翻譯人員:sigus 5451vs5451 youyou keke initnas

            校正人員:MillenniumDark


            適用版本:

            文章狀態:等待校正


            IconsPage?action=AttachFile&amp;amp;do=get&amp;amp;target=IconApt.png apt-get使用source.list文件進行軟件包管理。如果您想了解關于如何編輯和更新source.list中的條目的信息,請參閱SourcesList

            引言

            “起初GNU/Linux系 統中只有.tar.gz。用戶必須自己編譯他們想使用的每一個程序。在Debian出現之後,人們認為有必要在系統中添加一種機制用來管理安裝在計算機上 的軟件包。人們將這套系統稱為dpkg。至此著名的‘package’首次在GNU/Linux上出現。不久之後紅帽子也開始著手建立自己的包管理系統 ‘rpm’。

            “GNU/Linux的創造 者們很快又陷入了新的窘境。他們希望通過一種快捷、實用而且高效的方式來安裝軟件包。這些軟件包可以自動處理相互之間的依賴關系,并且在升級過程中維護他 們的配置文件。Debian又一次充當了開路先鋒的角色。她首創了APT(Advanced Packaging Tool)。這一工具後來被Conectiva 移植到紅帽子系統中用于對rpm包的管理。在其他一些發行版中我們也能看到她的身影。”

            "同時,apt是一個很完整和先進的軟件包管理程序,使用它可以讓你,又簡單,又準確的找到你要的的軟件包, 并且安裝或卸載都很簡潔。 它還可以讓你的所有軟件都更新到最新狀態,而且也可以用來對ubuntu進行升級。"

            "apt是需要用命令來操作的軟件,不過現在也出現了很多有圖形的軟件,比如Synaptic, Kynaptic 和 Adept。"

             命令

            下面將要介紹的所有命令都需要sudo!使用時請將“packagename”和“string”替換成您想要安裝或者查找的程序。

            apt-get autoclean——定期運行這個命令來清除那些已經卸載的軟件包的.deb文件。通過這種方式,您可以釋放大量的磁盤空間。如果您的需求十分迫切,可以使用apt-get clean以釋放更多空間。這個命令會將已安裝軟件包裹的.deb文件一并刪除。大多數情況下您不會再用到這些.debs文件,因此如果您為磁盤空間不足而感到焦頭爛額,這個辦法也許值得一試。

            典型應用

            我是個賽車發燒友,想裝個賽車類游戲玩玩。有哪些賽車類游戲可供選擇呢?

            apt-cache search racing game

            出來了一大堆結果。看看有沒有更多關于torcs這個游戲的信息。

            apt-cache show torcs

            看上去不錯。這個游戲是不是已經安裝了?最新版本是多少?它屬于哪一類軟件,universe還是main?

            apt-cache policy torcs

            好吧,現在我要來安裝它!

            apt-get install torcs

            在 控制臺下我應該調用什么命令來運行這個游戲呢?在這個例子中,直接用torcs就行了,但并不是每次都這么簡單。我們可一通過查找哪些文件被安裝到了 “/usr/bin”文件夾下來確定二進制文件名。對于游戲軟件,這些二進制文件將被安裝到“/usr/games”下面。對于系統管理工具相應的文件夾 是“/usr/sbin”。

            dpkg -L torcs|grep /usr/games/

            這個命令的前面一部分顯示軟件包“torcs”安裝的所有文件(您自己試試看)。通過命令的第二部分,我們告訴系統只顯示前一部分的輸出結果中含有“/usr/games”的那些行。

            這個游戲很酷哦。說不定還有其他賽道可玩的?

            apt-cache search torcs

            我的磁盤空間不夠用了。我得把apt的緩存空間清空才行。

            apt-get clean

            哦不,老媽叫我把機器上的所有游戲都刪掉。但是我想把配置文件保留下來,這樣待會我只要重裝一下就可以繼續玩了。

            apt-get remove torcs

            如果我想連配置文件一塊刪除:

            apt-get remove --purge torcs

            額外的軟件包

            deborphan和debfoster工具可以找出已經安裝在系統上的不會被用到的軟件包。

             提高命令行方式下的工作效率

            您可以通過定義別名(alias)來提高這些命令的輸入速度。例如,您可以在您的*~/.bashrc*文件中添加下列內容

            alias acs='apt-cache search'
            alias agu='sudo apt-get update'
            alias agg='sudo apt-get upgrade'
            alias agd='sudo apt-get dist-upgrade'
            alias agi='sudo apt-get install'
            alias agr='sudo apt-get remove'

            或者使用前面介紹的aptitude命令,如“alias agi='sudo aptitude install'”。

             apt-get設置http代理

            可以通過三種方法為apt-get設置http代理

            方法一

            這是一種臨時的手段,如果您僅僅是暫時需要通過http代理使用apt-get,您可以使用這種方式。

            在使用apt-get之前,在終端中輸入以下命令(根據您的實際情況替換yourproxyaddress和proxyport)。

            export http_proxy=http://yourproxyaddress:proxyport

            方法二

            這種方法要用到/etc/apt/文件夾下的apt.conf文件。如果您希望apt-get(而不是其他應用程序)一直使用http代理,您可以使用這種方式。

            注意: 某些情況下,系統安裝過程中沒有建立apt配置文件。下面的操作將視情況修改現有的配置文件或者新建配置文件。

            sudo gedit /etc/apt/apt.conf

            在您的apt.conf文件中加入下面這行(根據你的實際情況替換yourproxyaddress和proxyport)。

            Acquire::http::Proxy "http://yourproxyaddress:proxyport";

            保存apt.conf文件。

            方法三

            這種方法會在您的主目錄下的.bashrc文件中添加兩行。如果您希望apt-get和其他應用程序如wget等都使用http代理,您可以使用這種方式。

            gedit ~/.bashrc

            在您的.bashrc文件末尾添加如下內容(根據你的實際情況替換yourproxyaddress和proxyport)。

            http_proxy=http://yourproxyaddress:proxyport
            export http_proxy

            保存文件。關閉當前終端,然後打開另一個終端。

            使用apt-get update或者任何您想用的網絡工具測試代理。我使用firestarter查看活動的網絡連接。

            如果您為了糾正錯誤而再次修改了配置文件,記得關閉終端并重新打開,否自新的設置不會生效。

            posted @ 2009-10-19 10:59 暗夜教父 閱讀(378) | 評論 (0)編輯 收藏

            如果想封掉國內ip或者封掉國外ip,總歸要現有國內的ip段才可以。如果要做dns智能解析,也要有各地各運營商的ip段才行。網上有很多各式各樣的ip表,但很多都過期了,也不全。如果要做一個比較完整的ip數據,還是要靠APNIC才行。
            亞太互聯網絡信息中心(Asia-Pacific Network InformationCenter,簡稱APNIC)坐落于澳大利亞的布里斯班,是全球現有4個地區性互聯網注冊管理機構(RIR)之一,負責向亞太地區64個經濟體提供IP(v4及v6)地址和自治系統(AS)號碼分配,以及反向DNS授權服務的非營利性會員組織。其會員單位包括ISP、國家(或地區)互聯網注冊管理機構(NIR)等互聯網組織。
            如果要找出國內的ip地址段,這個比較簡單
            國家IP段數據下載地址:http://ftp.apnic.net/apnic/dbase/data/country-ipv4.lst
            下載數據后,將國家為cn的ip挑出來自己處理一下就可以。
            如果要找出各地各運營商的ip段

            wget http://ftp.apnic.net/apnic/dbase/tools/ripe-dbase-client-v3.tar.gz
            tar xzvf ripe-dbase-client-v3.tar.gz
            cd whois-3.1
            ./configure
            make
            完成上述編譯安裝工作后,我們開始獲取IP地址段;
            中國網通:
            ./whois3 -h whois.apnic.net -l -i mb MAINT-CNCGROUP > /var/cnc
            中國電信:
            ./whois3 -h whois.apnic.net -l -i mb MAINT-CHINANET > /var/chinanet
            中國鐵通:
            ./whois3 -h whois.apnic.net -l -i mb MAINT-CN-CRTC > /var/crtc

            打開獲取后的文件可以看到里面的信息非常詳細,甚至可以看到各個分公司的負責人、電話、電子郵件等等信息。如果想得到一份整齊干凈的IP地址段文件,只要用grep和awk簡單過濾就可以了

            然后在apache中設置一下權限就可以。


            Order deny,allow
            Deny from 113.0.0.0/13
            ……………………………….
            Deny from 61.240.0.0/14

            posted @ 2009-10-17 00:41 暗夜教父 閱讀(332) | 評論 (0)編輯 收藏

            我用的是lamp集成環境是xampp,linux下是lampp,其實都是一個東西。

            想改變一下自己老土的調試方式,所以試用一下zend debugger和xdebug

            言歸正傳,如何讓三者共存呢。(理論上,你用zend debugger就不必再使用xdebug,反之亦然)

            xampp已經給好了zend optimizer的配置,并且xdebug也已經默認給配置好了,只是都沒有啟用而已

            第一步:啟用zend optimizer

            在php.ini中,找到zend_optimizer.enable_loader,把值高為1即可

            如:

            [Zend]
            zend_extension_ts = “D:\xampp\php\zendOptimizer\lib\ZendExtensionManager.dll”
            zend_extension_manager.optimizer_ts = “D:\xampp\php\zendOptimizer\lib\Optimizer”
            zend_optimizer.enable_loader = 1
            zend_optimizer.optimization_level=15
            zend_optimizer.license_path =
            ; Local Variables:
            ; tab-width: 4
            ; End:

            第二步:加載zend debugger

            這里是一個需要注意的地方

            下載zend debugger: 地址:http://downloads.zend.com/pdt/server-debugger/,下載符合你操作系統的版本, 保存到自定義的目錄,例如d:/xampp/php/zenddebugger

            在該目錄下建立一個相應當前php版本的文件夾, 如當前php版本php5.26, 即在該文件夾下建立php-5.2.x文件夾, 注: 此處X為真實的字符,而不是一個代表符。

            將下載的debugger中相應版本的ZendDebugger.dll考到該目錄下。

            再配置 php.ini,加入

            [Debugger]
            zend_extension_manager.debug_server_ts=”D:\xampp\php\zenddebugger”
            zend_debugger.allow_hosts=127.0.0.1/32,192.168.0.0/44
            zend_debugger.expose_remotely=always

            重啟apache,查看phpinfo,如果看到

            with Zend Extension Manager v1.2.0, Copyright (c) 2003-2007, by Zend Technologies
            with Zend Optimizer v3.3.3, Copyright (c) 1998-2007, by Zend Technologies
            with Zend Debugger v5.2.15, Copyright (c) 1999-2008, by Zend Technologies

            就說明成功了

            第三步:加載xdebug

            我們可以以擴展形式加載xdebug,就避免了和zend optimizer沖突。

            extension=php_xdebug.dll

            注意php_xdebug.dll要在xampp/php/ext目錄下

            然后php.ini中添加的內容 (xampp已經添加好,我們只需要去掉注釋即可)

            [XDebug]
            ;; Only Zend OR (!) XDebug
            ;zend_extension_ts=”D:\xampp\php\ext\php_xdebug.dll”
            xdebug.remote_enable=true
            xdebug.remote_host=127.0.0.1
            xdebug.remote_port=9000
            ;xdebug.remote_handler=dbgp
            ;xdebug.profiler_enable=1
            ;xdebug.profiler_output_dir=”D:\xampp\tmp”

            再重啟apache, OK。 開始測試

            結果是,zend debugger可以和zend optimize共存,但xdebug不能和zend optimize共存

            如果使用dll方式加載xdebug,會有錯誤提示。并且不再執行

            posted @ 2009-10-12 15:43 暗夜教父 閱讀(1268) | 評論 (0)編輯 收藏

            為啥要PATCH?

                Mnesia最大的缺陷是存儲限制。這不是數據庫系統的錯誤,因為Mnesia能夠控制虛擬數據的大小。主要的問題在于過時的Erlang DETS存儲引擎,速度慢并且使用的32位偏移量(限制單文件大小為2GB)。

            思路?

                超乎想象的 mnesia 補丁包 mnesiaex 。這個東西解除了加在 mnesia 數據庫系統上所有的限制(雖說上面已經提到,實際上 mnesia 代碼本身沒有什么真正的限制)——你現在可以用 SleepyCat/BerkeleyDB/MySQL/Amazon S3/Tokyo Cabinet/… 甚至是你自己喜歡的某種東西來當作 mnesia 的后端,就像 ets/dets 一樣。而訪問的接口仍保持不變——繼續沿用 mnesia 的接口,一行也不用改。 DIY 這種擴展也變得相當容易,寫一個 behavior 就成了。

            實現過程

            1:與從源代碼編譯的方式安裝Erlang

            tar xvf otp_src_R12B-5.tar.gz

            cd otp_src_R12B-5

            ./configure & make & make install

            注意:我的系統是RHEL 5.3,默認安裝目錄為/usr/local/erlang

            2:安裝Mnesiaex

            tar xvf mnesia-4.4.7.6.tar.gz

            cd mnesia-4.4.7.6

            ./configure --prefix=/usr/local

            make

            make check

            make install

            注意:這里一定要指定prefix,不然就裝到/usr目錄去了

            3:安裝Tokyo Cabinet

            tar xvf  tokyocabinet-1.4.10.tar.gz

            cd tokyocabinet-1.4.10

            ./configure --prefix=/usr

            make & make install

            3:安裝tcerl

            tar xvf tcerldrv-1.3.1e.tar.gz

            cd tcerldrv-1.3.1e

            ./configure --prefix=/usr

            make & make install

            tar xvf tcerl-1.3.1e.tar.gz

            cd tcerl-1.3.1e

            ./configure --prefix=/usr/local

            make & make install

             

            本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/jimmychou/archive/2009/03/13/3988468.aspx

            posted @ 2009-09-29 15:12 暗夜教父 閱讀(906) | 評論 (0)編輯 收藏

            http://shiningray.cn/some-facts-about-erlang-and-smp.html

            原文:http://groups.google.com/group/erlang-questions/browse_thread/thread/7827f5e32681ca8e

            by.Kenneth Erlang/OTP team, Ericsson
            譯:ShiningRay

             

            以下是一些Erlang SMP實現的細節和與性能與伸縮性相關一些簡單介紹。

            幾周之內還有有一個關于多核如何運作以及未來如何發展的更詳細的介紹。我打算將一些內容放在我的報告中,將于9月27日的ICFP2008,Erlang Workshop在Victoria BC展示給大家。

            沒有SMP支持的Erlang VM只有1個運行在主處理線程中的調度器。該調度器從運行隊列(run-queue)中取出可以運行的Erlang進程以及IO任務,而且因為只有一個線程訪問他們所以無須鎖定任何數據。

            而帶有SMP支持的Erlang VM可以有一個或多個調度器,每個運行在一個線程中。調度器從同一個公共運行隊列中取出可運行的Erlang進程和IO任務。在SMP VM中所有的共享數據結構都會由鎖進行保護,運行隊列就是這樣一個由鎖保護的數據結構。

            從OTP R12B開始,如果操作系統報告有多于1個的CPU(或者核心)VM的SMP版本會自動啟動,并且根據CPU或者核心的數量啟動同樣數量的調度器。

            你可以從“erl”命令打印出來的第一行看到它選擇了哪些參數。例如:

            
            Erlang (BEAM) emulator version 5.6.4 [source] [smp:4] [asynch-threads:0] …..
            其中“[smp:4]”表示SMP VM運行了4個調度器。
            

            默認值可以用“-smp [enable|disable|auto]”來替換,auto是默認的。如果smp被啟用了(-smp enable),要設置調度器的數量可以使用“+S Number”其中Number是調度器的數量(1到1024)

            注意1:運行多于CPU或核心總數的調度器不會有任何提升。

            注意2:在某些操作系統中一個進程可使用的CPU或者核心的數量可以被限制。例如,在Linux中,命令“taskset”就可以實現這個功能。 Erlang VM目前還只能探測CPU或者核心的總數,不會考慮“taskset”所設置的掩碼。正因如此,例如可能會出現(已經出現過了)即使Erlang VM運行了4個調度器,也只使用了2個核心。OS會進行限制因為它要考慮“taskset”所設置的掩碼。

            每個Erlang VM的調度器都運行于一個OS線程上,是OS來決定線程是否執行在不同的核心上。一般來說OS會很好地處理這個問題并且會保證線程在執行期間運行于同一個核心上。

            Erlang進程會被不同的調度器運行,因為他們是從一個公共運行隊列中被取出,由首先可用的調度器運行。

            性能和伸縮性

            只有一個調度器的SMP VM要比非SMP的VM稍微慢那么一點點。SMP VM內部需要用到各種鎖,不過只要不存在鎖的爭用,那么由鎖引起的開銷不會非常大(就是鎖爭用上面需要花時間)。這也解釋了為何在某些情況下,運行多個只有一個調度器的SMP VM要比包含多個調度器的單一SMP VM更加高效。當然運行多個VM要求應用可以按照多個并行任務的方式運行并且之間沒有或者幾乎不通訊。

            一個程序是否能在多核上的SMP VM中良好地進行提升很大程度上取決于程序的性質,某些程序可以保持線性提升至8核甚至16核,同時其他某些程序基本不能提升,連2核都不行。實際應用中很多程序都能在主流市場的核心數上得到提升,見下文。

            若并行的持續“通話”由每個核心一個或多個Erlang進程來表示,實際的支持大量通話的電信產品已經先現出在雙核和四核處理器上不俗的伸縮性。注意,這些產品是在SMP VM和多核處理器出現很久以前按照普通的Erlang風格來寫的,他們也能無須任何修改甚至不需重新編譯代碼就能從Erlang SMP VM中獲益。

            SMP性能得到持續改進

            SMP實現正被不斷改進以便能得到更好的性能和伸縮性。在每個服務發布版R12B-1,2,3,4,5…,R13B等等中,你都能發現新的優化。

            一些已知的瓶頸

            單一的常見運行隊列隨著CPU或核心的數量的增加會成為一個顯著的瓶頸。

            這從4核開始往上就會顯現出來,不過4核仍然可以為多數應用程序提供不錯的性能。我們正在從事一個每個調度器一個運行隊列的解決方法作為目前最重要的改進。

            Ets表格會引入鎖。在R12B-4之前在每次對一個ets-table的訪問中會用到兩個鎖,但是在R12B-4中meta-table的鎖被優化過,可以顯著減少爭用(前面已經提到爭用是有很大代價的)。如果很多Erlang進程訪問同一個表格,就會有很多鎖爭用造成性能降低尤其當這些進程主要工作是訪問ets-table。鎖存在于表級而非記錄級。注意!這也會影響到Mnesia因為Mnesia用到了很多ets-table。

            我們關于SMP的策略

            當我們開始實現SMP VM的最初,我們就確定了策略:“首先讓它可以運行,然后測量,然后優化”。自從2006年五月我們發布了第一個穩定的SMP VM(R11B)以來,我們一直遵循著這個策略。

            還有更多已知的東西可以改進,我們會按照性能的收益大小先后各個擊破。

            我們將主要的精力放在多核(大于4)上更好的連續伸縮性上。

            卓越典范

            即使SMP系統有還有一些已知的瓶頸不過已經有不錯的整體性能和伸縮性,同時我相信在讓程序員利用多核機器事半功倍方面,我們是一個卓越的典范。

            posted @ 2009-09-24 22:23 暗夜教父 閱讀(588) | 評論 (0)編輯 收藏
            以下是在erlang項目開發中的一些記錄,即包含很多通俗易懂的原則,也包含一些似是而非的建議,比較混亂,還沒有積累到一個可以分門別類的地步,各位就將就看吧..
            :)

            * 確保沒有任何編譯警告

            * Erlang中String采用list實現,32位系統中,其1個字符用8個字節的空間(4個保存value, 4個保存指針)。因此string速度較慢,空間占用較大

            * 在Server中,總是盡力書寫尾遞歸(tail-recursive)的函數

            * 使用'++'時,left list會被拷貝,然后添加到right list的頭部,因此最好把length較短的list放在左側

            * 避免使用regexp,如果需要正則表達式,請使用re

            * timer模塊的大部分函數實現,依賴于一個process,如果過多使用timer,會導致這個process負載過大,影響效率。
              推薦使用erlang:send_after/3及erlang:start_timer/3

            * 避免使用list_to_atom/1,因為erlang中atom數量最大為1048576, 且不進行GC控制。因此如果持續性的調用list_to_atom/1
              可能很容易達到系統上限,從而導致emulator terminate。請使用list_to_existing_atom/1。

            * list內部實現為一個列表,因此length(List), 需要遍歷整個list比較耗時

            * 對于不同的數據類型,使用不同的size函數:tuple_size/1, byte_size/1, bit_size/1

            * 使用binary match來進行binary的分割,而不使用split_binary/2

            * 如果兩個list都擁有很多數據,那么請不要使用'--',而是將數據轉化到ordsets,然后調用ordsets:substract/2.

            * 對于binary相關操作可以進行binary優化(bin_opt_info編譯選項)代碼框架:

            *   f(<<Pattern1,...,Rest/bits>>,...) -> 
                   ... % Rest is not used here 
                   f(Rest,...); 
                f(<<Pattern2,...,Rest/bits>>,...) -> 
                  ... % Rest is not used here 
                  f(Rest,...); 
                ... 
                f(<<>>, ...) -> 
                  ReturnValue.

            * 調用lists:flatten/1可以將list扁平化,這個操作代價很大,比'++'還要昂貴。下面這些時候我們可以避免:
                將數據發送給port時
                調用list_bo_binary/1和iolist_to_binary前

            * 小的函數可以讓您方便的找出錯誤的函數和代碼

            * 不要在同一行出現相同的符號
            20    some_fun() ->
            21       L = [{key1, v1}, {key2, [some_record#v21, v22]}],
            22      ...
            編譯時,會提示line 21 '[' 語法錯誤, 因為21行有多個 '[' ,所以這個bug不能準確定位,你需要花時間去排查代碼。
            好的做法是:
            20 some_fun() ->
            21      L = [{key1, v1},
            22            {key2, [some_record#v21, v22]}
            23            ],
                  ...
            這樣,編譯其會提示你 line 22 '[' 語法錯誤,你很開就知道是那個地方錯了。

            * 使用 CTRL + \ 或 init:stop(), 可以退出Erlang, 使用CTRL + G 及 CTRL + C 彈出菜單選項,可以選擇是否退出Erlang
            其中CTRL + G可以用來連接其他的shell, CTRL + C可以查看其他一些系統信息
            Ctrl + C abort 是野蠻的退出方式

            * use "open_port({fd,0,2}, [out])" make erlang program write standard error to unix system

            * If you don't run experiments before you start designing a new system, your entire system will be an experiment!

            * standard data structure desc:

            Module Description
            sets sets, i.e. a collection of unique elements.
            gb_sets sets, but based on a general balanced data structure
            gb_tree a general balanced tree
            dict maps, also called associative arrays
            ets hash tables and ordered sets (trees)
            dets on-disk hash tables

            Suggestion:
            elments count: 0 - 100 | 100 - 10000  |  10000 -
            our select   :  list   |      ets     |  gb_tree

            * 通過code:clash/0 檢測代碼中是否有module沖突現象(sticky)

            * epmd -d -d 啟動 epmd 可以查看erlang node之間的通訊

            * 將正常的邏輯代碼和錯誤處理代碼分離,發生錯誤時,盡管錯誤。由另一個錯誤處理模塊進行處理

            * 類似于操作系統,我們的程序也可以分為kernel 和 user 兩層, 對于kernel絕對不能出現錯誤, 對于user可以出現錯誤,進行恢復

            * process頂層loop涉及的代碼及函數,最好在一個module中實現

            * process 的register name和module名稱一致, 便于尋找代碼

            * 每個process具有一個單一的角色,比如:supervisor 用來進行錯誤恢復, work 工作者,可以出現錯誤, trusted worker 不會出現錯誤

            * 通過函數調用可以實現的功能,就不要使用sever實現(如gen_server, 及類似的loop 實現)

            * 給消息加一個tag,在發生錯誤的時候,可以定位到消息,同時也有利于程序的穩健

            * 在消息循環中,對于unknown的消息,請調用lib:flush_receive/0 將其清除,減輕process msg queue的長度

            * server中總是書寫尾遞歸的循環

            * 盡量使用record, 而不是原始的tuple來表現數據結構, 在使用record時,使用select match:
            #person{name = Name, age = Age} = Person

            * 對于返回值,最好也添加一個tag,用來說明返回值類型,或者執行成功與否

            * 盡可能少的使用catch和try,在erlang程序中,不推薦主動捕獲異常。只有當我們的邏輯特別復雜,我們可以使用throw來返回數據,使用catch來獲取返回值。

            * 當然程序與外界交互,外界數據不可靠時,需要使用catch和try

            * 慎重使用process dictory, 當你使用get/1, put/1時,你的應用會具有很大的slide effect。可以通過加入一個新的參數來保存原本需要存儲到process dictory中數據

            * 如果不想使自己糊涂,請不要使用import

            * 使用export時,將功能類似的接口組合在一起,并添加合理的注視,這樣你的接口更清晰,別人使用起來更方便

            * 不要書寫嵌套太深的代碼

            * 不要書寫太長的module

            * 不要書寫太長的函數

            * 每行代碼不能太長

            * 避免使用 "_" 匿名變量,請為每個變量選擇有意義的名稱,如夠某個變量暫時不使用,請以下劃線 "_" 開始

            * {error, enfile} enfile error in socket 是以為內linux系統中 ulimit 限制, 在root下修改:ulimit -n 25000

            * {error, enotconn} 表示socket已經關閉

            * 在erlang開發時,慎重使用macro,因為erlang的single assign的緣故,同時調用某個marco,而macro又定義了某個變量,可能導致badmatch錯誤。
            比如:
            -define(ADDLINEINFO1(F),
                    (
                    begin
                    Str1 = lists:concat(["[Mod:", ?MODULE, " Line:", ?LINE, "]"]),
                    Str1 ++ F
                    end
                    )).
            -define(WARN(Log, F, D), log4erl:warn(Log, ?ADDLINEINFO(F), D)).
            如果連續使用 WARN, 會出現此錯誤

            * erlang中可以定義很多環境變量:
            ERL_MAX_ETS_TABLES 設置最大的ets數目 默認1400
            ERL_MAX_PORTS erlang最大的port數目 默認1024

            * .app文件中的start_phases, 選項既可以用來作為include applications之間的同步啟動,也可以用來對單個application進行分布啟動。
            順序如下
            包含included app:

            application:start(prim_app)
            => prim_app_cb:start(normal, [])
            => prim_app_cb:start_phase(init, normal, [])
            => prim_app_cb:start_phase(go, normal, [])
            => incl_app_cb:start_phase(go, normal, [])
            ok

            無included app:
            application:start(prim_app)
            => prim_app_cb:start(normal, [])
            => prim_app_cb:start_phase(init, normal, [])
            => prim_app_cb:start_phase(go, normal, [])
            ok

            * 任何時候,都要重視函數的返回值,通過match確保您的預期,如果發生錯誤,那么就大膽的表達出來。
            posted @ 2009-09-24 01:00 暗夜教父 閱讀(610) | 評論 (0)編輯 收藏
            A Million-user Comet Application with Mochiweb, Part 1
            在MacOSX平臺上遇到的一些問題:

            一. IPv6導致的問題
            在MacOS下測試時報錯econnrefused,mochi-urls.txt文件的url不能用localhost,得用127.0.0.1才行

            在Erlang的郵件列表中找到了解釋:
            We have seen the same issue with CouchDB. What we found out
            is that in our case localhost was not only resolving to 127.0.0.1 (IPv4)
            but also ::1 (IPv6) and that http:request() would try to connect to
            ::1 where no service was listening.

            Erlang的http模塊缺省是打開IPv6模式的,當測試程序通過http模塊連接localhost時,連接的地址是IPv6的::1地址,但是mochi沒有在此監聽,所以連接出錯 {error,econnrefused}

            解決方法兩種:
            1. 將mochi-urls.txt中的地址都改成127.0.0.1
            2. 在http:request(…)運行之前調用http:set_options([{ipv6,disabled}]),關閉測試程序的IPv6模式,使用IPv4模式

            理論上還有一種方法:讓mochi服務器開啟IPv6模式監聽,這個我不知道這么開,
            參考
            You should teach Yaws to listen also on IPv6 - “localhost” resolves not
            only to IPv4 127.0.0.1, but also to IPv6 ::1.


            二. 進程能打開的文件描述符數量的限制
            MacOSX下缺省能同時打開的文件描述符最大數是256個,使用 ulimit -a命令查看
            $ ulimit -a
            core file size          (blocks, -c) 0
            data seg size           (kbytes, -d) 6144
            file size               (blocks, -f) unlimited
            max locked memory       (kbytes, -l) unlimited
            max memory size         (kbytes, -m) unlimited
            open files                      (-n) 256
            pipe size            (512 bytes, -p) 1
            stack size              (kbytes, -s) 8192
            cpu time               (seconds, -t) unlimited
            max user processes              (-u) 266
            virtual memory          (kbytes, -v) unlimited
            使用ulimit -n XXXX設置,但最大數量還是不能超過10240

            查看內核每進程最大文件數:
            $ sysctl kern.maxfiles kern.maxfilesperproc
            kern.maxfiles: 12288
            kern.maxfilesperproc: 10240

            增大每進程最大文件數:
            $ sudo sysctl -w kern.maxfilesperproc=20480 kern.maxfiles=22528

            然后設置
            $ ulimit -n 20480
            注意ulimit只在每個shell窗口生命周期內有效,當新開一個shell后,得再次設置
            sysctl做的修改沒有這個問題

            三、調節IP端口號范圍,不然最多只能有15K個連接
            缺省動態端口號從49152開始,改成2000后最多可以有63K個連接
            sysctl -w net.inet.ip.portrange.hifirst=2000 net.inet.ip.portrange.first=2000
            posted @ 2009-09-24 00:59 暗夜教父 閱讀(421) | 評論 (0)編輯 收藏

            本文作者:sodme
            本文出處:http://blog.csdn.net/sodme
            聲明:本文可以不經作者同意任意轉載,但任何對本文的引用都須注明作者、出處及此聲明信息。謝謝!!

              特別聲明:
              本人非常欣賞暴雪及他們的游戲,之所以寫這個文章,是想讓大家了解一些網絡封包分析方面的常見方法以及學習暴雪游戲在網 絡處理方面的經驗,偶認為作為一個網絡編程者,熟練掌握封包分析的工具和方法應該是其基本功之一。本文所列的所有封包分析內容,全部是采用普通黑箱方式即 可得來的,并未涉及對魔獸世界可執行程序的逆向工程。同時,除此文涉及的內容外,本人拒絕向任何人透露更詳細的關于魔獸世界封包方面的更多內容,有興趣者 請自己進行相關的試驗,本人在此文中也將盡量避免公開敏感的封包內容及相關加解密算法。謹以此文獻給忠愛的暴雪!

              一、登錄模塊流程及封包分析

              我們先看登錄流程。從封包流程來看,魔獸的登錄流程是這樣的:

              1.由 Client向登錄/賬號服務器(Login Server)發送用戶名及密碼等信息。此數據包的最后部分是用戶名(明文表示,未加密),在用戶名的前一個字節表示的是用戶名的長度。登錄/賬號服務器 向Client返回登錄成功及后續連接到游戲服務器服務器所必備的信息等。這中間的兩個來往數據包,我還沒有看出具體有什么作用。在這個交互過程中,由登 錄/賬號服務器向Client發送所有的游戲服務器列表,服務器列表數據包的內容包括:ip, port, 服務器上所擁有的角色個數等信息,因服務器列表內容過多,被客戶端分為兩次接收完畢。

              2.Client收到Login Server的服務器列表后,根據最近訪問的服務器標識(這個信息應該是包含在那個服務器列表數據包中),連接到最近游戲的那個游戲服務器(Game Server)。連接成功后,Game Server首先向Client發送一個8字節的數據包,據以往的常識判斷,這個數據包的內容很可能是以后客戶端與服務器通信的加密密鑰。

            3.Client向Game Server再次發送自己的賬號信息。Game Server與Client經過兩個數據包的交互后,向Client發送角色數據包,此包中包括了玩家在該Game Server所創建的所有角色信息,當然這個信息只是部分的,并不是該角色的所有信息。

              4.在此后的通信過程中,Client每隔30秒向Game Server發送一個保持連接的包,該包長度為10字節,包的最后四字節是一個遞增數字,前面6字節暫時未看出規律。

            5.只要Client沒有點擊某個角色進入最終的Game Server,則Client要始終與Login Server保持連接。當Client點擊角色進入Game Server時,Client才與Login Server斷開連接。在以后的游戲過程中,Client始終與且僅與該Game Server進行數據通信。

              通過對登錄流程中的數據包初步分析,可以得出以下幾個結論:
              1.Client向Login Server發的第一個數據包,用戶名部分是采用明文的,且該數據包的內容,每次登錄都一樣,并沒有因時間的不同而發生改變。由此可以推算:針對于此數據 包中的密碼加密算法是固定不變的,換句話說,密碼的加密算法是比較容易通過逆向工程被找到的。偶認為,針對于此處,服務器也應該先向客戶端發送一個加密密 鑰,以后的通信可以用該密鑰作為安全驗證的依據。但暴雪沒有這樣作,最大的可能是為了提高服務器的效率,在登錄服務器上,如果每個客戶端一旦連接成功,登 錄服務器都得向客戶端廣播一個數據包的話,可能這個量還是比較大的,這可能延長了玩家的登錄等待時間,所以他們沒有在這塊作。

            2.Client在登錄Login Server的地址,每次Login Server的登錄地址都可能是不一樣的。偶沒有在客戶端目錄里找到這些地址,只在客戶端目錄里找到了四個大區的四個域名,我猜想,魔獸世界是用的DNS 解析的簡單方法來實現Login Server的簡單動態均衡的。不知道這個猜想是否正確。

              3.“根據玩家最近在玩的哪個游戲,由客戶端和服務器自動為玩家選擇進入這個游戲服務器”,這一項設定充分體現了暴雪一貫的風格:為玩家著想,最大限度地提高游戲的舒適度。再次對暴雪的態度予以肯定!

              4.一旦玩家進入了游戲世界,客戶端與服務器的通信端口會一直保持不變。即:魔獸世界的游戲世界服務器群設計結構采用的是帶網關的服務器集群。

            5.偶覺得在整個的登錄流程中,讓我產生最大疑問的就是Login Server與Client的連接保持邏輯。當Client與Game Server連接了之后,Client并未與Login Server斷開,是一直保持連接的。后來,經進一步的抓包分析,Client之所以要與Login Server保持這樣的連接,是為了當Client重新選擇服務器時,不至于重新連接Login Server。當Client點擊了"選擇服務器"按紐后,Login Server會每隔5秒向Client發一個當前所有的服務器列表數據包。要知道,這個服務器列表數據包的內容可是非常大的,如果有玩家就打開了這個窗口 不關閉,Login Server向這種情況的所有玩家每5秒鐘就發一個服務器列表數據包,這個廣播量可是很大的哦(2k左右,這可是一個用戶是2k哦)。偶認為這里的邏輯設 計是相當不合理的。Login Server如果為了給客戶端提供一個最新的全局服務器列表,可以保持連接,但也沒必要每隔5秒就向客戶端發一個服務器列表,最多只在客戶端在某個服務器 上創建了不同的角色后再更新這個列表也是可以的,但只用更新這個列表中的變化內容即可,不用發全部的完整包,這樣,在通信量上就小了很多。據說,魔獸剛開 始的時候,產生DOWN機的原因就是登錄模塊沒有處理好,偶不知道現在的這個情況是不是已經經過改良的了。但偶還是認為每隔5秒就向客戶端發送一個2K的 包,這一點是不可以被接受的。

              以上只是針對于魔獸世界登錄流程的簡單分析,沒有多少技術含量,拿出來跟大家相互討論討論,看看有沒有可以借鑒的地方,后面還會有其它部分的封包分析。歡迎繼續關注偶的Blog: http://blog.csdn.net/sodme

              偶在文章前面部分說過,作為一個網絡編程人員,熟練使用截包軟件和掌握基本的封包分析方法是其基本能力之一,發此文的目的一個原因也是希望向正在作網絡編程的兄弟介紹一下相關工具的使用和常見的分析方法。下面補充一下關于封包分析的基本方法和相關工具:

              1.你需要一個截包工具,偶推薦:commview,小巧但功能強大,支持自定義的封包分析插件以DLL形式裝載,也就是說只要你愿意,你可以寫個DLL對某類特殊形式的包進行顯示、記錄、解密等特別處理。

            2.如何查看真正的封包數據。在commview里,會詳細列出自網卡級別以上的各層封包數據,包括Ethernet層,IP層和TCP層。而我們作封 包分析時,只需要關注TCP層。但TCP層里也有很多內容,對于我們的分析需求來說,我們需要關注的是其Data字段(在協議目錄里可以看到"data length標識,點擊即可查看data段")的內容。

              3.TCP的幾個狀態對于我們分析所起的作用。在TCP層,有個FLAGS字 段,這個字段有以下幾個標識:SYN, FIN, ACK, PSH, RST, URG.其中,對于我們日常的分析有用的就是前面的五個字段。它們的含義是:SYN表示建立連接,FIN表示關閉連接,ACK表示響應,PSH表示有 DATA數據傳輸,RST表示連接重置。其中,ACK是可能與SYN,FIN等同時使用的,比如SYN和ACK可能同時為1,它表示的就是建立連接之后的 響應,如果只是單個的一個SYN,它表示的只是建立連接。TCP的幾次握手就是通過這樣的ACK表現出來的。但SYN與FIN是不會同時為1的,因為前者 表示的是建立連接,而后者表示的是斷開連接。RST一般是在FIN之后才會出現為1的情況,表示的是連接重置。一般地,當出現FIN包或RST包時,我們 便認為客戶端與服務器端斷開了連接;而當出現SYN和SYN+ACK包時,我們認為客戶端與服務器建立了一個連接。PSH為1的情況,一般只出現在 DATA內容不為0的包中,也就是說PSH為1表示的是有真正的TCP數據包內容被傳遞。TCP的連接建立和連接關閉,都是通過請求-響應的模式完成的。


              封包分析的手段,說簡單也挺簡單的,那就是:比較!要不斷地從不同的思維角度對封包進行對比分析,要充分發揮你的想象力不斷地截取自己需要的包進行比較。不僅要作橫向(同類)的比較,還要作縱向(不同類)的比較。即時對于同一個包,也要不斷地反復研究。

              初涉封包分析的新手,一般會不知道封包分析究竟該從何入手。基于經驗,本文將告訴你一般會從哪些類型的包入手進行分析以及應該怎樣對封包進行初 步的分析。需要指出的是:封包分析是一件非常有趣但同時也非常考驗耐心的事,通常,半天的封包分析下來,會讓你眼前全是諸如“B0 EF 58 02 10 72....”之類的網絡數據,而且附帶有頭疼、頭暈癥狀,所以,沒有充分的心理準備,還請不要輕易嘗試。呵呵。

              從事封包分析的基本前提是:應該了解和熟悉TCP協議,并知道數據包“粘合”是怎么一回事。當然,我們平常截獲到的包,從數量上來看,只有一小 部分是屬于“粘合”的情況。但如果不了解它,將可能會對你的分析思路產生誤導和困惑。關于“粘包”的更詳細解釋,請參考我的另外一篇文章“拼包函數及網絡 封包的異常處理(含代碼) (http://blog.csdn.net/sodme/archive/2005/07/10/419233.aspx)”。

              上一篇有關魔獸世界封包分析的文章(http://blog.csdn.net/sodme/archive/2005/06/18/397371.aspx)中,我根據客戶端與服務器端連接及斷開事件的處理流程以及登錄過程中的一些數據包分析了魔獸的架構和登錄邏輯。這篇文章中,我將結合聊天數據包的分析,來闡述魔獸世界封包的大體結構。  

              首先解釋一下我們的目標:封包的大體結構。封包的大體結構包含哪些內容呢?一般情況下,封包的大體結構至少包括兩方面的信息:
              1、一個封包是如何表示它的長度的?封包長度是由哪個字段表示的?(或者說:如何表示封包的開始和結束的)
              2、各種不同的封包類型是通過哪個字段表示的?

              是不是所有游戲的封包都必然會有表示“長度”信息的“字段”呢?答案是否定的。有的游戲確實沒有采用這種方式,它們的作法設定特殊的包開始和包 結束標志。但是,從應用的角度來看,偶推薦使用“長度”這樣的方法,因為不管在網絡底層的處理效率以及上層應用的處理便捷性來說,使用“長度”字段標識一 個完整的邏輯包都是比較好的辦法。在確定了封包的大體結構后,我們才方便分析具體類型包(比如聊天、行走等)的詳細結構。

              作數據包分析,在單純采用黑箱分析的階段,我們選取的數據包,須要是具有這種性質的,即:在數據包發送前客戶端未進行加密等處理時,這個數據包 中的部分內容,我們是已經知道的。這樣的包,就可以作為封包分析的突破口。這樣看來,我們拿“聊天封包”作為第一個分析對象也就不難理解了,因為我們說的 話,打上去的字,我們自己是知道的,但是我們說的話經過客戶端的處理后,發到網絡上的可能就是已經加了密的或者加了校驗碼的。站在黑箱分析的角度,我們能 作的,就是不斷截取各種“聊天包”進行對比、判斷和總結。

              OK,打開你的commview。讓我們從“聊天封包”開始。

              分析“聊天包”的前提,是我們能夠正常判斷哪種類型的數據包是屬于聊天的,不要誤把行走或其它的數據包當作了聊天數據包。為了減小分析難度,建 議新手到游戲中人少或周圍沒有玩家的地方進行封包分析。這樣一來沒人打擾,二來你的網絡通信量會相對小得多,比較容易進行一些封包判定。

              第一步,我們需要確定客戶端與服務器通信所用的端口,然后在commview的rules->ports中設定服務器端口,截獲與該端口 通信的所有數據包。服務器端口的確定方法:不要使用其它網絡通信工具,打開commview,進游戲,截包,觀察其通信端口。進行封包分析時,特別是初期 的封包分析時,你的網絡通信應該盡可能是單一的,即:除了游戲,其它的通信軟件盡可能不要開。但當你確定了服務器的IP和端口后,就可以照常使用其它網絡 軟件了。

              第二步,如前面述,在游戲中找個人少或沒人的地方,開始“自言自語”,呵呵。說話的內容,建議以字母和數字為宜,不要說中文。因為中文是雙字節 的,而字母和數字是單字節的,對于單字節的信息內容,截包軟件會以單字節的文本信息顯示,但對于雙字節的漢字而言,截包軟件在對其進行顯示時由于換行等原 因會造成部分中文顯示有亂碼,不容易直接看出中文內容。如果執意要說中文,偶也不攔你,給你推薦一個工具:String Demander(下載地址:http://www.cnxhacker.com/Download/show/395.html),這個軟件,可以查詢中文所對應的編碼。

              第三步,設定好commview的rules并使之生效,開始截包。

              觀察通過以上的過程所截的包,可以發現,魔獸世界的聊天封包的說話內容是明文的!這一點,用不著大驚小怪,呵呵。聊天封包本身并不會對游戲的關 鍵邏輯造成損害,所以,即使讓其明文顯示也不足為奇。但是,我們還是不太相信自己的眼睛,于是再截若干個包,發現包中的說話內容確實是明文的!但是,包的 其它字段卻是我們一時看不懂的“密文”。

              看來,下面的事情就是對這些包里的“密文”進行研究了。一般情況下,這種“密文”的加密方法,通過封包分析是分析不出來的,但,我們仍然可以通過封包分析來推論一些與“密文”生成算法有關的問題。我們可以作以下的對比分析:
              1、連續三次輸入“a”,并分別觀察及保存封包數據;
              2、連續三次輸入“aa”,并分別觀察及保存封包數據;
              3、連續三次輸入“aaa”,并分別觀察及保存封包數據。

              輸入的封包用例,我們選擇了字母"a",它的ASCII碼是61。輸入的規律是:每種情況連續輸入三次,然后逐次增加a字母的個數。于是,我們發現這樣一個有趣的現象:
              1、包中有關說話的內容是明文的;
              2、即使針對于同樣的說話內容,比如“a”,客戶端所發出去的包也是不一樣的;
              3、當一次說話的字母個數增加1時,封包的總體長度也隨之增加1;
              4、除每個封包的前面6個字節以及說話的字節外,其余的封包內容每次都一樣;
              5、每個聊天封包的結尾字節都是0。

              于是,我們可以試著得出如下結論:
              1、包是沒有壓縮的,它所使用的加密算法應該是按字節進行的,并沒有改變封包的長度使之看上去使用統一的長度;
              2、包是以0結尾的(盡管我們不知道它是以什么表示開頭的,呵呵);
            3、封包加密算法中所使用的密鑰是可變的,即針對于相同的數據包內容由于加密的密鑰不同,所以產生的密文也不同。由于客戶端的數據傳到服務器端后,服務 器端還要對數據進行解密。所以,客戶端的加密算法與服務器端的解密算法應該共用了前6字節中的某些內容,以此作為解密算法的密鑰。如果這6字節中沒有包含 有關封包加、解密所需要的同步數據,那客戶端和服務器之間應該會通過其它的方式同步這樣的數據。不過,偶傾向于前者,即:這6字節中應該含有加、解密所需 要的密鑰信息。

              回頭看我們上面觀察到的有趣現象,針對于第2點,反過來想,這應該也是最起碼的功能了。就是說,即使客戶端作出的是同樣的動作,在客戶端發出的包中,包的內容也是不一樣的。這樣,外掛就不能靠單純的重復發相同的包而達到其目的了。

              分析來分析去,我們還是沒能確定魔獸封包的大體結構。其實,到現在,我覺得我此文的目的已經達到了,即向大家展示封包分析的思維角度和思維方 式。至于具體結果,偶覺得倒真的不重要的了。可以肯定地告訴大家的是,魔獸的封包結構偶大致已經掌握了。偶僅在此公布我的分析結果:
              1、魔獸的封包長度字段是每個封包的前兩字節,它的表示方式是:前兩字節的數值+2。之所以加這個2,是因為封包長度字段本身占用了兩個字節的長度。
              2、魔獸的封包類型偶推斷是第三和第四字節,其中普通聊天的類型標識是“95 00”。

              請不要來信向我詢問任何有關魔獸封包破解的內容,偶能說的都已經在文章里說了,偶之所以寫這個系列的文章不是想破解魔獸,而是想以這樣優秀的一 款游戲作為案例來向大家展示它在封包設計方面值得我們學習和討論的地方,同時向更多的朋友普及有關封包分析的常識、工具以及思維方式,僅此而已。

              ps:由于每次封包分析的內容都很多,所以,一有了點結論后,要及時記錄和總結,并與之前取得的總結進行對比,及時更新相關的記錄文檔。

            posted @ 2009-09-23 23:48 暗夜教父 閱讀(825) | 評論 (0)編輯 收藏
            本文作者:sodme
            本文出處:http://blog.csdn.net/sodme
            聲明:本文可以不經作者同意任意轉載,但任何對本文的引用都須注明作者、出處及此聲明信息。謝謝!!

              在網絡應用中,“負載均衡”已經不能算是什么新鮮話題了,從硬件到軟件,也都有了很多的方法來實現負載均衡。我們這里討論的負載均衡,并不是指依靠DNS轉向或其它硬件設備等所作的負載均衡,而是指在應用層所作的負載均衡。

              一般而言,只有在大型在線系統當中才有必要引入負載均衡,那么,多大的系統才能被稱為大型系統呢?比如動輒同時在線數十萬的網絡游戲,比如同時在線數在10萬以上的WEB應用,這些我們都可以理解為大型系統,這本身就是一個寬泛的概念。

            設計再好的服務器程序,其單個程序所能承載的同時訪問量也是有限的,面對一個龐大且日益增長的網絡用戶群,如何讓我們的架構能適應未來海量用戶訪問,這 自然就牽涉到了負載均衡問題。支持百萬級以上的大型在線系統,它的架構核心就是如何將“百萬”這么大的一個同時在線量分攤到每個單獨的服務器程序上去。真 正的邏輯處理應該是在這最終的底層的服務器程序(如QQ游戲平臺的游戲房間服務器)上的,而在此之前所存在的那些服務器,都可以被稱為“引路者”,它們的 作用就是將客戶端一步步引導到這最終的負責真正邏輯的底層服務器上去,我們計算“百萬級在線”所需要的服務器數量,也是首先考慮這底層的邏輯服務器單個可 承載的客戶端連接量。

              比如:按上篇我們所分析QQ游戲架構而言,假設每個服務器程序最高支持2W的用戶在線(假設一臺機子只運行一個 服務器程序),那么實現150萬的在線量至少需要多少臺服務器呢?如果算得簡單一點的話,就應該是:150/2=75臺。當然,這樣算起來,可能并不能代 表真正的服務器數量,因為除了這底層的服務器外,還要包括登錄/賬號服務器以及大廳服務器。但是,由于登錄/賬號服務器和大廳服務器,它們與客戶端的連接 都屬于短連接(即:取得所需要信息后,客戶端與服務器即斷開連接),所以,客戶端給這兩類服務器帶來的壓力相比于長連接(即:客戶端與服務器始終保持連 接)而言就要輕得多,它們的壓力主要在處理瞬間的并發訪問上。

              “短連接”,是實現應用層負載均衡的基本手段!!!如果客戶端要始終與登錄/賬號服務器以及大廳服務器保持連接,那么這樣作的分層架構將是無意義的,這也沒有辦法從根本上解決用戶量不斷增長與服務器數量有限之間的矛盾。

            當然,短連接之所以可以被使用并能維護正常的游戲邏輯,是因為在玩家看不到的地方,服務器與服務器之間進行了大量的數據同步操作。如果一個玩家沒有登錄 到登錄服務器上去而是直接連接進了游戲房間服務器并試圖進行游戲,那么,由于游戲房間服務器與大廳服務器和登錄/賬號服務器之間都會有針對于玩家登錄的邏 輯維護,游戲房間服務器會檢測出來該玩家之前并沒有到登錄服務器進行必要的賬號驗證工作,它便會將玩家踢下線。由此看來,各服務器之間的數據同步,又是實 現負載均衡的又一必要條件了。

              服務器之間的數據同步問題,依據應用的不同,也會呈現不同的實現方案。比如,我們在處理玩家登錄這個問 題上。我們首先可以向玩家開放一些默認的登錄服務器(服務器的IP及PORT信息),當玩家連接到當前的登錄服務器后,由該服務器首先判斷自己同時連接的 玩家是不是超過了自定義的上限,如果是,由向與該服務器連接著的“登錄服務器管理者”(一般是一個內部的服務器,不直接向玩家開放)申請仲裁,由“登錄服 務器管理者”根據當前各登錄服務器的負載情況選擇一個新的服務器IP和PORT信息傳給客戶端,客戶端收到這個IP和PORT信息之后重定向連接到這個新 的登錄服務器上去,完成后續的登錄驗證過程。

              這種方案的一個特點是,在面向玩家的一側,會提供一個外部訪問接口,而在服務器集群的內部,會提供一個“服務器管理者”及時記錄各登錄服務器的負載情況以便客戶端需要重定向時根據策略選擇一個新的登錄接口給客戶端。

            采用分布式結構的好處是可以有效分攤整個系統的壓力,但是,不足點就是對于全局信息的索引將會變得比較困難,因為每個單獨的底層邏輯服務器上都只是存放 了自己這一個服務器上的用戶數據,它沒有辦法查找到其它服務器上的用戶數據。解決這個問題,簡單一點的作法,就是在集群內部,由一個中介者,提供一個全局 的玩家列表。這個全局列表,根據需要,可以直接放在“服務器管理者”上,也可以存放在數據庫中。

              對于邏輯相對獨立的應用,全局列表的 使用機會其實并不多,最主要的作用就是用來檢測玩家是不是重復登錄了。但如果有其它的某些應用,要使用這樣的全局列表,就會使數據同步顯得比較復雜。比 如,我們在超大無縫地圖的MMORPG里,如果允許跨服操作(如跨服戰斗、跨服交易等)的話,這時的數據同步將會變得異常復雜,也容易使處理邏輯出現不可 預測性。

              我認為,對于休閑平臺而言,QQ游戲的架構已經是比較合理的,也可以稱之為休閑平臺的標準架構了。那么,MMORPG一般的架構是什么樣的呢?

            MMORPG一般是把整個游戲分成若干個游戲世界組,每個組內其實就是一個單獨的游戲世界。而不同的組之間,其數據皆是相互獨立的,并不象QQ休閑平臺 一樣所有的用戶都會有一個集中的數據存放點,MMORPG的游戲數據是按服務器組的不同而各自存放的。玩家在登錄QQ游戲時,QQ游戲相關的服務器會自動 為玩家的登錄進行負載均衡,選擇相對不忙的服務器為其執行用戶驗證并最終讓用戶選擇進入哪一個游戲房間。但是,玩家在登錄MMORPG時,卻沒有這樣的自 動負載均衡,一般是由玩家人為地去選擇要進入哪一個服務器組,之所以這樣,是因為各服務器組之間的數據是不相通的。其實,細致想來,MMORPG的服務器 架構思想與休閑平臺的架構思想有異曲同工之妙,MMORPG的思想是:可以為玩家無限地開獨立的游戲世界(即服務器組),以滿足大型玩家在線;而休閑平臺 的思想則是:可以為玩家無限地開游戲房間以滿足大量玩家在線。這兩種應用,可以無限開的都是“具有完整游戲性的游戲世界”,對于MMORPG而言,它的一 個完整的游戲地圖就是一個整體的“游戲世界”,而對于休閑平臺,它的一個游戲房間就可以描述為一個“游戲世界”。如果MMORPG作成了休閑平臺那樣的全 服皆通,也不是不可以,但隨之而來的,就是要解決眾多跨服問題,比如:好友、組隊、幫派等等的問題,所有在傳統MMORPG里所定義的這些玩家組織形式的 規則可能都會因為“全服皆通”而改變。

              架構的選擇是多樣性的,確實沒有一種可以稱得上是最好的所謂的架構,適合于當前項目的,不一定就適合于另一個項目。針對于特定的應用,會靈活選用不同的架構。但有一點,是可以說的:不管你如何架構,你所要作的就是--要以盡可能簡單的方案實現盡可能的穩定、高效!
            posted @ 2009-09-23 23:48 暗夜教父 閱讀(753) | 評論 (0)編輯 收藏
            僅列出標題
            共9頁: 1 2 3 4 5 6 7 8 9 

            <2009年9月>
            303112345
            6789101112
            13141516171819
            20212223242526
            27282930123
            45678910

            常用鏈接

            留言簿(2)

            隨筆分類

            隨筆檔案

            文章分類

            文章檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            伊人久久大香线蕉无码麻豆| 波多野结衣AV无码久久一区| 亚洲国产精品久久久久久| 精品久久久久一区二区三区| 人妻无码久久精品| 久久久久女人精品毛片| 久久夜色精品国产| 国产成人久久精品激情| 久久中文精品无码中文字幕 | 97久久精品人妻人人搡人人玩| 国产99精品久久| 久久影视国产亚洲| 国产精品久久国产精麻豆99网站| 久久久久国产| 久久99国产精品久久久| 亚洲中文字幕伊人久久无码 | 久久综合九色综合网站| 成人免费网站久久久| 波多野结衣久久| 久久这里有精品视频| 久久国产高清字幕中文| 欧美牲交A欧牲交aⅴ久久 | 开心久久婷婷综合中文字幕| 久久偷看各类wc女厕嘘嘘| 久久成人小视频| 中文字幕久久亚洲一区| 久久九九免费高清视频| 亚洲一本综合久久| 国内精品伊人久久久久AV影院| 亚洲欧美成人久久综合中文网| 91精品国产91久久久久久青草| 久久精品www人人爽人人| 久久精品国产亚洲av麻豆小说| 国产99久久久国产精品小说| 亚洲午夜精品久久久久久浪潮| 久久国产精品免费一区| 国产精品无码久久四虎| 国产亚州精品女人久久久久久| 99久久人人爽亚洲精品美女| 色综合久久精品中文字幕首页 | 久久国产综合精品五月天|