1、簡介
html
最近新上了一個營銷項目(和微信結合),後臺用的是Tomcat。開始上線的時候由於人數很少感受沒太多問題,隨着正式環境的發佈,開人有人反映服務器頁面沒法打開,連入tomcat查看時發現鏈接數已滿且CPU也用到了極限,初始的架構以下圖所示,其使用1臺tomcat和一臺數據庫服務器。前端
該業務系統主要用於微信營銷,顧客在微信上下單購買(搶)對應的商品,搶購成功後該商品(券)會自動生成條形碼保存在該用戶的註冊信息中。用戶憑券到實體店完成支付和取貨操做。由於涉及券覈銷的問題(支付完成後即時覈銷),所以該業務沒法放在雲端(覈銷的數據和實體店銷售數據需即時交互),最終只能經過本地的方案來解決。linux
首先考慮到的是將網上的鏈接經過負載均衡的方式分散來減輕服務器的壓力,這方面可使用nginx代理來實現;其次須要解決的問題是session,對比了幾種方案發現nginx內置的ip_hash策略能夠解決該問題,最終網絡的架構變成了下圖所示,在該方案中增長了4臺服務器,其中一臺nginx負載轉發,另外四臺爲新增的tomcat服務。nginx
2、安裝Nginx數據庫
Nginx的安裝配置十分簡單,我這裏實際用的是tengine版本,具體的安裝方法能夠參考」 nginx配置指南之一」。這裏須要注意的是它的編譯參數,記得它的配置文件和日誌文件的存放位置。後端
3、優化系統資源緩存
文件限制tomcat
Linux系統中文件的打開個數及單用戶最多擁有的進程數是有限制的,能夠經過「ulimit -n」或「ulimit -u」來查看,詳細的設置能夠參考「ORACLE 11G在Linux下的標準安裝方法(上)」。先修改/etc/security/limit.conf中的限制,以下圖所示。安全
內核優化服務器
內核中涉及的TCP相關的選項在大併發鏈接的狀況下也須要作相應的調整不然能夠出「TCP: time wait bucket table overflow」 的錯誤提示。具體修改/etc/sysctl.conf文件,若有特殊要求請結合實際狀況修改。具體以下所示:
tcp_max_tw_buckets 系統在同時所處理的最大 timewait sockets 數目。若是超過此數的話﹐time-waitsocket 會被當即刪除而且顯示警告信息。
ip_local_port_range 用於向外鏈接的端口範圍。
netdev_max_backlog 每一個網絡接口接收數據包的速率比內核處理這些包的速率快時,容許送到隊列的數據包的最大數目,對重負載服務器而言,該值須要調高一點。
tcp_max_orphans 處理不屬於任何進程的套接字數量,不屬於任程進程的進程就是「孤兒(orphans)進程」,在快速、大量的鏈接中這種進程會不少所以要適當的設置該參數,也能夠用來防護簡單的DoS***。
tcp_max_syn_backlog 用於記錄還沒有收到客戶端確認信息的鏈接請求的最大值。
4、優化Nginx
epoll爲linux下的必須模型,適用於2.6之後的內核版本,以下圖所示:
優化代理配置
須要注意的是「proxy_max_temp_file_size」,它主要用來設置臨時文件的最大值。當被請求的文件內容大於代理緩存的大小時,該文件會被存儲到這個臨時文件,可是若是被請求文件的內容大於這個值的時候,那麼將會從上游的服務器(被代理的服務器)上直接同步傳遞,而再也不使用代理緩存。該指令的默認值爲1GB,若是設置爲0,那麼意味着禁止使用臨時文件。
5、配置Nginx
Nginx配置以下所示,其中upstreambackend配置的是後端的tomcat應用,ip_hash表示啓用該策略,用戶的目的是爲了解決後端session不一致的問題(在nginx前端還有CDN或是局域網的環境中須慎用)。
server段配置的是轉發的路徑和端口,須要注意「proxy_set_header Host $host:8162;」的寫法。若是該變量後沒有加8162端口則實際的轉發會致使頁面沒法正常顯示。其後的兩條語句能夠參考nginx日誌的記錄內容,主要用來記錄外網實際的訪問請求。($HOST 在使用80端口的時候ok,非80端口可使用$http_host。感謝ontheway2015指點)
log_format字段用來生成指定的日誌格式文件,相應的變量對應日誌文件中的訪問記錄,能夠對照下圖來查看。
6、Nginx安全限制
隨着業務的增長,網絡鏈接的流量愈來愈大,合理的控制訪問請求及鏈接數很是重要,不然仍會出現失去響應的狀況。
7、增長IP限制功能
最簡單也最容易實現的的方式是Nginx自帶的IP訪問控制,由模塊ngx_http_limit_conn_module和來ngx_http_limit_req_module實現,經過它們能夠實現對IP地址鏈接數及服務器訪問請求數的控制。
要限制鏈接,必須先有一個容器對鏈接進行計數,在http段加入以下代碼:"zone=" 給它一個名字,能夠隨便叫,這個名字要跟下面的limit_conn 一致,$binary_remote_addr = 用二進制來儲存客戶端的地址,1m 能夠儲存 32000 個併發會話。
限制請求數的方式和限制鏈接數相似,其中「rate=10r/s」表示一秒中處理的請求爲10個,若是須要限制爲每分鐘不超過30個則表示爲「rate=30r/m」;一個具體的設定以下所示:
http { limit_req_zone$binary_remote_addr zone=one:10m rate=10r/s; limit_conn_zone$binary_remote_addr zone=two:10m; }
在server段中加入如下內容,其中「burst=5」表示同時容許超過頻率限制的請求數很少於5個;「limit_conn two 15」表示對於同一IP的鏈接數限制爲15個。
limit_req zone=one burst=5; limit_conn two 15;
後續WAF模塊的添加以及nginx相關的監控待整理。