日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

大家先思考一個問題,這也是在面試過程中經常遇到的問題。

如果你們公司現在的產品能夠支持10W用戶訪問,你們老板突然和你說,融到錢了,會大量投放廣告,預計在1個月后用戶量會達到1000W,如果這個任務交給你,你應該怎么做?

1000W用戶的問題分解

如何支撐1000W用戶其實是一個非常抽象的問題,對于技術開發來說,我們需要一個非常明確的對于執行關鍵業務上的性能指標數據,比如,高峰時段下對于事務的響應時間、并發用戶數、QPS、成功率、以及基本指標要求等,這些都 必須要非常明確,只有這樣才能夠指導整個架構的改造和優化。所以,如果大家接到這樣一個問題,首先需要去定位到問題的本質,也就是首先得知道一些可量化的數據指標。

  • 如果有過往的相似業務交易歷史數據經驗,你需要盡量參考,處理這些收集到的原始數據(日志),從而分析出高峰時段,以及該時段下的交易行為,交易規模等,得到你想要看清楚的需求細節
  • 另外一種情況,就是沒有相關的數據指標作為參考,這個時候就需要經驗來分析。比如可以參考一些類似行業的比較成熟的業務交易模型(比如銀行業的日常交易活動或交通行業售檢票交易活動)或者干脆遵循“2/8”原則和“2/5/8”原則來直接下手實踐。當用戶能夠在2秒以內得到響應時,會感覺系統的響應很快;當用戶在2-5秒之間得到響應時,會感覺系統的響應速度還可以;當用戶在5-8秒以內得到響應時,會感覺系統的響應速度很慢,但是還可以接受;而當用戶在超過8秒后仍然無法得到響應時,會感覺系統糟透了,或者認為系統已經失去響應,而選擇離開這個Web站點,或者發起第二次請求。

在估算響應時間、并發用戶數、TPS、成功率這些關鍵指標的同時,你仍需要關心具體的業務功能維度上的需求,每個業務功能都有各自的特點,比如有些場景可以不需要同步返回明確執行結果,有些業務場景可以接受返回“系統忙,請等待!”這樣暴力的消息,以避免過大的處理流量所導致的大規模癱瘓,因此,學會平衡這些指標之間的關系是必要的,大多數情況下最好為這些指標做一個優先級排序,并且盡量只考察幾個優先級高的指標要求。(SLA服務等級)

SLA:Service-Level Agreement的縮寫,意思是服務等級協議。服務的SLA是服務提供者對服務消費者的正式承諾,是衡量服務能力等級的關鍵項。服務SLA中定義的項必須是可測量的,有明確的測量方法。

阿里P8面試官:如何設計一個扛住千萬級并發的架構?

 

并發中相關概念的解釋

在分析上述問題之前,先給大家普及一下,系統相關的一些關鍵衡量指標。

TPS

TPS(Transaction Per Second)每秒處理的事務數。

站在宏觀角度來說,一個事務是指客戶端向服務端發起一個請求,并且等到請求返回之后的整個過程。從客戶端發起請求開始計時,等到收到服務器端響應結果后結束計時,在計算這個時間段內總共完成的事務個數,我們稱為TPS。

站在微觀角度來說,一個數據庫的事務操作,從開始事務到事務提交完成,表示一個完整事務,這個是數據庫層面的TPS。

QPS

QPS(Queries Per Second)每秒查詢數,表示服務器端每秒能夠響應的查詢次數。這里的查詢是指用戶發出請求到服務器做出響應成功的次數,可以簡單認為每秒鐘的Request數量。

針對單個接口而言,TPS和QPS是相等的。如果從宏觀層面來說,用戶打開一個頁面到頁面渲染結束代表一個TPS,那這個頁面中會調用服務器很多次,比如加載靜態資源、查詢服務器端的渲染數據等,就會產生兩個QPS,因此,一個TPS中可能會包含多個QPS。

QPS=并發數/平均響應時間

阿里P8面試官:如何設計一個扛住千萬級并發的架構?

 

RT

RT(Response Time),表示客戶端發起請求到服務端返回的時間間隔,一般表示平均響應時間。

并發數

并發數是指系統同時能處理的請求數量。

