互聯網公司高並發圖片(縮略圖)處理中間層服務架構設計一


互聯網公司高並發圖片處理中間層服務架構設計                                 

                              目錄

背景 1

大吞吐量服務端架構設計要考慮四個技術點 1

編程語言和編譯優化 2

下面說一下單進程多線程模型 2

多進程服務器: 3

圖片壓縮算法(jpeg,png,gif) 4

高效分布式文件存儲系統選型 4

Linux系統中sysctl參數優化(TCP高級選項設置) 5

背景

本文分析互聯網公司高並發高吞吐量(訪問)下圖片處理(主要是圖片壓縮或變換)中間層服務架構設計,互聯網公司經常會有大量原始圖片上傳,而且一個原圖會在頁面以不同尺寸縮略圖顯示,一般有兩種策略生成縮略圖,一種在上傳圖片時,生成需要的多張不同縮略圖,另一種是請求指定尺寸的圖片時實時生存縮略圖片,第一種方式有一定限制,就是需要提前知道所有尺寸的圖片,做雍余存儲,無形中增加大量文件數量,如果文件系統設計不好,還有可能形成大量文件碎片,而且會消耗大量存儲空間,如果前端ui設計改變了圖片大小,需要重新生成。而第二種方式更加靈活,但是更消耗cpu資源,屬於cpu密集計算型,以上兩種方式優缺點一目了然,如果選擇就要看公司服務器資源側重點了。 

我只是把個人見解做一下分析,不准確地方歡迎大家指出。

大吞吐量服務端架構設計要考慮四個技術點

編程語言和編譯優化

技術選型,是單進程多線程模型(reactor事件機制),還是多進程模型.

圖片壓縮算法

高效分布式文件存儲系統選型。

Linux系統中sysctl參數優化(TCP高級選項設置)

 

編程語言和編譯優化

互聯網行業用java開發語言比較多,而且開發人員成熟,而且經驗豐富。

高性能網絡框架:nettymina等等,而且資料比較,社區比較活躍。而且有大量內置的圖像處理API和算法直接使用.對於jdk自帶的一套圖片處理庫,他的特點是穩定簡單,但是對圖片處理來說,性能確實很差!離實際線上要求差距很大。不過java方面也提供了類似jni方式支持GraphicsMagick+im4java處理圖像,但是要原生態支持openmpi,tbbopencv等就比較繁瑣了,要用jni方式調用大量動態或靜態庫。一個性能問題,二是如果出現內存問題也不好控制。

C語言:

1.有成熟圖像處理庫GraphicsMagick和opencv

2.有可以很容易實現多進程模式。

3.容易用其他編譯器做優化,比如用intel icc編譯,可以大幅度提高性能。

4.多進程中每個進程方面綁定到每個cpu核上,實現操作系統每個cpu核上隊列相同,均衡調度,更容易發揮目前多核cpu性能!

 

下面說一下單進程多線程模型

主線程負責偵聽listen,注冊accept和新進來連接,然后把連接socket轉交給work thread pool進行讀寫事件注冊,計算邏輯處理

reactor事件機制:

Reactor釋義“反應堆”,是一種事件驅動機制。和普通函數調用的不同之處在於:應用程序不是主動的調用某個API完成處理,而是恰恰相反,Reactor逆置了事件處理流程,應用程序需要提供相應的接口並注冊到Reactor上,如果相應的時間發生,Reactor將主動調用應用程序注冊的接口,這些接口又稱為“回調函數”.

 Reactor模式的優點

Reactor模式是編寫高性能網絡服務器的必備技術之一,它具有如下的優點:
    1)響應快,不必為單個同步時間所阻塞,雖然Reactor本身依然是同步的;
    2)編程相對簡單,可以最大程度的避免復雜的多線程及同步問題,並且避免了多線程/進程的切換開銷;
    3)可擴展性,可以方便的通過增加Reactor實例個數來充分利用CPU資源;
    4)可復用性,reactor框架本身與具體事件處理邏輯無關,具有很高的復用性;

多進程服務器:

每個進程處理多個connection,使用epoll事件驅動來管理這些連接,多個worker進程之間是對等的,他們同等競爭來自客戶端的請求,各進程互相之間是獨立的

master由信號驅動,workerepoll驅動(當然信號會讓epoll_wait返回),有更好的容錯性,如果其中一個進程掛了或產生core,master收到相關信號后,會同時重啟一個進程,並同時發送出相關監控信息,也不會導致不能提供服務,

多進程用來利用多CPU硬件,所以按照業務邊界來划分進程,或者就按CPU個數配置。

每個進程是單線程的:所有IO相關操作都是全異步處理方式, 避免多線程切換和鎖機制開銷

進程之間搶占epoll資源時,僅用一個輕量級的共享內存鎖,循環依次把連接事件放入隊列,然后循環處理每個客戶端的連接請求和邏輯處理。

高性能:服務器若支持多CPU或超線程,多線程無法完全利用機器性能,多進程則可以讓服務器滿載.

 

 

 

圖片壓縮算法(jpeg,png,gif)

目前圖像壓縮算法已經成型,而且基本上都是搞數學方面的大牛發明的,

關於圖像處理方面可以參考如下:http://blog.csdn.net/lizhitao/article/details/9317521

圖片壓縮或處理是一個非常消耗cpu的操作計算量非常大,因為要進行大量矩陣,傅立葉變換、沃爾什變換、離散余弦變換,圖像噪聲處理等變換或計算.目前高性能圖像處理開源軟件有2GraphicsMagick和opecv

GraphicsMagick:

GraphicsMagick號稱圖像處理領域的瑞士軍刀。 短小精悍的代碼卻提供了一個魯棒、高效的工具和庫集合,來處理圖像的讀取、寫入和操作,支持超過88圖像格式,包括重要的DPXGIFJPEGJPEG-2000PNGPDFPNMTIFF等等。

通過使用OpenMP可是利用多線程進行圖片處理,增強了通過擴展CPU提高處理能力。

注意:但是GraphicsMagick啟動多線程時,處理速度雖然加快了,但是cpu確大幅飆升。

Opencv:

OpenCV1999年由Intel建立,如今由Willow Garage提供支持。OpenCV是一個基於[1](開源)發行的跨平台計算機視覺庫,可以運行在LinuxWindowsMac OS操作系統上。它輕量級而且高效——由一系列 函數和少量 C++ 類構成,同時提供了PythonRubyMATLAB等語言的接口,實現了圖像處理和計算機視覺方面的很多通用算法。[2]最新版本是2.4.5

OpenCV 擁有包括 300 多個C函數的跨平台的中、高層 API。它不依賴於其它的外部庫——盡管也可以使用某些外部庫。

注意opencv目前支持jpeg,tiff,png,但是由於版權和法律方面原因不支持gif圖像處理,png只是有限支持,圖像壓縮時會變形或變模糊。

 

GraphicsMagick與Opencv比較優缺點:

GraphicsMagick支持圖像多,覆蓋面全,幾乎所有常見圖像格式.壓縮質量高

Opencv支持有限的圖像處理,覆蓋面不全,經過大量壓力測試綜合比較,但是壓縮性能確比GraphicsMagick快一倍多。

綜合兩者的優點:需要把兩者結合起來混合處理不同圖像,以達到圖像處理最佳性能。

高效分布式文件存儲系統選型

互聯網圖片文件存儲,一般考慮帶寬,存儲空間方面壓力,經過壓縮大小不會2MB。因此存儲方案就有多種選擇,既可以選擇傳統mysql數據庫,也可以用成熟的分布式文件系統.下面就來說說他們的不同和優缺點。

mysql做存儲:

1.互聯網公司都用mysql的豐富經驗,技術成熟,眾多人都會用mysql,而且還有專業的DBA團隊來維護。

2.Mysq性能穩定,單台機器加上內存,基本能滿足QPS性能要求。

3.存儲圖片的表結構屬性少,結構簡單,一般訪問時只需要查詢主鍵就可以了,不需求簡歷額外的索引。

