日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

系統(tǒng)負(fù)載能力淺析

 漢無為 2017-09-30

互聯(lián)網(wǎng)時(shí)代,高并發(fā)是一個(gè)老生常談的話題。無論對于一個(gè)Web站點(diǎn)還是App應(yīng)用,高峰時(shí)能承載的并發(fā)請求都是衡量一個(gè)系統(tǒng)性能的關(guān)鍵標(biāo)志。像阿里雙十一頂住了上億的峰值請求、訂單也確實(shí)體現(xiàn)了阿里的技術(shù)水平(當(dāng)然有錢也是一個(gè)原因)。


那么,何為系統(tǒng)負(fù)載能力?怎么衡量?相關(guān)因素有哪些?又如何優(yōu)化呢?


一. 衡量指標(biāo)


用什么來衡量一個(gè)系統(tǒng)的負(fù)載能力呢?有一個(gè)概念叫做每秒請求數(shù)(Requests per second),指的是每秒能夠成功處理請求的數(shù)目。比如說,你可以配置Tomcat服務(wù)器的maxConnection為無限大,但是受限于服務(wù)器系統(tǒng)或者硬件限制,很多請求是不會(huì)在一定的時(shí)間內(nèi)得到響應(yīng)的,這并不作為一個(gè)成功的請求,其中成功得到響應(yīng)的請求數(shù)即為每秒請求數(shù),反應(yīng)出系統(tǒng)的負(fù)載能力。


通常的,對于一個(gè)系統(tǒng),增加并發(fā)用戶數(shù)量時(shí)每秒請求數(shù)量也會(huì)增加。然而,我們最終會(huì)達(dá)到這樣一個(gè)點(diǎn),此時(shí)并發(fā)用戶數(shù)量開始“壓倒”服務(wù)器。如果繼續(xù)增加并發(fā)用戶數(shù)量,每秒請求數(shù)量開始下降,而反應(yīng)時(shí)間則會(huì)增加。這個(gè)并發(fā)用戶數(shù)量開始“壓倒”服務(wù)器的臨界點(diǎn)非常重要,此時(shí)的并發(fā)用戶數(shù)量可以認(rèn)為是當(dāng)前系統(tǒng)的最大負(fù)載能力。


二. 相關(guān)因素


一般的,和系統(tǒng)并發(fā)訪問量相關(guān)的幾個(gè)因素如下:


  • 帶寬

  • 硬件配置

  • 系統(tǒng)配置

  • 應(yīng)用服務(wù)器配置

  • 程序邏輯

  • 系統(tǒng)架構(gòu)


其中,帶寬和硬件配置是決定系統(tǒng)負(fù)載能力的決定性因素。這些只能依靠擴(kuò)展和升級提高。我們需要重點(diǎn)關(guān)注的是在一定帶寬和硬件配置的基礎(chǔ)上,怎么使系統(tǒng)的負(fù)載能力達(dá)到最大。


2.1 帶寬


毋庸置疑,帶寬是決定系統(tǒng)負(fù)載能力的一個(gè)至關(guān)重要的因素,就好比水管一樣,細(xì)的水管同一時(shí)間通過的水量自然就少(這個(gè)比喻解釋帶寬可能不是特別合適)。一個(gè)系統(tǒng)的帶寬首先就決定了這個(gè)系統(tǒng)的負(fù)載能力,其單位為Mbps,表示數(shù)據(jù)的發(fā)送速度。


2.2 硬件配置


系統(tǒng)部署所在的服務(wù)器的硬件決定了一個(gè)系統(tǒng)的最大負(fù)載能力,也是上限。一般說來,以下幾個(gè)配置起著關(guān)鍵作用:


  • CPU頻率/核數(shù):CPU頻率關(guān)系著CPU的運(yùn)算速度,核數(shù)則影響線程調(diào)度、資源分配的效率。

  • 內(nèi)存大小以及速度:內(nèi)存越大,那么可以在內(nèi)存中運(yùn)行的數(shù)據(jù)也就越大,速度自然而然就快;內(nèi)存的速度從原來的幾百hz到現(xiàn)在幾千hz,決定了數(shù)據(jù)讀取存儲(chǔ)的速度。

  • 硬盤速度:傳統(tǒng)的硬盤是使用磁頭進(jìn)行尋址的,IO速度比較慢,使用了SSD的硬盤,其尋址速度大大較快。