需要注意,并發數和QPS不要搞混了,QPS表示每秒的請求數量,而并發數是系統同時處理的請求數量,并發數量會大于QPS,因為服務端的一個連接需要有一個處理時長,在這個請求處理結束之前,這個連接一直占用。

舉個例子,如果QPS=1000,表示每秒鐘客戶端會發起1000個請求到服務端,而如果一個請求的處理耗時是3s,那么意味著總的并發=1000*3=3000,也就是服務端會同時有3000個并發。

計算方法

上面說的這些指標,怎么計算呢?舉個例子。

假設在10點到11點這一個小時內,有200W個用戶訪問我們的系統,假設平均每個用戶請求的耗時是3秒,那么計算的結果如下:

  • QPS=2000000/60*60 = 556 (表示每秒鐘會有556個請求發送到服務端)
  • RT=3s(每個請求的平均響應時間是3秒)
  • 并發數=556*3=1668

從這個計算過程中發現,隨著RT的值越大,那么并發數就越多,而并發數代表著服務器端同時處理的連接請求數量,也就意味服務端占用的連接數越多,這些鏈接會消耗內存資源以及CPU資源等。所以RT值越大系統資源占用越大,同時也意味著服務端的請求處理耗時較長。

但實際情況是,RT值越小越好,比如在游戲中,至少做到100ms左右的響應才能達到最好的體驗,對于電商系統來說,3s左右的時間是能接受的,那么如何縮短RT的值呢?

按照2/8法則來推算1000w用戶的訪問量

繼續回到最開始的問題,假設沒有歷史數據供我們參考,我們可以使用2/8法則來進行預估。

  • 1000W用戶,每天來訪問這個網站的用戶占到20%,也就是每天有200W用戶來訪問。
  • 假設平均每個用戶過來點擊50次,那么總共的PV=1億。
  • 一天是24小時,根據2/8法則,每天大部分用戶活躍的時間點集中在(24*0.2) 約等于5個小時以內,而大部分用戶指的是(1億點擊 * 80%)約等于8000W(PV), 意味著在5個小時以內,大概會有8000W點擊進來,也就是每秒大約有4500(8000W/5小時)個請求。
  • 4500只是一個平均數字。在這5個小時中,不可能請求是非常平均的,有可能會存在大量的用戶集中訪問(比如像淘寶這樣的網站,日訪問峰值的時間點集中在下午14:00、以及晚上21:00,其中21:00是一天中活躍的峰值),一般情況下訪問峰值是平均訪問請求的3倍到4倍左右(這個是經驗值),我們按照4倍來計算。那么在這5個小時內有可能會出現每秒18000個請求的情況。也就是說,問題由原本的支撐1000W用戶,變成了一個具體的問題,就是服務器端需要能夠支撐每秒18000個請求(QPS=18000)
阿里P8面試官:如何設計一個扛住千萬級并發的架構?

 


阿里P8面試官:如何設計一個扛住千萬級并發的架構?

 

服務器壓力預估

大概預估出了后端服務器需要支撐的最高并發的峰值之后,就需要從整個系統架構層面進行壓力預估,然后配置合理的服務器數量和架構。既然是這樣,那么首先需要知道一臺服務器能夠扛做多少的并發,那這個問題怎么去分析呢?我們的應用是部署在Tomcat上,所以需要從Tomcat本身的性能下手。

下面這個圖表示Tomcat的工作原理,該圖的說明如下。

  • LimitLatch是連接控制器,它負責控制Tomcat能夠同時處理的最大連接數,在NIO/NIO2的模式中,默認是10000,如果是APR/native,默認是8192
  • Acceptor是一個獨立的線程,在run方法中,在while循環中調用socket.accept方法中接收客戶端的連接請求,一旦有新的請求過來,accept會返回一個Channel對象,接著把這個Channel對象交給Poller去處理。Poller 的本質是一個 Selector ,它同樣也實現了線程,Poller 在內部維護一個 Channel 數組,它在一個死循環里不斷檢測 Channel 的數據就緒狀態,一旦有 Channel 可讀,就生成一個 SocketProcessor 任務對象扔給 Executor 去處理
  • SocketProcessor 實現了 Runnable 接口,當線程池在執行SocketProcessor這個任務時,會通過Http11Processor去處理當前這個請求,Http11Processor 讀取 Channel 的數據來生成 ServletRequest 對象。
  • Executor 就是線程池,負責運行 SocketProcessor 任務類, SocketProcessor 的 run 方法會調用 Http11Processor 來讀取和解析請求數據。我們知道, Http11Processor 是應用層協議的封裝,它會調用容器獲得響應,再把響應通過 Channel 寫出。
