單品頁依賴服務(wù)眾多,分布在各個部門。問題:
服務(wù)質(zhì)量沒有監(jiān)控數(shù)據(jù)
出現(xiàn)問題不能及時降級
接口調(diào)用分散化
域名重復(fù)解析,沒有長連接的優(yōu)勢
架構(gòu)總體原則
設(shè)計上無狀態(tài)
使用nginx+lua+tomcat7架構(gòu)
充分利用localcache(proxycache or shared_dict orjava guava cache)
使用localtwemproxy做redis分片,且緩存分離(重要業(yè)務(wù)與其他業(yè)務(wù)分離)
分離線程池,核心業(yè)務(wù)與非核心業(yè)務(wù)分離,且有線程池監(jiān)控和開關(guān)
異步化更新
Redis集群使用主從架構(gòu)
使用unixdomain socket減少連接數(shù)
使用keepalive長連接
考慮好開關(guān)
緩存時間、是否調(diào)用后端服務(wù)、托底(托底恢復(fù)采用指數(shù)/隨機(jī)數(shù)恢復(fù)機(jī)制)
Twemproxy+Redis
使用localtwemproxy做redis分片,且緩存分離(重要業(yè)務(wù)與其他業(yè)務(wù)分離)Redis集群使用集中式主從架構(gòu)/ 考慮復(fù)制緩沖區(qū)大小
考慮使用unix domain socket/ 套接字放內(nèi)存文件系統(tǒng)
考慮使用HashTag
Redis考慮緩存驅(qū)逐策略:maxmemory-policy allkeys-lru maxmemory-samples 10
Nginx keep alive
使用長連接,并限制長連接數(shù)量
Nginx timeout
設(shè)置超時
Nginx proxy cache
使用內(nèi)存文件系統(tǒng)進(jìn)行 Nginx Proxy Cache
注意響應(yīng)頭對cache時間的影響
Parameters of caching can also beset directly in the response header. This has higher priority than setting ofcaching time using the directive.
·The“X-Accel-Expires” header field sets caching time of a response in seconds. Thezero value disables caching for a response. If the value starts with the @ prefix,it sets an absolute time in seconds since Epoch, up to which the response maybe cached.·Ifthe header does not include the “X-Accel-Expires” field, parameters of cachingmay be set in the header fields “Expires” or “Cache-Control”.·Ifthe header includes the “Set-Cookie” field, such a response will not be cached.·Ifthe header includes the “Vary” field with the special value “*”,such a response will not be cached (1.7.7). If the header includes the “Vary”field with another value, such a response will be cached taking into accountthe corresponding request header fields (1.7.7).
數(shù)據(jù)有問題不要緩存
Nginx DNS
proxy_pass時使用Local DNS解析
可能解析到多個server(nslookup),會自動next upstream
Nginx plus支持upstream的動態(tài)解析
Nginx Gzip
根據(jù)自己需求設(shè)置gzip_comp_level、gzip_min_length、gzip_types
Nginx upstream
upstream檢查
upstream策略 ip_hash
upstream策略 hash key [consistent]
consistent_key是根據(jù)流量負(fù)載動態(tài)計算的,如根據(jù)ip計算:
local newval, err = ip_log:incr(ip, 1)
local toDelay = false
-- 單IP惡意請求 分流到固定機(jī)組
if newval > 50 then
toDelay = true
ngx_var.consistent_key = ngx_var.consistent_key .. '_' .. newval
--要在set_uri前執(zhí)行,否則執(zhí)行不到
end
Nginx Real ip
Nginx client header
限定請求頭和請求體大小,在proxy pass到后端服務(wù)時不傳輸請求頭和請求體,減少網(wǎng)絡(luò)交互。
Nginx limit
limit request
limit connection / limit rate
ip白名單/黑名單
user-agent白名單/黑名單
Token限流
漏桶算法令牌桶算法(JavaGuava rate limit)
Delay限速
參考聊聊高并發(fā)系統(tǒng)之限流特技-1、聊聊高并發(fā)系統(tǒng)之限流特技-2。
Nginx+Lua shared_dict
使用共享字典做local cache
Nginx+Lua 接口合并
請求時使用method參數(shù)表示請求哪個服務(wù)
數(shù)據(jù)過濾邏輯前置,不合法直接403(防止XSS)
封裝調(diào)用邏輯,參數(shù)順序等固定,提升緩存命中率
通過Nginx子請求(ngx.location.capture_multi)進(jìn)行合并
只對原子接口進(jìn)行Cache
通過一層代理重試或者記錄UMP日志
Nginx+Lua 記錄日志
記錄日志還可以通過
Java 架構(gòu)
異步非阻塞事件模型
從Servlet3開始支持異步模型,Tomcat7/Jetty8開始支持,相同的概念是Jetty6的Continuations。我們可以把處理過程分解為一個個的事件。
通過這種將請求劃分為事件方式我們可以進(jìn)行更多的控制。如,我們可以為不同的業(yè)務(wù)再建立不同的線程池進(jìn)行控制:
即我們只依賴tomcat線程池進(jìn)行請求的解析,對于請求的處理我們交給我們自己的線程池去完成;這樣tomcat線程池就不是我們的瓶頸,造成現(xiàn)在無法優(yōu)化的狀況。
通過使用這種異步化事件模型,我們可以提高整體的吞吐量,不讓慢速的A業(yè)務(wù)處理影響到其他業(yè)務(wù)處理。慢的還是慢,但是不影響其他的業(yè)務(wù)。
通過這種將請求劃分為事件方式我們可以進(jìn)行更多的控制。如,我們可以為不同的業(yè)務(wù)再建立不同的線程池進(jìn)行控制:
Java Tomcat
start.sh
export JAVA_OPTS='-Djava.library.path=/usr/local/lib -server -XX:-UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=80 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:MaxDirectMemorySize=512m -Xss256k -XX:NewRatio=1 -XX:SurvivorRatio=6 -Xms16384m -Xms16384m -XX:MaxPermSize=256m -Djava.awt.headless=true -Dsun.net.client.defaultConnectTimeout=60000 -Dsun.net.client.defaultReadTimeout=60000 -Djmagick.systemclassloader=no -Dnetworkaddress.cache.ttl=300 -Dsun.net.inetaddr.ttl=300 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_BASE/logs -XX:ErrorFile=$CATALINA_BASE/logs/java_error_%p.log'
-XX:+UseConcMarkSweepGC 表示使用CMS
-XX:+CMSParallelRemarkEnabled 表示并行remark
-XX:+UseCMSCompactAtFullCollection 表示在FGC之后進(jìn)行壓縮,因為CMS默認(rèn)不壓縮空間的。
-XX:CMSInitiatingOccupancyFraction=80 設(shè)置閥值為80%,默認(rèn)為68%。
-XX:SoftRefLRUPolicyMSPerMBsoftly reachable objects will remain alive for some amount of time after thelast time they were referenced. The default value is one second of lifetime perfree megabyte in the heap
-XX:NewRatio年輕代(包括Eden和兩個Survivor區(qū))與年老代的比值(不包括持久代)
-XX:SurvivorRatio Eden區(qū)與Survivor區(qū)的大小比值
server.xml
以Tomcat 6為例,其Connector有幾個關(guān)鍵配置:
BIO實(shí)現(xiàn):
acceptCount:在超過最大連接數(shù)時,可接受的排隊數(shù)量;超過這個值就直接拒絕連接;默認(rèn)100;
maxThreads:tomcat可創(chuàng)建的最大線程數(shù),沒線程處理一個請求,它決定了tomcat最大線程閥值;默認(rèn)200;
minSpareThreads:最小備用線程數(shù),即tomcat一啟動就創(chuàng)建的線程數(shù);默認(rèn)25;(使用Executor時配置)
maxQueueSize:最大備用線程數(shù),一旦創(chuàng)建的線程超過這個值tomcat就會關(guān)閉不活動的線程;默認(rèn)Integer.MAX_VALUE;(使用Executor時配置)
NIO實(shí)現(xiàn)(繼承如上的配置):
acceptorThreadCount:接受連接的線程數(shù);默認(rèn)1,可以根據(jù)CPU核數(shù)調(diào)整;如果沒有問題默認(rèn)1個即可,基本不需要改;
pollerThreadCount:運(yùn)行選擇事件的線程個數(shù);默認(rèn)每核一個;
processorCache:協(xié)議處理器緩存Http11NioProcessor對象的個數(shù),目的是提高性能,默認(rèn)200,建議其值接近maxThreads;
對于tomcat7的相關(guān)配置可以參考官網(wǎng)http://tomcat.apache.org/tomcat-7.0-doc/config/http.html;核心差不多。
Java servlet3
Java thread pool
線程池并發(fā)執(zhí)行任務(wù)獲取數(shù)據(jù)
異步更新緩存
Java cache
local cache guava
批量接口時,對單個數(shù)據(jù)進(jìn)行緩存;首先查詢單個緩存,然后對miss數(shù)據(jù)進(jìn)行批量獲取,最后合并為結(jié)果
其他
域名分區(qū):客戶端同域連接限制,進(jìn)行域名分區(qū):c.3.cn c1.3.cn c2.3.cn
充分使用CPU,比如綁定CPU核數(shù)
考慮減少連接數(shù)
考慮使用內(nèi)存文件系統(tǒng)
考慮大內(nèi)存或企業(yè)級SSD
全部使用彈性云