很多系統(tǒng)的架構(gòu)設(shè)計(jì)、系統(tǒng)優(yōu)化,最終都會(huì)加上這么一句:使用SSD存儲(chǔ)解決了這些問題。


可見,硬件配置是決定一個(gè)系統(tǒng)的負(fù)載能力的最關(guān)鍵因素。


2.3 系統(tǒng)配置


一般來說,目前后端系統(tǒng)都是部署在Linux主機(jī)上的。所以拋開Win系列不談,對于Linux系統(tǒng)來說一般有以下配置關(guān)系著系統(tǒng)的負(fù)載能力。


  • 文件描述符數(shù)限制:Linux中所有東西都是文件,一個(gè)socket就對應(yīng)著一個(gè)文件描述符,因此系統(tǒng)配置的最大打開文件數(shù)以及單個(gè)進(jìn)程能夠打開的最大文件數(shù)就決定了socket的數(shù)目上限。

  • 進(jìn)程/線程數(shù)限制: 對于Apache使用的Prefork等多進(jìn)程模式,其負(fù)載能力由進(jìn)程數(shù)目所限制。對Tomcat多線程模式則由線程數(shù)所限制。

  • TCP內(nèi)核參數(shù):網(wǎng)絡(luò)應(yīng)用的底層自然離不開TCP/IP,Linux內(nèi)核有一些與此相關(guān)的配置也決定了系統(tǒng)的負(fù)載能力。


2.3.1 文件描述符數(shù)限制


  • 系統(tǒng)最大打開文件描述符數(shù):/proc/sys/fs/file-max中保存了這個(gè)數(shù)目,修改此值


  臨時(shí)性
      echo 1000000 > /proc/sys/fs/file-max
  永久性:在/etc/sysctl.conf中設(shè)置
      fs.file-max = 1000000


  • 進(jìn)程最大打開文件描述符數(shù):這個(gè)是配單個(gè)進(jìn)程能夠打開的最大文件數(shù)目??梢酝ㄟ^ulimit -n查看/修改。如果想要永久修改,則需要修改/etc/security/limits.conf中的nofile。


通過讀取/proc/sys/fs/file-nr可以看到當(dāng)前使用的文件描述符總數(shù)。另外,對于文件描述符的配置,需要注意以下幾點(diǎn):


  • 所有進(jìn)程打開的文件描述符數(shù)不能超過/proc/sys/fs/file-max

  • 單個(gè)進(jìn)程打開的文件描述符數(shù)不能超過user limit中nofile的soft limit

  • nofile的soft limit不能超過其hard limit

  • nofile的hard limit不能超過/proc/sys/fs/nr_open


2.3.2 進(jìn)程/線程數(shù)限制


  • 進(jìn)程數(shù)限制:ulimit -u可以查看/修改單個(gè)用戶能夠打開的最大進(jìn)程數(shù)。/etc/security/limits.conf中的noproc則是系統(tǒng)的最大進(jìn)程數(shù)。

  • 線程數(shù)限制

    • 可以通過/proc/sys/kernel/threads-max查看系統(tǒng)總共可以打開的最大線程數(shù)。

    • 單個(gè)進(jìn)程的最大線程數(shù)和PTHREAD_THREADS_MAX有關(guān),此限制可以在/usr/include/bits/local_lim.h中查看,但是如果想要修改的話,需要重新編譯。

    • 這里需要提到一點(diǎn)的是,Linux內(nèi)核2.4的線程實(shí)現(xiàn)方式為linux threads,是輕量級進(jìn)程,都會(huì)首先創(chuàng)建一個(gè)管理線程,線程數(shù)目的大小是受PTHREAD_THREADS_MAX影響的。但Linux2.6內(nèi)核的線程實(shí)現(xiàn)方式為NPTL,是一個(gè)改進(jìn)的LWP實(shí)現(xiàn),最大一個(gè)區(qū)別就是,線程公用進(jìn)程的pid(tgid),線程數(shù)目大小只受制于資源。

    • 線程數(shù)的大小還受線程棧大小的制約:使用ulimit -s可以查看/修改線程棧的大小,即每開啟一個(gè)新的線程需要分配給此線程的一部分內(nèi)存。減小此值可以增加可以打開的線程數(shù)目。


2.3.3 TCP內(nèi)核參數(shù)