阿里P8面試官:如何設計一個扛住千萬級并發的架構?

 

從這個圖中可以得出,限制Tomcat請求數量的因素四個方面。

當前服務器系統資源

我想可能大家遇到過類似“Socket/File:Can't open so many files”的異常,這個就是表示linux系統中的文件句柄限制。

在Linux中,每一個TCP連接會占用一個文件描述符(fd),一旦文件描述符超過Linux系統當前的限制,就會提示這個錯誤。

我們可以通過下面這條命令來查看一個進程可以打開的文件數量

ulimit -a 或者 ulimit -n

open files (-n) 1024 是linux操作系統對一個進程打開的文件句柄數量的限制(也包含打開的套接字數量)

這里只是對用戶級別的限制,其實還有個是對系統的總限制,查看系統總線制:

cat /proc/sys/fs/file-max

file-max是設置系統所有進程一共可以打開的文件數量 。同時一些程序可以通過setrlimit調用,設置每個進程的限制。如果得到大量使用完文件句柄的錯誤信息,是應該增加這個值。

當出現上述異常時,我們可以通過下面的方式來進行修改(針對單個進程的打開數量限制)

vi /etc/security/limits.conf
  root soft nofile 65535
  root hard nofile 65535
  * soft nofile 65535
  * hard nofile 65535
  • *代表所有用戶、root表示root用戶。
  • noproc 表示最大進程數量
  • nofile代表最大文件打開數量。
  • soft/hard,前者當達到閾值時,制作警告,后者會報錯。

另外還要注意,要確保針對進程級別的文件打開數量反問是小于或者等于系統的總限制,否則,我們需要修改系統的總限制。

vi /proc/sys/fs/file-max

TCP連接對于系統資源最大的開銷就是內存。

因為tcp連接歸根結底需要雙方接收和發送數據,那么就需要一個讀緩沖區和寫緩沖區,這兩個buffer在linux下最小為4096字節,可通過cat /proc/sys/net/ipv4/tcp_rmem和cat /proc/sys/net/ipv4/tcp_wmem來查看。

所以,一個tcp連接最小占用內存為4096+4096 = 8k,那么對于一個8G內存的機器,在不考慮其他限制下,最多支持的并發量為:810241024/8 約等于100萬。此數字為純理論上限數值,在實際中,由于linux kernel對一些資源的限制,加上程序的業務處理,所以,8G內存是很難達到100萬連接的,當然,我們也可以通過增加內存的方式增加并發量。

Tomcat依賴的JVM的配置

我們知道Tomcat是JAVA程序,運行在JVM上,因此我們還需要對JVM做優化,才能更好的提升Tomcat的性能,簡單帶大家了解一下JVM,如下圖所示。

阿里P8面試官:如何設計一個扛住千萬級并發的架構?

 

在JVM中,內存劃分為堆、程序計數器、本地方發棧、方法區(元空間)、虛擬機棧。

堆空間說明

其中,堆內存是JVM內存中最大的一塊區域,幾乎所有的對象和數組都會被分配到堆內存中,它被所有線程共享。 堆空間被劃分為新生代和老年代,新生代進一步劃分為Eden和Surivor區,如下圖所示。

阿里P8面試官:如何設計一個扛住千萬級并發的架構?

 

新生代和老年代的比例是1:2,也就是新生代會占1/3的堆空間,老年代會占2/3的堆空間。 另外,在新生代中,空間占比為Eden:Surivor0:Surivor1=8:1:1 。 舉個例子來說,如果eden區內存大小是40M,那么兩個Survivor區分別是占5M,整個新生代就是50M,然后計算出老年代的內存大小是100M,也就是說堆空間的總內存大小是150M。

可以通過 java -XX:PrintFlagsFinal -version查看默認參數

uintx InitialSurvivorRatio = 8 uintx NewRatio = 2

InitialSurvivorRatio: 新生代Eden/Survivor空間的初始比例

