# 如何搭建高性能服務器
運營一個餐廳和構建一個高性能的服務器有很多相似的地方,我們一起來看看吧。
### 單打獨斗的單線程模式
小明的餐廳剛起步,規模很小,就只有小明一個人在忙活。當客人到來的時候,他得首先去招呼客人,等客人下單,然后去后廚炒菜,然后再把飯菜端給客人。如果在這個過程中有新的客人到來,他是沒有功夫去招呼新客人,新客人就只能在那里等候,或者等不及了就離開了。這就類似于服務器在一個線程里面等待客戶端的連接請求并在同一個線程中讀取數據、處理請求和返回數據,在這種模式下客戶端在一個時間點只能處理一個客戶的請求。當然,餐廳老板不會采用這種模式,也沒有服務器是這樣設計的### 。
單打獨斗的高級模式
小明經過一段時間的努力,掌握了兩個新本領:1)多任務處理能力,能在給一個客人點單或者炒菜的同時能招呼新來的客人;2)批處理能力,如果幾位客人到達的時間差不多,先等他們點好單后再一起做。這樣運作的餐廳,當客人多的時候,小明忙得不可開交,響應速度也變慢了。類似的服務器程序可以用java NIO中的Selector來監聽多個通道上的socket請求,并且把客戶端請求放入隊列中以便批處理。同樣的,當客戶端請求一多,響應速度會變慢。
### 粗放型的多線程模式
餐廳在小明的打理下,規模慢慢壯大,又招聘了幾個服務員,其中一個服務員(前臺)專門招呼客人,其他幾個服務員負責點單和炒菜。當新客人來的時候,前臺隨機找一個空閑的服務員,讓其專門為這位客人服務(點單和炒菜)。這樣,餐廳終于能夠同時服務多位客人了。類似的服務器程序就是一個主線程負責接受(accept)客戶端請求,多個工作線程負責處理業務,并把結果返回給客戶端。這種模式的缺點是:1)系統的利用率不高,因為工作線程的很多時間可能阻塞在網絡IO上;2)系統的并發量上不去,因為這受制于系統能開啟的線程數量。
### 多線程的高級模式
在招聘了很多服務員以后,小明發明了一種全新的餐廳運作方式。讓一個服務員(前臺)在餐廳門口接待客戶,讓N個服務員(點菜員)負責點菜,然后讓M個服務員在后廚專門炒菜。新的接待客人的流程為:
當新客人到達餐廳時,前臺隨機找一個點菜員,讓其接待該客人,這樣前臺的工作很輕量,能保證其響應客戶的速度;
點菜員接到新客人的時候,首先將菜單給客人,讓其先看一下。這時他就可以處理別的客戶的請求了。同時,他會隨時注意分配給他的客人,看看客人是否可以點菜了。
當客人示意點菜員可以點菜后,點菜員則去處理客人的點菜請求,把客人點的菜寫在一張便簽紙上,并貼到后廚的小黑板。
后廚的廚師一旦看到小黑板上有新的便簽紙,便立刻取下便簽紙,然后去按照客人的要求去制作菜肴。
類似的服務器程序就是Reactor模式,其中包括了如下角色的線程:Acceptor,Processor和Handler,它們在系統中的數量和職責是:
一個Acceptor(類似于餐廳的前臺),專門監聽客戶端的請求,它自身并不處理客戶端的請求,它只是accept客戶端的連接請求,然后分配一個Processor給這個客戶端。
N個Processor(類似于餐廳的點菜員),它處理網絡讀寫請求,本身并不處理具體的業務,它用Selector來監聽分配給它的客戶端的讀寫請求,一旦某個客戶端變成可讀(類似于餐廳中的客人可以點菜了),它就去讀取客戶端發送來的數據并封裝成Request對象,并添加到一個隊列(類似于餐廳后廚的小黑板)中。
M個Handler,它是處理具體業務的線程(類似于餐廳中的廚師),它從隊列中取出Request對象并進行處理。
當Handler處理完一個Request后,返回結果返回給客戶端的時候有兩種選擇,一是交給讀取該客戶端數據的Processor,讓其返回給客戶端(類似于餐廳中點菜員負責給客戶上菜);另外一種是交給一組專門處理返回結果的線程(類似于餐廳中有專門的上菜員來給客戶上菜)。
這個模式的優點是職責明確,Acceptor和Processor都采用了非阻塞IO和Selector,從而一個線程就可以處理多個客戶端的讀寫請求,效率非常高。這種模式在很多餐廳和分布式系統中(比如Kafka和Hadoop)都有使用,也是目前比較主流一種設計。
- 我的筆記
- 服務器
- ubuntu svn 環境的搭建
- ubuntu Memcache 的配置
- ubuntu 密鑰登錄服務器
- centos 搭建服務器環境
- nginx+tomcat 集群搭建
- 餐廳運營來看如何構建高性能服務器
- VMware-Centos-網絡配置
- Ubuntu-PHP-Apache-Mysql-PhpMyadmin的搭建
- UbuntuApache配置日志
- linux獲取當前執行腳本的目錄
- Ubuntu svn的快速配置(原創)
- Https配置
- Mysql 不支持遠程連接解決方案
- ubuntu+apache+rewrite
- php Mcrypt 擴展
- 重啟Apache出現警告信息Could not reliably determine the server's fully qualified domain name,
- Mysql無法遠程連接
- 定時任務設置
- Linux中Cache內存占用過高解決辦法
- Ubuntu14-04安裝redis和php5-redis擴展
- php
- thinkphp3.2 一站多城市配置
- PHP 安全編程建議(轉)
- phpexcel導入時間處理
- Mysql按時,天,月,年統計數據
- PHP-支付寶-APP支付
- 百度爬蟲-獲取全國數據
- PHPEXCEL導入導出excel文件
- php-微信app支付后端設計
- Phpqrcode生成二維碼
- 圖片+文字水印
- 數據庫優化
- java
- Mybatis 二級緩存
- 微信
- 微信公眾號多域名授權
- 微信掃碼支付
- web
- 網站性能優化方案實施
- ionic環境搭建
- 登錄設計方案
- 設置dev元素的寬高比例
- 設計模式
- app
- 版本更新
- 微擎數據庫操作擴展
- select
- find
- delete
- update
- insert
- where
- order
- page
- group
- having
- limit
- fields
- debug
- bind
- join
- alias
- query
- 聚合函數
- count
- sum
- max
- min
- avg
- 事務管理
- 自增自減
- 算法設計
- ACM:入口的選擇------深度優先搜索
- java:N的N次方
- 最少攔截系統:貪心思想
- ACM:蠶寶寶:搜索
- ACM:n!的位數 :斯特林公式
- 神奇的異或
- 中國剩余定理
- 矩陣翻硬幣
- 回溯法
- ACM程序設計網站集錦
- 博弈論
- 多維空間上的搜索算法
- 算法學習筆記之一(排序)
- 算法學習筆記之二(堆排序)
- 算法學習筆記之三(快速排序)
- ACM俱樂部密碼
- 原創開源
- 個人感悟