在一臺(tái)服務(wù)器CPU和內(nèi)存資源額定有限的情況下,最大的壓榨服務(wù)器的性能,是最終的目的。在節(jié)省成本的情況下,可以考慮修改Linux的內(nèi)核TCP/IP參數(shù),來最大的壓榨服務(wù)器的性能。如果通過修改內(nèi)核參數(shù)也無法解決的負(fù)載問題,也只能考慮升級服務(wù)器了,這是硬件所限,沒有辦法的事。


netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'


使用上面的命令,可以得到當(dāng)前系統(tǒng)的各個(gè)狀態(tài)的網(wǎng)絡(luò)連接的數(shù)目。如下:


LAST_ACK 13
SYN_RECV 468
ESTABLISHED 90
FIN_WAIT1 259
FIN_WAIT2 40
CLOSING 34
TIME_WAIT 28322


這里,TIME_WAIT的連接數(shù)是需要注意的一點(diǎn)。此值過高會(huì)占用大量連接,影響系統(tǒng)的負(fù)載能力。需要調(diào)整參數(shù),以盡快的釋放time_wait連接。


一般TCP相關(guān)的內(nèi)核參數(shù)在/etc/sysctl.conf文件中。為了能夠盡快釋放time_wait狀態(tài)的連接,可以做以下配置:


  • net.ipv4.tcp_syncookies = 1 //表示開啟SYN Cookies。當(dāng)出現(xiàn)SYN等待隊(duì)列溢出時(shí),啟用cookies來處理,可防范少量SYN攻擊,默認(rèn)為0,表示關(guān)閉;

  • net.ipv4.tcp_tw_reuse = 1 //表示開啟重用。允許將TIME-WAIT sockets重新用于新的TCP連接,默認(rèn)為0,表示關(guān)閉;

  • net.ipv4.tcp_tw_recycle = 1 //表示開啟TCP連接中TIME-WAIT sockets的快速回收,默認(rèn)為0,表示關(guān)閉;

  • net.ipv4.tcp_fin_timeout = 30 //修改系統(tǒng)默認(rèn)的 TIMEOUT 時(shí)間。


這里需要注意的一點(diǎn)就是當(dāng)打開了tcp_tw_recycle,就會(huì)檢查時(shí)間戳,移動(dòng)環(huán)境下的發(fā)來的包的時(shí)間戳有些時(shí)候是亂跳的,會(huì)把帶了“倒退”的時(shí)間戳的包當(dāng)作是“recycle的tw連接的重傳數(shù)據(jù),不是新的請求”,于是丟掉不回包,造成大量丟包。另外,當(dāng)前面有LVS,并且采用的是NAT機(jī)制時(shí),開啟tcp_tw_recycle會(huì)造成一些異常,可見:http://www./?p=416。如果這種情況下仍然需要開啟此選項(xiàng),那么可以考慮設(shè)置net.ipv4.tcp_timestamps=0,忽略掉報(bào)文的時(shí)間戳即可。


此外,還可以通過優(yōu)化tcp/ip的可使用端口的范圍,進(jìn)一步提升負(fù)載能力,如下:


  • net.ipv4.tcp_keepalive_time = 1200 //表示當(dāng)keepalive起用的時(shí)候,TCP發(fā)送keepalive消息的頻度。缺省是2小時(shí),改為20分鐘。

  • net.ipv4.ip_local_port_range = 10000 65000 //表示用于向外連接的端口范圍。缺省情況下很?。?2768到61000,改為10000到65000。(注意:這里不要將最低值設(shè)的太低,否則可能會(huì)占用掉正常的端口?。?/span>

  • net.ipv4.tcp_max_syn_backlog = 8192 //表示SYN隊(duì)列的長度,默認(rèn)為1024,加大隊(duì)列長度為8192,可以容納更多等待連接的網(wǎng)絡(luò)連接數(shù)。

  • net.ipv4.tcp_max_tw_buckets = 5000 //表示系統(tǒng)同時(shí)保持TIME_WAIT的最大數(shù)量,如果超過這個(gè)數(shù)字,TIME_WAIT將立刻被清除并打印警告信息。默認(rèn)為180000,改為5000。對于Apache、Nginx等服務(wù)器,上幾行的參數(shù)可以很好地減少TIME_WAIT套接字?jǐn)?shù)量,但是對于Squid,效果卻不大。此項(xiàng)參數(shù)可以控制TIME_WAIT的最大數(shù)量,避免Squid服務(wù)器被大量的TIME_WAIT拖死。