NewRatio : Old區/Young區的內存比例

堆內存的具體工作原理是:

  • 絕大部分的對象被創建之后,會保存在Eden區,當Eden區滿了的時候,就會觸發YGC(Young GC),大部分對象會被回收掉,如果還有活著的對象,就拷貝到Survivor0,這時Eden區被清空。
  • 如果后續再次觸發YGC,活著的對象Eden+Survivor0中的對象拷貝到Survivor1區, 這時Eden和Survivor0都會被清空
  • 接著再觸發YGC,Eden+Survivor1中的對象會被拷貝到Survivor0區,一直這么循環,直到對象的年齡達到閾值,則放入到老年代。(之所以這么設計,是因為Eden區的大部分對象會被回收)
  • Survivor區裝不下的對象會直接進入到老年代
  • 老年代滿了,會觸發Full GC。

GC標記-清除算法 在執行過程中暫停其他線程??

阿里P8面試官:如何設計一個扛住千萬級并發的架構?

 

程序計數器

程序計數器是用來記錄各個線程執行的字節碼地址等,當線程發生上下文切換時,需要依靠這個來記住當前執行的位置,當下次恢復執行后要沿著上一次執行的位置繼續執行。

方法區

方法區是邏輯上的概念,在HotSpot虛擬機的1.8版本中,它的具體實現就是元空間。

方法區主要用來存放已經被虛擬機加載的類相關信息,包括類元信息、運行時常量池、字符串常量池,類信息又包括類的版本、字段、方法、接口和父類信息等。

方法區和堆空間類似,它是一個共享內存區域,所以方法區是屬于線程共享的。

本地方發棧和虛擬機棧

Java虛擬機棧是線程私有的內存空間,當創建一個線程時,會在虛擬機中申請一個線程棧,用來保存方法的局部變量、操作數棧、動態鏈接方法等信息。每一個方法的調用都伴隨這棧幀的入棧操作,當一個方法返回之后,就是棧幀的出棧操作。

本地方法棧和虛擬機棧類似,本地方法棧是用來管理本地方法的調用,也就是native方法。

JVM內存應該怎么設置

了解了上述基本信息之后,那么JVM中內存應該如何設置呢?有哪些參數來設置?

而在JVM中,要配置的幾個核心參數無非是。

  • -Xms,Java堆內存大小
  • -Xmx,Java最大堆內存大小
  • -Xmn,Java堆內存中的新生代大小,扣除新生代剩下的就是老年代內存新生代內存設置過小會頻繁觸發Minor GC,頻繁觸發GC會影響系統的穩定性
  • -XX:MetaspaceSize,元空間大小, 128M
  • -XX:MaxMetaspaceSize,最大云空間大小 (如果沒有指定這兩個參數,元空間會在運行時根據需要動態調整。) 256M一個新系統的元空間,基本上沒辦法有一個測算的方法,一般設置幾百兆就夠用,因為這里面主要存放一些類信息。
  • -Xss,線程棧內存大小,這個基本上不需要預估,設置512KB到1M就行,因為值越小,能夠分配的線程數越多。

JVM內存的大小,取決于機器的配置,比如一個2核4G的服務器,能夠分配給JVM進程也就2G左右,因為機器本身也需要內存,而且機器上還運行了其他的進程也需要占內存。而這2G還得分配給棧內存、堆內存、元空間,那堆內存能夠得到的也就1G左右,然后堆內存還要分新生代、老年代。

Tomcat本身的配置

http://tomcat.Apache.org/tomcat-8.0-doc/config/http.html

The maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200. If an executor is associated with this connector, this attribute is ignored as the connector will execute tasks using the executor rather than an internal thread pool. Note that if an executor is configured any value set for this attribute will be recorded correctly but it will be reported (e.g. via JMX) as -1 to make clear that it is not used.

