作者簡介:楊濤,廣發證券交易雲技術研發團隊負責人,資深架構師,在證券行業有超過9年的工作經驗。目前緻力于廣發證券OpenTrading證券交易雲核心技術研發。
責編:魏偉,本文轉載自《程式員》,謝絕轉載,更多技術文章,請訂閱《程式員》,歡迎投稿,郵箱[email protected]
證券行業已經走在“網際網路+”的前列。一是證券行業的使用者服務手段已經高度網際網路化,截至2014年底,我國證券行業網上交易量占比已經超過90%;二是網際網路證券試點工作取得了積極成果,截至2015年5月,已有55家證券公司開展網際網路證券業務試點,在證券支付體系、賬戶體系、移動應用、跨界合作等方面進行了有益探索,網際網路對于證券行業的影響正在持續擴大;三是證券行業網際網路化基礎設施建設取得顯著成效,機構間私募産品報價與服務系統、場外證券業務清算機構、場外證券業務備案系統、證券行業支付體系、證券行業雲平台、征信體系、證聯網等基礎設施的籌建和使用,為證券行業的網際網路化奠定了發展基礎。
2014年可謂證券行業的“網際網路化元年”,作為證券行業網際網路化的先行者,廣發證券通過一系列變革積累了豐富的創新經驗。目前,證券行業創新轉型程序不斷加快,網際網路金融的迅速崛起更是加劇了行業競争和洗牌,也為有實力的券商做大做強提供了曆史機遇。作為植根廣東的知名證券公司,廣發證券始終堅持“創新驅動、轉型發展”,圍繞券商基礎功能建設加快組織創新、業務創新和産品創新,努力打造核心競争力,也為行業提供了值得借鑒的創新模闆。
概述
我們的平台邏輯層次上分為四層結構,分别為:接入控制層、業務前置層、交易總線層、虛拟化/容器化層。每一層我們在技術上都采用基于異步高性能消息流水線的體系結構。平台在架構上支援多開發語言接入,所用的開發語言包括Java、Go、Nodejs、Lua、C++等。
圖1,opentrading平台邏輯架構
我們從2013年左右開始研究docker的,生産環境從最初的docker-1.3.2用到目前docker-1.10.0,一直在不斷增加基于docker的部署。2014年開始嘗試在生産環境使用docker,2015年開始大規模使用。
目前我們生産環境使用的docker執行個體個數:
- 行情雲:超過4000個執行個體,分布在6個IDC機房。目前承載實時并發超過30萬,整個行情雲每秒的吞吐在1.5Gbps左右, 目前服務客戶超過200萬。
- 交易雲:超過300個執行個體,主要分布在廣州同城中心交易機房。目前承載客戶DMA接入,每天的交易請求數在100萬以上,每日交易額平均在8億左右,最高的峰值超過30億。
為什麼要容器化
對傳統的垂直行業來講,Docker也是最近幾年才出來的技術,技術理念非常先進,是以采用Docker容器化技術對我們而言需要綜合的評估,但是我們為什麼要去做呢?首先,從行業現狀來說,證券行業一方面量化交易、高頻交易、實時風控要求高,其次,行業創新非常多,創新業務也很頻繁,另外,監管方面,證監會證監局對我們要求交易事故零容忍,當然,最近幾年網際網路金融發展非常快,衆籌、P2P非常多,再次,天量行情,2014年底到去年,最高一天有兩萬億的市場行情,這樣的話對我們整個交易系統是非常大的挑戰。
我們在業務發展過程中一直團繞我們的就是怎樣利用有限的資源去支撐業務創新,真正做到IT引領業務;另一方面,我們和其他大型的網際網路公司在資源方面是沒有辦法比的,是以怎樣利用有限的資源支撐業務創新,這些都是我們要考慮的事情。
在使用容器化技術之前,我們遇到一些比較典型的痛點:
- 以項目為機關部署系統:一個項目采購一批機器,分别各自部署,每個項目之間的機器互相孤立,做不到資源共享。追成極大資源浪費。
- 傳統的交易系統更新是非常困難的,例如,要更新要有一個背景資料表,因為表的資料量非常大,是以這個更新基本上是隻能在周末更新,更新時間要1個或幾個小時。
- 還有交易系統要更新要打更新檔,在系統裡面更新一個更新檔,把更新檔放上去,更新檔打的越多導緻生産環境的系統的版本變得不可維護,不敢随便去做改動或重新部署。
- 測試環境搭建非常耗時,快速部署非常困難。
- 系統在大的更新完後基本是不可回退的。
- 行業烏龍指等黑天鵝事件時有發生,根本的原因就是技術系統實時風控速度達不到業務的要求,冒險把比較耗時的風控去掉。
容器化技術很好的解決了我們上面所遇到的問題,因為采用容器化至少有以下幾個方面的好處:
① 輕量的引擎,高效虛拟化
② 秒級部署,輕松遷移和擴充
③ 易于移植、彈性伸縮,簡單管理
④ 開始具備一點“雲”的能力
⑤ 讓微服務成為可能
⑥ 标準化的伺服器端傳遞物
⑦ 向DevOps邁進的重要一步
容器技術與雲的落地
- Docker絕對不是一個虛拟機,而且它也不是幹這個事的,我們的了解是Docker其實就是一個程序的替代者。
- 廣義講,雲其實就是一個單機多程序的跨網絡多程序的延伸,要實作雲肯定要實作對資源對程序進行遠端編排跟排程,我們認為這構成雲的基礎。
舉一個簡單的監控服務例子,一個基于statsd完備的監控服務需要有influxdb、grafana、statsd三個服務組成,每個服務隻是一個單一的功能,單純的一個服務是不能提供監控服務的,要把它提供成一個服務,肯定要組合起來,是以我們是通過compose檔案把三個服務組成一個關系,這樣就是一個完整的服務。
1. influxdb:
2. image: "docker.gf.com.cn/gfcloud/influxdb:0.9"
3. ports:
4. - "8083:8083"
5. - "8086:8086"
6. expose:
7. - "8090"
8. - "8099"
9. volumes:
10. - "/var/monitor/influxdb:/data"
11. environment:
12. - "PRE_CREATE_DB=influxdb"
13. - "ADMIN_USER=root"
14. - "INFLUXDB_INIT_PWD=root"
15. grafana:
16. image: "docker.gf.com.cn/gfcloud/grafana"
17. ports:
18. - "3000:3000"
19. volumes:
20. - "/var/monitor/grafana:/var/lib/grafana"
21. statsd:
22. image: "docker.gf.com.cn/gfcloud/statsd"
23. ports:
24. - "8125:8125/udp"
25. links:
26. - "influxdb:influxdb"
27. volumes:
28. - "/var/monitor/statsd/log:/var/log"
29. environment:
30. - INFLUXDB_HOST=influxdb
31. - INFLUXDB_PORT=8086
32. - INFLUXDB=influxdb
33. - INFLUXDB_USERNAME=root
34. - INFLUXDB_PASSWORD=root
對于容器編排,可以從以下兩個方面了解。
- 容器編排是跨主機去管理多個叢集Container的一種行為,随着Docker的發展,生态圈越來越完善,比較常見的Kubernetes、Mesos + Mathon、Rancher等都屬于此類範疇。
- 容量編排是為了将資源使用率最大化,同時均衡系統因容錯需要不斷變化的需求。
還有排程,雲要落地必須要對資源進行排程,這個其實也不難了解,舉個例子,我們每年的春運,鐵道局都會對客流很大的路線增加臨時列車,以防止出現乘客滞留。對我們應用也是這樣的類似情況,比如說我們交易系統的一個登入服務,這個服務現在資源利用比較高,有可能出現瓶頸了,這個時候就要想辦法多部署一套登入服務,是以排程的話其實就是要發現一些存在潛在的資源瓶頸的節點,你要想辦法排程一下,再拉取一套系統提供服務。
圖2,容器編排的技術演進
透明部署之應用要感覺雲
雲要落地,對我們的應用也是有要求的,應用一開始設計的時候就要容錯,寫的應用可以容忍當機,應用要有可伸縮,盡量做到無狀态,能夠做到透明部署。
應用服務就像一個樂高玩具,每一個元件都有不同的功能,不管怎麼部署,怎麼組合,可以把樂高玩具可以組成一個民房,也可以組合成大廈,對樂高玩具的元件來講,功能是一樣的,不管你怎麼組合怎麼部署,房子也好大廈也好,應用本身是不知道的,是以應用設計的時候也是這樣子的,一定不要對部署有任何的要求,是以我們是這樣想的,對部署是不能做要求的,這樣才符合雲的一些要素。
圖3,容器與樂高玩具類比
交易雲平台的架構
圖4,opentrading平台技術架構
虛拟化部署
我們的目标是把整個平台搭建在私有雲上,并在多個IDC複制部署。目前我們尚未實作IaaS,故目前僅是通過虛拟化技術在實體機上建構虛拟機資源層,通過工具把本平台的各部件的部署變成可重複和自動化。另外,對資料分片、伺服器負載均衡等做了設計,例如采用一定的consistent hash算法,讓例如Redis服務在其底層虛拟機數量一定的情況下,擴充實體機資源達到擴容目的。
圖5、容器管理及部署
如果一個“私有雲”是一個部署單元(包含整個平台所有子產品、服務)的話,上圖則是簡略的一覽圖,我們所有的應用都是基于Docker Container,采用的是最小化的Container,一個服務就一個Container,是以生産環境,在主機伺服器上面會跑無數個Container來提供服務,一個Container等同于一個APP提供的服務,我們的Docker通過Rancher開源容器管理平台來管理。
集中與分散部署結合
圖6,集中與分散部署場景
對于金融行業來說,其業務需求對比其它行業,甚至證券行業對銀行、保險等金融行業,都具有更高的要求。主要展現在:
①、高時效性,證券市場瞬息萬變,幾秒鐘的時間差可能導緻結果的巨大差異;
②、高一緻性要求,重要資料在不同節點應表現一緻性,如客戶的資金和委托資料;
③、高可用性,哪怕是分鐘級别的系統服務中斷都是不可接受的;
基于以上三點,簡單的集中部署方案和傳統的分布部署方案均已經不能滿足要求,需要集中與分布部署相結合:
重要業務資料集中部署,以實作高一緻性要求,如客戶的資産資訊、委托資訊等,客戶無論從哪個管道接入,檢視到的所有資訊都是一緻的。
行情和資訊以及一些靜态資源分布部署到離客戶最近的網際網路接入中心 (IDC),以解決網際網路客戶“最後一公裡”問題。這樣可以實作資料的高時效性(如行情資料,這顯然是很重要的),有效提升客戶使用體驗。
多個IDC接入中心具有互備功能,假如其中一個接入中心因為不可抗力導緻服務終止,可通過DNS域名切換到其它可用的IDC接入,以保證服務的持續性。
容器技術與雲的最佳實踐
不可變運維
因為有了容器技術,使得我們在管理變更,自動化部署方面有了可能,生産系統随着時間的推移,無論如何伺服器都會積攢下許多變更,包括:新應用、更新、配置變更、計劃任務,以及問題的修正。有一點是毫無疑問的:配置好的伺服器運作時間越長久,它就越有可能處于未知狀态。對于前面所述的每次變更,不可變運維将通過重新建立新的容器執行個體來解決确定伺服器狀态的問題。這樣之前我們提到的更新打更新檔的一系列痛點問題都得到很好的解決。
不可變,顧名思義就是一旦建立,便不再修改,以下是我們生産實踐在使用Docker容器方面的一些原則:
①、容器一旦執行個體化後,永不改變
②、服務的變更(更新,降級,修改配置)都通過重新部署實作
③、不修改容器的内部
Docker最佳實踐
①. 除了持久存儲外,不用映射外部檔案
特别是日志檔案,不通過映射外部檔案的方式,可以通過flume、kafka等接口把日志資料寫入到集中地方。
②.不要使用本地網絡
不使用”Host”模式,Host模式會污染主控端,同時也不符合雲計算
③.鏡像使用标簽,抛棄Latest
生産應用中一律使用Tag來辨別應用,不使用Latest,因為使用Latest将無法實作復原。
④.Build編譯應用和Build Image分離
使用專用的編譯Docker來編譯應用本身,如用Maven、Go、C++的image來編譯應用。編譯後再把應用通過Dockerfile加到服務Image裡面。
⑤.Apt-get安裝Package用完即删
如下圖的例子,Apt-get在一條指令裡面寫完,因為Docker是分層存儲,如果是在另一個RUN指令裡面解除安裝臨時軟體包,對Docker的Images的大小減小沒有幫助。
⑥.Docker内部不要Daemon
服務在Docker内部不要有守護程序,應用挂掉就讓它挂掉。通過外部監控來實作應用重新開機等操作。
1. FROM docker.gf.com.cn/gfcloud/ubuntu
2. RUN echo "deb http://nginx.org/packages/ubuntu/ trusty nginx" >> /etc/apt/sources.list && \
3. echo "deb-src http://nginx.org/packages/ubuntu/ trusty nginx" >>/etc/apt/sources.list
4. RUN apt-get update && apt-get install -y wget \
5. && wget http://nginx.org/keys/nginx_signing.key && apt-key add nginx_signing.key \
6. && apt-get update && apt-get install -y nginx \
7. && rm -rf /var/lib/apt/lists/* \
8. && echo "\ndaemon off;" >> /etc/nginx/nginx.conf \
9. && apt-get purge -y --auto-remove wget
10. # chown -R www-data:www-data /var/lib/nginx
11.
12. # Define mountable directories.
13. VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx", "/var/www/html"]
14.
15. # Define working directory.
16. WORKDIR /etc/nginx
17.
18. # Define default command.
19.
20. # Expose ports.
21. EXPOSE 80
22. EXPOSE 443
23. CMD ["nginx","-g","daemon off;"]
CSDN Docker技術微信專家群已經建立,彙聚容器技術頂級專家,歡迎微信搜尋“k15751091376”,由專人拉入。