2.4 應(yīng)用服務(wù)器配置


說到應(yīng)用服務(wù)器配置,這里需要提到應(yīng)用服務(wù)器的幾種工作模式,也叫并發(fā)策略。


  • multi process:多進(jìn)程方式,一個(gè)進(jìn)程處理一個(gè)請求。

  • prefork:類似于多進(jìn)程的方式,但是會(huì)預(yù)先fork出一些進(jìn)程供后續(xù)使用,是一種進(jìn)程池的理念。

  • worker:一個(gè)線程對應(yīng)一個(gè)請求,相比多進(jìn)程的方式,消耗資源變少,但同時(shí)一個(gè)線程的崩潰會(huì)引起整個(gè)進(jìn)程的崩潰,穩(wěn)定性不如多進(jìn)程。

  • master/worker:采用的是非阻塞IO的方式,只有兩種進(jìn)程:worker和master,master負(fù)責(zé)worker進(jìn)程的創(chuàng)建、管理等,worker進(jìn)程采用基于事件驅(qū)動(dòng)的多路復(fù)用IO處理請求。mater進(jìn)程只需要一個(gè),woker進(jìn)程根據(jù)cpu核數(shù)設(shè)置數(shù)目。


前三者是傳統(tǒng)應(yīng)用服務(wù)器Apache和Tomcat采用的方式,最后一種是Nginx采用的方式。當(dāng)然這里需要注意的是應(yīng)用服務(wù)器和nginx這種做反向代理服務(wù)器(暫且忽略nginx+cgi做應(yīng)用服務(wù)器的功能)的區(qū)別。應(yīng)用服務(wù)器是需要處理應(yīng)用邏輯的,有時(shí)候是耗cup資源的;而反向代理主要用作IO,是IO密集型的應(yīng)用。使用事件驅(qū)動(dòng)的這種網(wǎng)絡(luò)模型,比較適合IO密集型應(yīng)用,而并不適合CPU密集型應(yīng)用。對于后者,多進(jìn)程/線程則是一個(gè)更好地選擇。


當(dāng)然,由于Nginx采用的基于事件驅(qū)動(dòng)的多路IO復(fù)用的模型,其作為反向代理服務(wù)器時(shí),可支持的并發(fā)是非常大的。淘寶Tengine團(tuán)隊(duì)曾有一個(gè)測試結(jié)果是“24G內(nèi)存機(jī)器上,處理并發(fā)請求可達(dá)200萬”。


2.4.1 Nginx/Tengine


Ngixn是目前使用最廣泛的反向代理軟件,而Tengine是阿里開源的一個(gè)加強(qiáng)版Nginx,其基本實(shí)現(xiàn)了Nginx收費(fèi)版本的一些功能,如:主動(dòng)健康檢查、session sticky等。對于Nginx的配置,需要注意的有這么幾點(diǎn):


  • worker數(shù)目要和cpu(核)的數(shù)目相適應(yīng)

  • keepalive timout要設(shè)置適當(dāng)

  • worker_rlimit_nofile最大文件描述符要增大

  • upstream可以使用http 1.1的keepalive


典型配置可見:https://github.com/superhj1987/awesome-config/blob/master/nginx/nginx.conf


2.4.2 Tomcat


Tomcat的關(guān)鍵配置總體上有兩大塊:jvm參數(shù)配置和connector參數(shù)配置。


  • jvm參數(shù)配置:

  • 堆的最小值:Xms

  • 堆的最大值:Xmx

  • 新生代大小: Xmn

  • 永久代大小: XX:PermSize:

  • 永久代最大大小: XX:MaxPermSize:

  • 棧大?。?Xss或-XX:ThreadStackSize


這里對于棧大小有一點(diǎn)需要注意的是:在Linux x64上ThreadStackSize的默認(rèn)值就是1024KB,給Java線程創(chuàng)建棧會(huì)用這個(gè)參數(shù)指定的大小。如果把-Xss或者-XX:ThreadStackSize設(shè)為0,就是使用“系統(tǒng)默認(rèn)值”。而在Linux x64上HotSpot VM給Java棧定義的“系統(tǒng)默認(rèn)”大小也是1MB。所以普通Java線程的默認(rèn)棧大小怎樣都是1MB。這里有一個(gè)需要注意的地方就是java的棧大小和之前提到過的操作系統(tǒng)的操作系統(tǒng)棧大?。╱limit -s):這個(gè)配置只影響進(jìn)程的初始線程;后續(xù)用pthread_create創(chuàng)建的線程都可以指定棧大小。HotSpot VM為了能精確控制Java線程的棧大小,特意不使用進(jìn)程的初始線程(primordial thread)作為Java線程。