4.去中心化設計,兩台服務器為一組,雙寫隨機讀(任意一台服務器),服務器為raid5模式。

5.系統擴容,每當當前服務器存儲空間不足,需要增加服務器擴容時,都需要成倍增加服務器數量.

 


 

用分布式文件做存儲

1.一般是直接使用成熟開源產品或自主研發,使用開源產品,開發成本低,學習成本高,需要專門花費一些進行研究或學習。還要自己來維護。自主研發,時間周期長,投入成本更高,但可控性更強。能進行大量性能優化和調整,或許能節省一些服務器資源。

2.同等條件下分布式文件系統性能一般會比mysql等關系型數據庫高3-5倍,因為它不需求進行B+Tree(時間復雜度 )分頁查找,文件在上傳時,其生成的文件名就包含了大量文件具體位置信息,一般o(1)時間就能准備定位。而且是順序一次性讀取。不想B+Tree按頁式存儲,可能要多次讀取多頁數據,而且每條記錄需求存儲額外信息,進行事物回滾處理,比較浪費存儲空間。

3.中心化設計(一般為meta serverdata server兩類服務器組集群),兩或三台服務器為一組,雙寫隨機讀(任意一台服務器),可以不用raid5模式。

4.系統擴容,每當當前服務器存儲空間不足,可以輕易做到線性擴展,只需要增加一組服務器就可以了。明顯在成本上具有優勢。

 

Linux系統中sysctl參數優化(TCP高級選項設置)

服務器在高並發時,會創建大量連接,這就需要設置TCP相關參數來提供服務器性能。

1.文件描述符最大數調整。

   修改 vi /etc/security/limits.conf 值

      在里面添加一行

      * - nofile 65535
    保存重啟,再用命令ulimit -n 可發現文件描述符由默認變成65535

2.高負載linux服務器的內核調優
vi /etc/sysctl.conf,修改內核參數:
kernel.shmall = 268435456
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 5000 65000
net.ipv4.tcp_mem = 786432 1048576 1572864
net.core.wmem_max = 873200
net.core.rmem_max = 873200
net.ipv4.tcp_wmem = 8192 436600 873200
net.ipv4.tcp_rmem = 32768 436600 873200
net.core.somaxconn = 256
net.core.netdev_max_backlog = 1000
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_retries2 = 5
net.ipv4.tcp_keepalive_time = 500
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.conf.lo.arp_ignore = 0
net.ipv4.conf.lo.arp_announce = 0
net.ipv4.conf.all.arp_ignore = 0
net.ipv4.conf.all.arp_announce = 0

3.參數說明:
net.ipv4.tcp_syncookies = 1
#表示開啟SYN Cookies。當出現SYN等待隊列溢出時,啟用cookies來處理,可防范少量SYN攻擊,默認為0,表示關閉;
net.ipv4.tcp_tw_reuse = 1
#表示開啟重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認為0,表示關閉;
net.ipv4.tcp_tw_recycle = 1
#表示開啟TCP連接中TIME-WAIT sockets的快速回收,默認為0,表示關閉。
net.ipv4.tcp_fin_timeout = 30
#表示如果套接字由本端要求關閉,這個參數決定了它保持在FIN-WAIT-2狀態的時間。
net.ipv4.tcp_keepalive_time = 1200 
#表示當keepalive起用的時候,TCP發送keepalive消息的頻度。缺省是2小時,改為20分鍾。
net.ipv4.ip_local_port_range = 1024    65000 
#表示用於向外連接的端口范圍。缺省情況下很小:3276861000,改為102465000
net.ipv4.tcp_max_tw_buckets = 5000
#表示系統同時保持TIME_WAIT套接字的最大數量,如果超過這個數字,
#TIME_WAIT套接字將立刻被清除並打印警告信息。默認為180000,改為5000

 

后續會分享一下pic server中間層服務器如何設計的,其100-200KB設置縮略圖尺寸100*75,實時壓縮(計算)如何達到單台機器1000左右/QPS

硬件服務器配置:戴爾PowerEdge R710 八核16線程     Xeon E5620 2.4GHz

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM