證券行業已經走在“互聯網+”的前列。一是證券行業的用戶服務手段已經高度互聯網化,截至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 " daemon 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;"]