其他還要根據(jù)業(yè)務(wù)場景,選擇使用那種垃圾回收器,回收的策略。另外,當(dāng)需要保留GC信息時(shí),也需要做一些設(shè)置。


典型配置可見:https://github.com/superhj1987/awesome-config/blob/master/tomcat/java_opts.conf


  • connector參數(shù)配置

  • protocol: 有三個(gè)選項(xiàng):bio;nio;apr。建議使用apr選項(xiàng),性能為最高。

  • connectionTimeout:連接的超時(shí)時(shí)間

  • maxThreads:最大線程數(shù),此值限制了bio的最大連接數(shù)

  • minSpareThreads: 最大空閑線程數(shù)

  • acceptCount:可以接受的最大請求數(shù)目(未能得到處理的請求排隊(duì))

  • maxConnection: 使用nio或者apr時(shí),最大連接數(shù)受此值影響。


典型配置可見:https://github.com/superhj1987/awesome-config/blob/master/tomcat/connector.conf


一般的當(dāng)一個(gè)進(jìn)程有500個(gè)線程在跑的話,那性能已經(jīng)是很低很低了。Tomcat默認(rèn)配置的最大請求數(shù)是150。當(dāng)某個(gè)應(yīng)用擁有250個(gè)以上并發(fā)的時(shí)候,應(yīng)考慮應(yīng)用服務(wù)器的集群。


另外,并非是無限調(diào)大maxTreads和maxConnection就能無限調(diào)高并發(fā)能力的。線程越多,那么CPU花費(fèi)在線程調(diào)度上的時(shí)間越多,同時(shí),內(nèi)存消耗也就越大,那么就極大影響處理用戶的請求。受限于硬件資源,并發(fā)值是需要設(shè)置合適的值的。


對于tomcat這里有一個(gè)爭論就是:使用大內(nèi)存Tomcat好還是多個(gè)小的Tomcat集群好?(針對64位服務(wù)器以及Tomcat來說)


其實(shí),這個(gè)要根據(jù)業(yè)務(wù)場景區(qū)別對待的。通常,大內(nèi)存Tomcat有以下問題:


  • 一旦發(fā)生full gc,那么會(huì)非常耗時(shí)

  • 一旦gc,dump出的堆快照太大,無法分析


因此,如果可以保證一定程度上程序的對象大部分都是朝生夕死的,老年代不會(huì)發(fā)生gc,那么使用大內(nèi)存Tomcat也是可以的。但是在伸縮性和高可用卻比不上使用小內(nèi)存(相對來說)Tomcat集群。


使用小內(nèi)存Tomcat集群則有以下優(yōu)勢:


  • 可以根據(jù)系統(tǒng)的負(fù)載調(diào)整tc的數(shù)量,以達(dá)到資源的最大利用率,

  • 可以防止單點(diǎn)故障。


2.4.3 數(shù)據(jù)庫


  • MySQL

MySQL是目前最常用的關(guān)系型數(shù)據(jù)庫,支持復(fù)雜的查詢。但是其負(fù)載能力一般,很多時(shí)候一個(gè)系統(tǒng)的瓶頸就發(fā)生在MySQL這一點(diǎn),當(dāng)然有時(shí)候也和SQL語句的效率有關(guān)。比如,牽扯到聯(lián)表的查詢一般說來效率是不會(huì)太高的。


影響數(shù)據(jù)庫性能的因素一般有以下幾點(diǎn):


  • 硬件配置:這個(gè)無需多說

  • 數(shù)據(jù)庫設(shè)置:max_connection的一些配置會(huì)影響數(shù)據(jù)庫的連接數(shù)

  • 數(shù)據(jù)表的設(shè)計(jì):使用冗余字段避免聯(lián)表查詢;使用索引提高查詢效率

  • 查詢語句是否合理:這個(gè)牽扯到的是個(gè)人的編碼素質(zhì)。比如,查詢符合某個(gè)條件的記錄,我見過有人把記錄全部查出來,再去逐條對比

  • 引擎的選擇:myisam和innodb兩者的適用場景不同,不存在絕對的優(yōu)劣