server:
  tomcat:
    uri-encoding: UTF-8
    #最大工作線程數,默認200, 4核8g內存,線程數經驗值800
    #操作系統做線程之間的切換調度是有系統開銷的,所以不是越多越好。
    max-threads: 1000
    # 等待隊列長度,默認100,
    accept-count: 1000
    max-connections: 20000
    # 最小工作空閑線程數,默認10, 適當增大一些,以便應對突然增長的訪問量
    min-spare-threads: 100
  • accept-count: 最大等待數,當調用HTTP請求數達到tomcat的最大線程數時,還有新的HTTP請求到來,這時tomcat會將該請求放在等待隊列中,這個acceptCount就是指能夠接受的最大等待數,默認100。如果等待隊列也被放滿了,這個時候再來新的請求就會被tomcat拒絕(connection refused)
  • maxThreads:最大線程數,每一次HTTP請求到達Web服務,tomcat都會創建一個線程來處理該請求,那么最大線程數決定了Web服務容器可以同時處理多少個請求。maxThreads默認200,肯定建議增加。但是,增加線程是有成本的,更多的線程,不僅僅會帶來更多的線程上下文切換成本,而且意味著帶來更多的內存消耗。JVM中默認情況下在創建新線程時會分配大小為1M的線程棧,所以,更多的線程異味著需要更多的內存。線程數的經驗值為:1核2g內存為200,線程數經驗值200;4核8g內存,線程數經驗值800。
  • maxConnections,最大連接數,這個參數是指在同一時間,tomcat能夠接受的最大連接數。對于Java的阻塞式BIO,默認值是maxthreads的值;如果在BIO模式使用定制的Executor執行器,默認值將是執行器中maxthreads的值。對于Java 新的NIO模式,maxConnections 默認值是10000。對于windows上APR/native IO模式,maxConnections默認值為8192如果設置為-1,則禁用maxconnections功能,表示不限制tomcat容器的連接數。
    maxConnections和accept-count的關系為:當連接數達到最大值maxConnections后,系統會繼續接收連接,但不會超過acceptCount的值。

1.3.4 應用帶來的壓力

前面我們分析過,NIOEndPoint接收到客戶端請求連接后,會生成一個SocketProcessor任務給到線程池去處理,SocketProcessor中的run方法會調用HttpProcessor組件去解析應用層的協議,并生成Request對象。最后調用Adapter的Service方法,將請求傳遞到容器中。

容器主要負責內部的處理工作,也就是當前置的連接器通過Socket獲取到信息之后,得到一個Servlet請求,而容器就是負責處理Servlet請求。

Tomcat使用MApper組件將用戶請求的URL定位到一個具體的Serlvet,然后Spring中的DispatcherServlet攔截到該Servlet請求后,基于Spring本身的Mapper映射定位到我們具體的Controller中。

到了Controller之后,對于我們的業務來說,才是一個請求真正的開始,Controller調用Service、Service調用dao,完成數據庫操作之后,講請求原路返回給到客戶端,完成一次整體的會話。也就是說,Controller中的業務邏輯處理耗時,對于整個容器的并發來說也會受到影響。

阿里P8面試官:如何設計一個扛住千萬級并發的架構?

 

服務器數量評估

通過上述分析,我們假設一個tomcat節點的QPS=500,如果要支撐到高峰時期的QPS=18000,那么需要40臺服務器,這四臺服務器需要通過Nginx軟件負載均衡,進行請求分發,Nginx的性能很好,官方給的說明是Nginx處理靜態文件的并發能夠達到5W/s。另外Nginx由于不能單點,我們可以采用LVS對Nginx做負載均衡,LVS(Linux VirtualServer),它是采用IP負載均衡技術實現負載均衡。

阿里P8面試官:如何設計一個扛住千萬級并發的架構?

 

通過這樣的一組架構,我們當前服務端是能夠同時承接QPS=18000,但是還不夠,再回到前面我們說的兩個公式。

  • QPS=并發量/平均響應時間
  • 并發量=QPS*平均響應時間

假設我們的RT是3s,那么意味著服務器端的并發數=18000*3=54000,也就是同時有54000個連接打到服務器端,所以服務端需要同時支持的連接數為54000,這個我們在前文說過如何進行配置。如果RT越大,那么意味著堆積的鏈接越多,而這些連接會占用內存資源/CPU資源等,容易造成系統崩潰的現象。同時,當鏈接數超過閾值時,后續的請求無法進來,用戶會得到一個請求超時的結果,這顯然不是我們所希望看到的,所以我們必須要縮短RT的值。

來源:
https://www.cnblogs.com/mic112/p/15416875.html

分享到:
標簽:架構
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定