好比A,B,C3人同時在一個頁面上瀏覽,A對B進行了評論,而且提到了C。傳統的架構,B,C將沒法感知到,只有B,C再次拉取內容時,纔會獲得此信息。顯然B ,C錯過了與A交互的最佳時機,並且得知信息的時間延後了不少。java
傳統的PULL模式,也能夠經過定時輪詢的方式來嘗試拉取數據。但這種技術mysql
1是並非實時的,信息仍是須要到了必定時間間隔才能夠獲得。程序員
2,這種方式可能大部分請求是無效的,白白浪費了一次網絡請求。還形成了web Server的負載大大增高。web
真正的PUSH技術目前有3種,算法
WebSocket,目前還不夠成熟,並且IE瀏覽器或其餘低版本瀏覽器不支持。sql
Flash Socket,雖然能夠實現,但須要依賴Flash第三方組件,並且可能會被防火牆或者其餘安全策略攔截,實際效果不理想。數據庫
XHR輪詢,這種方式目前是最成熟的解決方案,瀏覽器端開啓KeepAlive,Server使用epoll等異步IO方式,效率很是高,實測效果很是好。目前Facebook、人人網都使用此模式。編程
騰訊的PSF框架瀏覽器
PSF是騰訊開發的一套徹底使用PHP開發的邏輯Server框架,基於epoll異步事件通知模型安全
支持TCP長鏈接、TCP短鏈接、UDP,3種模式。
TCP使用了經典的Multi-Reactor模型,UDP使用相似LVS的半同步/半異步模型,運行效率很高。在高併發高負載的環境可快速穩定地運行。
PSF擁有完善的多配置多插件管理體系,健壯的Worker進程管理系統,全自動柔性重啓策略。
PSF框架支撐着不少邏輯層Server,有數百臺線上服務器運行着PSF的插件。在公司內的四層架構建設中發揮了很大的做用。
PSF使用簡單方便,開發人員無需關注底層實現,只需專一於業務邏輯開發。
PSF採用了單一配置文件,開發人員只須要修改配置文件便可調整監聽IP、端口、資源分配、協議類型、業務組件的上線/下線以及服務器擴容。配置文件中提供了不少選項,能夠針對業務的特徵,對Server的運行參數進行微調。
PSF框架性能很是好,併發2000壓測,一個簡單的EchoServer,TCP每秒可處理4萬個請求,UDP可處理6萬請求。
近來公司某個域名流量大漲,發現一個外部QQ登陸的接口常常失敗,用戶登陸老是不成功。通過排查發現是登陸的第一步須要保存一個token_secret。當時的程序員編寫此代碼時直接用了$_SESSION來保存token_secret。這裏在併發量小時問題不大,併發大了以後極有可能會出問題。
假設A,B兩個請求同時出發,A,B同時session_start,讀取到了一個$SESSION的值。當A完成請求寫入$SESSION,但B尚未完成請求,B完成請求後再寫$_SESSION,就會覆蓋A所設置的值。
相似的數據同步問題其實不少的,好比file_put_contents寫PHP的Cache文件,若是不加LOCK_EX就可能會存在同步問題,當一個進程寫file時,只寫到一半有另外的進程去require此文件,這時就會由於文件不完整,致使PHP語法錯誤。因此涉及到同時讀寫同一個文件或數據時必定要加鎖,不然在高併發的狀況下會產生嚴重錯誤。
線程是在同一個進程內的,能夠共享內存變量實現線程間通訊
線程比進程更輕量級,開很大量進程會比線程消耗更多系統資源
多線程也存在一些問題:
線程讀寫變量存在同步問題,須要加鎖
鎖的粒度過大會有性能問題,可能會致使只有1個線程在運行,其餘線程都在等待鎖。這樣就不是並行了
同時使用多個鎖,邏輯複雜,一旦某個鎖沒被正確釋放,可能會發生線程死鎖
某個線程發生致命錯誤會致使整個進程崩潰
多進程方式更加穩定,另外利用進程間通訊(IPC)也能夠實現數據共享。
共享內存,這種方式和線程間讀寫變量是同樣的,須要加鎖,會有同步、死鎖問題。
消息隊列,能夠採用多個子進程搶隊列模式,性能很好
PIPE,UnixSock,TCP,UDP。可使用read/write來傳遞數據,TCP/UDP方式使用socket來通訊,子進程能夠分佈運行
利用fork能夠實現一個最簡單的併發TCP Server。主進程accept鏈接,有新的鏈接到來就Fork一個子進程。
子進程中循環recv/send,處理數據。
這種模式在請求量很少狀況下很實用,像FTP服務器。過去有不少Linux程序都是這種模式的,簡單高效,幾十行代碼就能夠實現。固然這種模型在幾百個併發的狀況下還算不錯,大量併發的狀況下就有點消耗過大了。
Go語言是google推出的一個靜態編譯型語言,目標是取代C、C++、Java做爲系統開發的語言。開發者不少都是來自貝爾實驗室的大神。Go語言包含了不少很是酷的語言特性,值得嘗試。
目前Google、盛大、金山、百度等公司已經開始使用Go語言開發系統模塊了。本文重點介紹下Go語言區別於通常語言的特性。其餘語言,好比內置數據結構,內存管理,閉包,反射等共有的特性就不說了,Go語言所有都有。
一、語言級別的原生併發機制:goroutine
C/C++、java C#等語言都有併發的庫,通常都是對操做系統的線程或進程庫作封裝,使用很不方便。
好比Pthread線程。
Go語言內建了併發機制,使用很是簡單。Go語言會本身調度goroutine。goroutine的實現也很高效,能夠同時開啓幾十萬個goroutine,並且goroutine之間互相切換成本很低。
func abc(s sting){
time.Sleep(1);
fmt.Println(s);
}
//普通的串行調用
abc(「hello」)
//Go語言並行調用
go abc(「hello」)
Go語言還提供了遠程RPC調用,執行go func() 時甚至能夠是分佈式調用的。
二、語言級別的管道通訊機制:channel
大部分語言都是用共享內存方式進行通訊,而Go語言徹底使用消息傳遞來進行通訊,安全高效無鎖。
channel能夠幹各類事情,用來作消息傳遞,管道,緩衝區,mutex等等,還能夠配合使用select語法。
ch := make(chan int, 1000)
go func(){
time.Sleep(1e9)
ch <- 999 //寫入數據
}
num = <- ch //讀數據
chan還能夠當成參數傳遞。Go語言還提供了netchan,能夠跨越網絡實現消息傳遞。
三、語言級別的延遲執行特性:defer
好比鏈接mysql,調用完成後,須要關閉鏈接通常語言要很當心地考慮加在什麼地方。如何處理好異常,好比Java中複雜的final語法。Go語言能夠很是輕鬆的實現,只須要在開始的時候加defer,具體什麼時間調用,Go語言會幫你處理。
db.Connect(host, port, db)
defer db.Close()
…//讀取數據庫
四、語言級別的多返回值特性
C/C++、Java、PHP之類語言想要return多個值,須要很複雜的處理。Go語言很簡單,語言自然支持。
ret1, ret2 = func1()
func func1()(ret1 int, ret2 int){
ret1 := 1
ret2 := 2
return ret1, ret2
}
五、Go語言不用寫 ;結束符
六、Go語言經過首字母大小寫來控制public、private
七、Go語言能夠跟C語言無縫結合
慎用全局變量,全局變量很差管理的,會致使你的代碼依賴於全局變量,而耦合度過高。
必定不要複製粘貼代碼,可重用的代碼必定要寫成函數,或者類。等你代碼多了,就知道這個多麼重要了。
不要硬編碼數據到代碼中,必定要可配置化。若是是全局使用的就搞個全局config。若是僅在類中使用,請使用類靜態變量配置。別直接在代碼裏頭寫
程序的結構化要作好,先規劃一個流程。代碼怎麼運轉的,要很清晰,有主線,從A->B->C,一眼就明白了,並且很容易修改流程和增長,替換環節。不要A直接進入B而後沒蹤跡了,而後在B中又進入C又沒蹤跡了。
搞個Trace系統,在你的代碼中加入Trace來進行調試。跟蹤變量的變化,這樣會很方便。發佈代碼時,可註釋掉全部Trace,只須要批量替換便可。
多寫點單元測試的腳本,一旦更改了代碼,作了大的版本更新。不須要你挨個去試,跑一下單元測試就知道是否是有的地方出問題了。
不少IT公司都採用產品驅動技術的管理模式,咱們騰訊也是如此。身爲一個程序員不得不對這種模式作點評價。
不能否認這種模式會比較快得做出產品來,雖然開發出的產品不必定會是最好,最起碼不會是最差。另外產品開發的成功率也獲得了保證,不至於作了一半不搞了。
可是也順便講講他的壞處吧。產品驅動的開發模式最致命的問題是:會讓全部程序員完全失去積極性。不管多麼棒的Idea,多麼有意思的Idea,只要用了這種模式,程序員的那種積極性,創新性都將不存在了。逐漸會產生另一個問題,反正不是我主導的,我不用再思考了,大家怎麼說我就怎麼作吧。效率愈來愈差勁。若是軍隊是參謀指揮將軍,打起仗來會怎麼樣?
談論下Facebook的管理模式吧。他們也有產品經理,但主要產品的是技術人員而不是產品經理,產品經理負責給技術出謀劃策,提供信息幫助技術人員。他們的效率很高。
騰訊也是產品驅動型的管理模式,不過廣州研發部是個例外,也正是由於例外,因此他們搞出了QQ郵箱,微信這樣的重量級產品來。
對於一個大型網站來講,代碼庫很是龐大,模塊衆多。部門協做的人數規模在百人以上,如何跟蹤定位問題不像小網站那樣容易。並且咱們的服務器都是集羣化的,動輒幾千臺。有一套可查詢方便使用的日誌系統相當重要。
對於日誌的使用也有了必定的經驗。咱們的日誌一般會很是詳細的記錄各類參數,環境變量,HOST等信息,在出現異常的狀況下,必需要記錄日誌。咱們使用了MySQL按時間分片的方式來記錄日誌,全部集羣內節點均經過網絡方式來寫入到中心日誌系統。
在管理端咱們提供了很方便友好的工具,來查詢定位日誌,可按用戶ID、類型、時間等幾種索引方式查詢。日誌系統幫助咱們定位到了不少問題。
PHP錯誤日誌是全部PHP程序問題最直接的反饋渠道。經過分析PHP日誌能夠發現和分析出系統現有的Bug和潛在的問題。咱們經過在節點部署監控工具,實時收集PHP錯誤日誌,Fatal Error告警。解決了不少問題
咱們有一整套數據上報的系統,系統內各類接口調用、請求響應、錯誤返回,都會上報到數據統計中心。咱們以報表的形式展示出來,能夠很方便的看到每一個模塊,每一個接口的可用性,成功率,數據規模。根據數據,咱們還作了成功率告警,當接口成功率低於某個數值,好比99.99%時就會發送短信報警。還有歷史數據對比報警,當發現今日數據與往期數據差距較大時,多是系統出現了問題,會及時進行報警。
咱們有一套工具,來監控每一個服務器節點的CPU、硬盤、內存、網卡流量信息,以及其餘系統關鍵參數的信息。並以圖表方式提供展現,方便了解服務器運行狀況。每次新版本,或新功能上線,都經過這些信息來感知訪問量變化,以及機器的負載狀況。
當一組Server中其中一臺出現問題時,會及時發現,並踢掉。
深刻理解計算機系統
UNIX環境高級編程
深刻理解Linux內核
UNIX網絡編程
TCP/IP詳解
Linux多線程服務端編程
算法導論
《數據結構》(C語言版)
C程序設計語言
PHP5權威編程