拋開以上因素,當(dāng)數(shù)據(jù)量單表突破千萬甚至百萬時(shí)(和具體的數(shù)據(jù)有關(guān)),需要對mysql數(shù)據(jù)庫進(jìn)行優(yōu)化,一種常見的方案就是分表:


  • 垂直分表:在列維度的拆分

  • 水平分表:行維度的拆分


此外,對于數(shù)據(jù)庫,可以使用讀寫分離的方式提高性能,尤其是對那種讀頻率遠(yuǎn)大于寫頻率的業(yè)務(wù)場景。這里一般采用master/slave的方式實(shí)現(xiàn)讀寫分離,前面用程序控制或者加一個(gè)Proxy層。可以選擇使用MySQL Proxy,編寫lua腳本來實(shí)現(xiàn)基于Proxy的MySQL讀寫分離;也可以通過程序來控制,根據(jù)不同的SQL語句選擇相應(yīng)的數(shù)據(jù)庫來操作,這個(gè)也是筆者公司目前在用的方案。由于此方案和業(yè)務(wù)強(qiáng)綁定,是很難有一個(gè)通用的方案的,其中比較成熟的是阿里的TDDL,但是由于未全部開源且對其他組件有依賴性,不推薦使用。


現(xiàn)在很多大的公司對這些分表、主從分離、分布式都基于MySQL做了自己的二次開發(fā),形成了自己公司的一套分布式數(shù)據(jù)庫系統(tǒng)。比如阿里的Cobar、網(wǎng)易的DDB、360的Atlas等。當(dāng)然,很多大公司也研發(fā)了自己的MySQL分支,比較出名的就是姜承堯帶領(lǐng)研發(fā)的InnoSQL。


  • Redis


當(dāng)然,對于系統(tǒng)中并發(fā)很高并且訪問很頻繁的數(shù)據(jù),關(guān)系型數(shù)據(jù)庫還是不能妥妥應(yīng)對。這時(shí)候就需要緩存數(shù)據(jù)庫出馬以隔離對MySQL的訪問,防止MySQL崩潰。


其中,Redis是目前用的比較多的緩存數(shù)據(jù)庫(當(dāng)然,也有直接把Redis當(dāng)做數(shù)據(jù)庫使用的)。Redis是單線程基于內(nèi)存的數(shù)據(jù)庫,讀寫性能遠(yuǎn)遠(yuǎn)超過MySQL。一般情況下,對Redis做讀寫分離主從同步就可以應(yīng)對大部分場景的應(yīng)用。但是這樣的方案缺少HA,尤其對于分布式應(yīng)用,是不可接受的。目前,Redis集群的實(shí)現(xiàn)方案有以下幾個(gè):


  • Redis Cluster:這是一種去中心化的方案,是Redis的官方實(shí)現(xiàn)。是一種非?!爸亍钡姆桨福呀?jīng)不是Redis單實(shí)例的“簡單、可依賴”了。目前應(yīng)用案例還很少,貌似國內(nèi)的芒果臺(tái)用了,結(jié)局不知道如何。

  • Twemproxy:這是Twitter開源的Redis和Memcached的Proxy方案。比較成熟,目前的應(yīng)用案例比較多,但也有一些缺陷,尤其在運(yùn)維方面。比如無法平滑的擴(kuò)容/縮容,運(yùn)維不友好等。

  • Codis: 這個(gè)是豌豆莢開源的Redis Proxy方案,能夠兼容Twemproxy,并且對其做了很多改進(jìn)。由豌豆莢于2014年11月開源,基于Go和C開發(fā)?,F(xiàn)已廣泛用于豌豆莢的各種Redis業(yè)務(wù)場景。現(xiàn)在比Twemproxy快近100%。目前據(jù)我所知除了豌豆莢之外,Hulu也在使用這套方案。當(dāng)然,其升級項(xiàng)目Reborndb號稱比Codis還要厲害。


2.5 系統(tǒng)架構(gòu)


影響性能的系統(tǒng)架構(gòu)一般會(huì)有這幾方面:


  • 負(fù)載均衡

  • 同步 or 異步

  • 28原則


