<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                典型的兩個現實案例: 我們先看兩個用Go做消息推送的案例實際處理能力。 360消息推送的數據: 16臺機器,標配:24個硬件線程,64GB內存 Linux Kernel 2.6.32 x86_64 單機80萬并發連接,load 0.2~0.4,CPU 總使用率 7%~10%,內存占用20GB (res) 目前接入的產品約1280萬在線用戶 2分鐘一次GC,停頓2秒 (1.0.3 的 GC 不給力,直接升級到 tip,再次吃螃蟹) 15億個心跳包/天,占大多數。 京東云消息推送系統 (團隊人數:4) 單機并發tcp連接數峰值118w 內存占用23G(Res) Load 0.7左右 心跳包 4k/s gc時間2-3.x s C10K問題 為什么可以支撐這么高并發的請求呢?我們先從C10K問題說起:2001年左右的時候,有一個叫Dan Kegel的人在網上提出:現在的硬件應該能夠讓一臺機器支持10000個并發的client。然后他討論了用不同的方式實現大規模并發服務的技術。 http://www.kegel.com/c10k.html (英文版) http://www.oschina.net/translate/c10k (中文翻譯版) http://www.cnblogs.com/fll/archive/2008/05/17/1201540.html 當然, 現在C10K 已經不是問題了, 任何一個普通的程序員, 都能利用手邊的語言和庫, 輕松地寫出 C10K 的服務器. 這既得益于軟件的進步, 也得益于硬件性能的提高,現在應該擴展討論的是應該是C10M問題了。 參考資料: 千萬級并發實現的秘密:內核不是解決方案,而是問題所在! http://www.csdn.net/article/2013-05-16/2815317-The-Secret-to-10M-Concurrent-Connections Coroutine模型 和 非阻塞/異步IO(callback) 不論線程還是進程,都不可能一個連接創建一個,相應的成本太大,多進程和多線程都有資源耗費比較大的問題,所以在高并發量的服務器端使用并不多。解決方案是一個線程或者進程處理多個連接,更具體的現在比較主流的是:Coroutine模型 和 非阻塞/異步IO(callback),在分析這兩個之前,我們先看看多進程和多線程的情況。 多進程 這種模型在linux下面的服務程序廣泛采用,比如大名鼎鼎的apache。 下圖說明了Apache的生命周期(prefork模式)。主進程負責監聽和管理連接,而具體的業務處理都會交給子進程來處理。 1234514831_ddvip_588 這種架構的最大的好處是隔離性,子進程萬一crash并不會影響到父進程。缺點就是對系統的負擔過重,想像一下如果有上萬的連接,會需要多少進程來處理。所以這種模型比較合適那種不需要太多并發量的服務器程序。另外,進程間的通訊效率也是一個瓶頸之一,大部分會采用share memory等技術來減低通訊開銷。 apache的處理能力,下面有幾篇文章: 2008年時的數據:http://www.blogjava.net/daniel-tu/archive/2008/12/29/248883.html http://wenku.baidu.com/view/c527582a453610661ed9f40f.html Apache的問題 Apache的問題在于服務器的性能會隨著連接數的增多而變差 關鍵點:性能和可擴展性并不是一回事。當人們談論規模時,他們往往是在談論性能,但是規模和性能是不同的,比如Apache。 持續幾秒的短期連接,比如快速事務,如果每秒處理1000個事務,只有約1000個并發連接到服務器。 事務延長到10秒,要維持每秒1000個事務,必須打開1萬個并發連接。這種情況下:盡管你不顧DoS攻擊,Apache也會性能陡降;同時大量的下載操作也會使Apache崩潰。 如果每秒處理的連接從5千增加到1萬,你會怎么做?比方說,你升級硬件并且提高處理器速度到原來的2倍。發生了什么?你得到兩倍的性能,但你沒有得到兩倍的處理規模。每秒處理的連接可能只達到了6000。你繼續提高速度,情況也沒有改善。甚至16倍的性能時,仍然不能處理1萬個并發連接。所以說性能和可擴展性是不一樣的。 問題在于Apache會創建一個CGI進程,然后關閉,這個步驟并沒有擴展。 為什么呢?內核使用的O(N^2)算法使服務器無法處理1萬個并發連接。 內核中的兩個基本問題: 連接數=線程數/進程數。當一個數據包進來,內核會遍歷其所有進程以決定由哪個進程來處理這個數據包。 連接數=選擇數/輪詢次數(單線程)。同樣的可擴展性問題,每個包都要走一遭列表上所有的socket。 解決方法:改進內核使其在常數時間內查找。 使線程切換時間與線程數量無關。 使用一個新的可擴展epoll()/IOCompletionPort常數時間去做socket查詢。 參考:http://www.csdn.net/article/2013-05-16/2815317-The-Secret-to-10M-Concurrent-Connections 多線程 這種模型在windows下面比較常見。它使用一個線程來處理一個client。他的好處是編程簡單,最重要的是你會有一個清晰連續順序的work flow。簡單意味著不容易出錯。 這種模型的問題就是太多的線程會減低軟件的運行效率。 線程和進程的成本 普通的線程,需要消耗1M的堆棧 http://www.cnblogs.com/PurpleTide/archive/2010/11/12/1875763.html 多進程和多線程的優缺點... http://blog.163.com/ymguan@yeah/blog/static/140072872201147832740/ 我們知道,操作系統的最小調度單元是“線程”,要執行任何一段代碼,都必須落實到“線程”上。可惜線程太重,資源占用太高,頻繁創建銷毀會帶來比較嚴重的性能問題,于是又誕生出線程池之類的常見使用模式。也是類似的原因,“阻塞”一個線程往往不是一個好主意,因為線程雖然暫停了,但是它所占用的資源還在。線程的暫停和繼續對于調度器都會帶來壓力,而且線程越多,調度時的開銷便越大,這其中的平衡很難把握。 針對這個問題,有兩類架構解決它:基于callback和coroutine的架構。 Callback- 非阻塞/異步IO 這種架構的特點是使用非阻塞的IO,這樣服務器就可以持續運轉,而不需要等待,可以使用很少的線程,即使只有一個也可以。需要定期的任務可以采取定時器來觸發。把這種架構發揮到極致的就是node.js,一個用javascript來寫服務器端程序的框架。在node.js中,所有的io都是non-block的,可以設置回調。 舉個例子來說明一下。 傳統的寫法: var file = open(‘my.txt’); var data = file.read(); //block sleep(1); print(data); //block node.js的寫法: fs.open(‘my.txt’,function(err,data){ setTimeout(1000,function(){ console.log(data); } }); //non-block 這種架構的好處是performance會比較好,缺點是編程復雜,把以前連續的流程切成了很多片段。另外也不能充分發揮多核的能力。 Coroutine-協程 coroutine本質上是一種輕量級的thread,它的開銷會比使用thread少很多。多個coroutine可以按照次序在一個thread里面執行,一個coroutine如果處于block狀態,可以交出執行權,讓其他的coroutine繼續執行。 非阻塞I/O模型協程(Coroutines)使得開發者可以采用阻塞式的開發風格,卻能夠實現非阻塞I/O的效果隱式事件調度, 簡單來說:協程十分輕量,可以在一個進程中執行有數以十萬計的協程,依舊保持高性能。 進程、線程、協程的關系和區別: 進程擁有自己獨立的堆和棧,既不共享堆,亦不共享棧,進程由操作系統調度。 線程擁有自己獨立的棧和共享的堆,共享堆,不共享棧,線程亦由操作系統調度(標準線程是的)。 協程和線程一樣共享堆,不共享棧,協程由程序員在協程的代碼里顯示調度。 堆和棧的區別請參看:http://www.cnblogs.com/ghj1976/p/3623037.html 協程和線程的區別是:協程避免了無意義的調度,由此可以提高性能,但也因此,程序員必須自己承擔調度的責任。 執行協程只需要極少的棧內存(大概是4~5KB),默認情況下,線程棧的大小為1MB。 goroutine就是一段代碼,一個函數入口,以及在堆上為其分配的一個堆棧。所以它非常廉價,我們可以很輕松的創建上萬個goroutine,但它們并不是被操作系統所調度執行。 Google go語言對coroutine使用了語言級別的支持,使用關鍵字go來啟動一個coroutine(從這個關鍵字可以看出Go語言對coroutine的重視),結合chan(類似于message queue的概念)來實現coroutine的通訊,實現了Go的理念 ”Do not communicate by sharing memory; instead, share memory by communicating.”。 http://my.oschina.net/Obahua/blog/144549 goroutine 的一個主要特性就是它們的消耗;創建它們的初始內存成本很低廉(與需要 1 至 8MB 內存的傳統 POSIX 線程形成鮮明對比)以及根據需要動態增長和縮減占用的資源。這使得 goroutine 會從 4096 字節的初始棧內存占用開始按需增長或縮減內存占用,而無需擔心資源的耗盡。 為了實現這個目標,鏈接器(5l、6l 和 8l)會在每個函數前插入一個序文,這個序文會在函數被調用之前檢查判斷當前的資源是否滿足調用該函數的需求(備注 1)。如果不滿足,則調用 runtime.morestack 來分配新的棧頁面(備注 2),從函數的調用者那里拷貝函數的參數,然后將控制權返回給調用者。此時,已經可以安全地調用該函數了。當函數執行完畢,事情并沒有就此結束,函數的返回參數又被拷貝至調用者的棧結構中,然后釋放無用的棧空間。 通過這個過程,有效地實現了棧內存的無限使用。假設你并不是不斷地在兩個棧之間往返,通俗地講叫棧分割,則代價是十分低廉的。 簡單來說:Go語言通過系統的線程來多路派遣這些函數的執行,使得每個用go關鍵字執行的函數可以運行成為一個單位協程。當一個協程阻塞的時候,調度器就會自動把其他協程安排到另外的線程中去執行,從而實現了程序無等待并行化運行。而且調度的開銷非常小,一顆CPU調度的規模不下于每秒百萬次,這使得我們能夠創建大量的goroutine,從而可以很輕松地編寫高并發程序,達到我們想要的目的。 Coroutine模型 和 非阻塞/異步IO(callback)性能對比 從性能角度來說,callback的典型node.js和golang的性能測試結果,兩者差不多,參考下面測試數據: http://www.cnblogs.com/QLeelulu/archive/2012/08/12/2635261.html 不過從代碼可讀性角度來說,callback確實有點不太好。 參考資料: 風格之爭:Coroutine模型 vs 非阻塞/異步IO(callback) http://blog.csdn.net/kjfcpua/article/details/15809703 Goroutine(協程)為何能處理大并發? http://www.cnblogs.com/ghj1976/p/3642513.html python Eventlet http://www.360doc.com/content/14/0522/00/8504707_379786818.shtml 為什么我認為goroutine和channel是把別的平臺上類庫的功能內置在語言里 http://blog.zhaojie.me/2013/04/why-channel-and-goroutine-in-golang-are-buildin-libraries-for-other-platforms.html Go-簡潔的并發 http://www.yankay.com/go-clear-concurreny/ GOROUTINE性能測試 http://www.kankanews.com/ICkengine/archives/115285.shtml Golang特性介紹 http://mryufeng.iteye.com/blog/576968/ 并發編程 http://book.2cto.com/201301/14436.html ![](https://box.kancloud.cn/032176b8778dbc41f1ce6b79a83d59c1_900x350.jpg)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看