2.5.1 負(fù)載均衡


負(fù)載均衡在服務(wù)端領(lǐng)域中是一個(gè)很關(guān)鍵的技術(shù)??梢苑譃橐韵聝煞N:


  • 硬件負(fù)載均衡

  • 軟件負(fù)載均衡


其中,硬件負(fù)載均衡的性能無疑是最優(yōu)的,其中以F5為代表。但是,與高性能并存的是其成本的昂貴。所以對于很多初創(chuàng)公司來說,一般是選用軟件負(fù)載均衡的方案。


軟件負(fù)載均衡中又可以分為四層負(fù)載均衡和七層負(fù)載均衡。上文在應(yīng)用服務(wù)器配置部分講了nginx的反向代理功能即七層的一種成熟解決方案,主要針對的是七層http協(xié)議(雖然最新的發(fā)布版本已經(jīng)支持四層負(fù)載均衡)。對于四層負(fù)載均衡,目前應(yīng)用最廣泛的是lvs。其是阿里的章文嵩博士帶領(lǐng)的團(tuán)隊(duì)所研發(fā)的一款linux下的負(fù)載均衡軟件,本質(zhì)上是基于iptables實(shí)現(xiàn)的。分為三種工作模式:


  • NAT: 修改數(shù)據(jù)包destination ip,in和out都要經(jīng)過lvs。

  • DR:修改數(shù)據(jù)包mac地址,lvs和realserver需要在一個(gè)vlan。

  • IP TUUNEL:修改數(shù)據(jù)包destination ip和源ip,realserver需要支持ip tunnel協(xié)議。lvs和realserver不需要在一個(gè)vlan。


三種模式各有優(yōu)缺點(diǎn),目前還有阿里開源的一個(gè)FULL NAT是在NAT原來的DNAT上加入了SNAT的功能。


此外,haproxy也是一款常用的負(fù)載均衡軟件。但限于對此使用較少,在此不做講述。


2.5.2 同步 or 異步


對于一個(gè)系統(tǒng),很多業(yè)務(wù)需要面對使用同步機(jī)制或者是異步機(jī)制的選擇。比如,對于一篇帖子,一個(gè)用戶對其分享后,需要記錄用戶的分享記錄。如果你使用同步模式(分享的同時(shí)記錄此行為),那么響應(yīng)速度肯定會(huì)受到影響。而如果你考慮到分享過后,用戶并不會(huì)立刻去查看自己的分享記錄,犧牲這一點(diǎn)時(shí)效性,可以先完成分享的動(dòng)作,然后異步記錄此行為,會(huì)提高分享請求的響應(yīng)速度(當(dāng)然,這里可能會(huì)有事務(wù)準(zhǔn)確性的問題)。有時(shí)候在某些業(yè)務(wù)邏輯上,在充分理解用戶訴求的基礎(chǔ)上,是可以犧牲某些特性來滿足用戶需求的。


這里值得一提的是,很多時(shí)候?qū)τ谝粋€(gè)業(yè)務(wù)流程,是可以拆開劃分為幾個(gè)步驟的,然后有些步驟完全可以異步并發(fā)執(zhí)行,能夠極大提高處理速度。


2.5.3 28原則


對于一個(gè)系統(tǒng),20%的功能會(huì)帶來80%的流量。這就是28原則的意思,當(dāng)然也是我自己的一種表述。因此在設(shè)計(jì)系統(tǒng)的時(shí)候,對于80%的功能,其面對的請求壓力是很小的,是沒有必要進(jìn)行過度設(shè)計(jì)的。但是對于另外20%的功能則是需要設(shè)計(jì)再設(shè)計(jì)、reivew再review,能夠做負(fù)載均衡就做負(fù)載均衡,能夠緩存就緩存,能夠做分布式就分布式,能夠把流程拆開異步化就異步化。


當(dāng)然,這個(gè)原則適用于生活中很多事物。


三. 一般架構(gòu)


一般的Java后端系統(tǒng)應(yīng)用架構(gòu)如下圖所示:LVS+Nginx+Tomcat+MySql/DDB+Redis/Codis


其中,虛線部分是數(shù)據(jù)庫層,采用的是主從模式。也可以使用redis cluster(codis等)以及mysql cluster(Cobar等)來替換。


作者:颯然Hang,架構(gòu)師/后端工程師,working@中華萬年歷

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多