亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

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

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

前不久作為架構師完成了某知名快消企業的一個業務中臺建設。系統上線后,經歷了雙十一活動的流量高峰,整體運行穩定。最近有空,便將此次架構的思路,心得稍作整理在這篇博客中分享一下。不會深入每一個技術細節,而是把用到的技術、框架、工具做一個簡單的回顧,作為日后的參考。

業務架構

業務架構方面,該系統作為業務中臺,主要負責客戶資產管理,包括客戶的卡、券以及其他虛擬資產。通過對外暴露標準restful接口的方式提供服務。服務的調用方包括自有渠道的App、小程序,以及合作伙伴渠道,包括招行、阿里等。而系統本身也會通過服務網關去調用公司內部的其他業務系統接口,如通過客戶中心接口同步會員信息等。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

 

根據目前的統計,這個業務中臺,每日的服務調用量在700萬次左右,有活動時也會超過1000萬次。而大部分交易,發生在上班、午休以及下午3點左右(下午茶)的時間段內。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

由于涉及到客戶業務細節,這里對業務架構就不做詳細說明了。

技術架構

這個案例中采用了基于SpringBoot的微服務架構。結合企業自身的基礎架構設施,進行K8S容器化部署,并采用Kong API Gateway對各業務中臺暴露的API接口進行統一管理。

Kong API Gateway

隨著微服務架構在企業中的流行,原來大而全的系統被拆分為粒度較小的中臺,而系統中的大部分功能則被以restful API形式提供的服務所取代,這使得IT系統能夠更加快速地響應業務變化帶來的挑戰,但同時隨著服務的增加,如何有效管理這些服務卻成為難題。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

在一些中小型項目中,我們一般都會采用Spring Cloud的技術棧,并選擇Spring Cloud Gateway來作服務網關。然而,對于一些大型企業,則需要全局考慮服務的治理,網關性能,以及其他擴展功能。

在這個案例中,企業使用了Kong作為API網關。中臺將需要開放外部使用的API,通過網關控制臺進行注冊,添加證書,生成Auth Key供關聯方使用。

Kong具有以下一些特性,能夠很好地滿足大型組織對于服務網關的需求:

  • 開源(本案例中使用的是Kong的企業版,提供了原廠服務)
  • 亞毫秒級的響應延遲,得益于基于Nginx與OpenResty帶來的超高性能
  • 單節點25K TPS
  • 認證、授權、限流、數據轉換(此案例中會員ID被添加到請求頭中)、日志、統計分析
基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

應用架構

整個系統采用JAVA開發后端以及vue開發前端,應用部分共分為4個服務組件,全部進行容器化部署,并通過Ingress Controller負載均衡對外暴露服務:

  • 資產服務:提供客戶資產相關的服務接口
  • 資產消費者服務:MQ監聽服務,異步處理資產相關請求
  • 控制臺服務:資產管理運維類服務接口,供控制臺前端使用
  • 控制臺前端服務:使用Vue開發的控制臺前端應用(如下圖)
基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

SpringBoot

除控制臺前端外,其他三個組件均采用目前主流的java微服務框架SpringBoot 2.3.4開發(考慮到穩定性,未使用最新的2.4版本)。

本案例中,通過開發應用框架,實現了系統中數據表達形式的統一,以及標準的據轉換、校驗、消息綁定、錯誤處理等功能。架構師需要對應用框架負責,簡明、高效、統一的應用框架,能夠提升開發效率,產出標準一致的代碼,保證交付質量。

應用框架不在本文的討論范圍內,而以下一些技巧或第三方包,卻在我們構建大多數SpringBoot應用中得到使用。

####定制MyBatis 數據層框架采用MyBatis,在大型應用中MyBatis能夠幫助程序員更好地控制數據層交互,并進行調優。一般可以在applicaion.yml中配置MyBatis,但當我們需要讓MyBatis支持更多定制特性(如:多數據庫支持)時,可以通過定義SqlSessionFactory bean來實現。

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sfb = new SqlSessionFactoryBean();
        sfb.setDataSource(dataSource);
        sfb.setVfs(SpringBootVFS.class);
        Properties props = new Properties();
        props.setProperty("dialect", dataConfiguration.getDialect());
        props.setProperty("reasonable", String.valueOf(dataConfiguration.isPageReasonable()));
        PageHelper pagePlugin = new PageHelper();
        pagePlugin.setProperties(props);
        Interceptor[] plugins = {pagePlugin};
        sfb.setPlugins(plugins);

        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        sfb.setMapperLocations(resolver.getResources("classpath*:mappers/"+ dataConfiguration.getDialect()+"/*.xml"));
        sfb.setTypeAliasesPackage("com.xxx.bl.core.data.model");

        SqlSessionFactory factory = sfb.getObject();
        factory.getConfiguration().setMapUnderscoreToCamelCase(true);
//        factory.getConfiguration().addInterceptor(new CoreResultSetHandler());
        factory.getConfiguration().setCallSettersOnNulls(dataConfiguration.isCallSettersOnNulls());
        return factory;
    }
復制代碼

使用logback日志組件

采用logback日志框架,可以在logback配置文件中指定針對不同的Spring profile在不同的環境中采用不同的日志級別,并采用不同的appender。同時引入spring-cloud-starter-sleuth依賴,通過設置traceId,使整個請求全鏈路上的所有日志打印出一致的traceId,大大方便了各系統間生產問題的協同排查。另外,采用異步方式記錄日志,也有利于降低IO阻塞。

   <springProfile name="stg">
        <root level="error">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="SAVE-ERROR-TO-FILE-STG"/>
        </root>
        <logger name="org.xxx" level="error" additivity="false">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="ASYNC-SAVE-TO-FILE-STG"/>
        </logger>        
    </springProfile>
    <springProfile name="prod">
        <root level="error">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="SAVE-ERROR-TO-FILE-PROD"/>
        </root>
        <logger name="org.xxx" level="error" additivity="false">
            <appender-ref ref="ASYNC-SAVE-TO-FILE-PROD"/>
        </logger>
    </springProfile>
復制代碼

SSL加密及密碼安全

全鏈路傳輸加密已成為企業安全中必不可少的措施。通過在classpath中引入CA頒發(也可以使用自簽)的jks證書,并在application配置文件中進行簡單配置,便可實現SpringBoot應用的SSL加密。

  ssl:
    enabled: true
    key-store: classpath:xxx.net.jks
    key-store-type: JKS
    key-store-password: RUIEIoUD
    key-password: RUIEIoUD
    require-ssl: true
復制代碼

密碼以明文形式存放在配置文件中,也是不安全的。你可以jasypt加密配置文件中使用到的密碼,或者直接使用Key-Vault方案,比如本案例中會分別在微軟云環境中使用Azure Key Vault或本地IDC中使用Cyberark Conjur方案。

###同步與異步服務 我們并沒有使用Spring Webflux來支持reactive特性,因為,這會增加開發復雜度,并且Webflux雖然改善了Web容器阻塞機制,但并不能從根本上解決高并發請求到來時的阻塞問題。

在這個案例中,通過搭建了3個節點的RabbitMq鏡像集群,作為消息中間件,并通過應用框架的支持,實現了服務的同步異步切換功能。我們將對外提供的服務注冊到數據庫中,在應用啟動時,讀入redis緩存。當請求到來時,通過API code判斷該請求的響應模式:同步或異步。如果是同步請求則直接處理,而如果是異步請求,則發送到RabbitMq中,再由經過封裝的消費者組件進行異步消費,最終達到削峰的目的。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

對于開發人員來說,他們只需要關注服務的業務邏輯開發,由應用框架統一處理服務的同步,異步切換,消息發送或失敗時的異常處理,以及死信隊列的維護等工作。

Dockerfile

案例中的四個組件需要實現容器化部署,分別為SpringBoot應用與Vue應用創建Dockerfile。

典型的SpringBoot應用Dockerfile如下,一般情況下大型組織會構建私有鏡像倉庫,通過私有倉庫拉取鏡像的速度更快,能夠節省CICD的時間。

FROM openjdk:11-jre
#FROM cargo.xxx.net/library/openjdk:11-jre
ARG JAR_FILE=console-service/build/libs/*.jar
COPY ${JAR_FILE} app.jar
EXPOSE 9002
EXPOSE 9003
ENTRYPOINT [ "java", "-jar", "/app.jar" ]
復制代碼

vue應用的Dockerfile如下,同樣添加了SSL證書,進行傳輸加密:

FROM cargo.xxx.net/library/nginx:stable-alpine
COPY /dist /usr/share/nginx/html/console
COPY nginx.conf /etc/nginx/nginx.conf
ARG KEY_FILE=stg.xxx.net.key
ARG PEM_FILE=stg.xxx.net.pem
COPY ${KEY_FILE} /etc/ssl/certs/cert.key
COPY ${PEM_FILE} /etc/ssl/certs/cert.pem
EXPOSE 80
CMD [ "nginx", "-c", "/etc/nginx/nginx.conf", "-g", "daemon off;" ]
復制代碼

編寫dockerfile時有以下一些注意事項:

  • 基礎鏡像:盡可能推薦選擇官方鏡像
  • 選擇大小適中的版本:如果選擇的基礎鏡像過大,啟動后需要消耗更多的資源,影響系統性能。如果太小,則可能缺失關鍵功能。
  • 利用緩存:將dockerfile中不易變動的內容寫在dockerfile最前。

##數據庫架構 在賬戶數據上億,交易數據幾百億的系統,需要采用分庫分表方案。本案例中,采用了MyCat+MySQL的數據庫架構方案。采用mycat代理Master與Slave,可靈活進行主從切換。Slave可作為Master熱備,也同時可作為讀庫,實現讀寫分離。備庫除作為準實時的備份外,也可作為運維庫或提供大數據平臺數據抽取。

同時采用1主2從1備的雙機房設計

  • Master到Slave使用半同步方案,保證從庫數據一致性。
  • Master異常時,通過mycat切換至Slave,Slave轉換為新Master
  • Master異常恢復后,先將原Master設置為Slave,數據同步完成后,再切換回正式Master

mycat高可用

mycat采用k8s容器化運行,使用k8s service來實現mycat的負載均衡,達到mycat的集群的高可用。若mycat容器節點異常,應用自動連接到另外的mycat節點上。

對數據庫的大量操作是讀操作,一般占到所有操作70%以上。所以做讀寫分離還是很有必要的,如果不做讀寫分離,那么從庫也是一種很大的浪費。 mycat通過配置很容易做到讀寫分離,在從庫進行讀操作,提升資源利用率,在主庫進行寫操作,減低主庫壓力。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

分庫分表

  • 垂直分庫:按照功能劃分,把數據分別放到不同的數據庫和服務器。例如:賬戶、資產、交易等業務領域不同的數據分別放在不同的庫中,分散壓力、減少相互影響、降低耦合,獨立模塊獨立發布
  • 水平分庫:在垂直分庫不能滿足要求時,再對模型進行水平的 切分,將同一實體,不同范圍的數據分散到不同庫中,保持單庫數量和壓力,提升連接數,達到橫向擴展的目的。
基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

冷熱數據方案

熱數據緩存

  • 對于高頻使用的熱數據,如經常使用App的客戶信息等,適當增加數據庫query cache,提升數據庫查詢性能。
  • 在應用層使用redis等內存緩存部分高頻使用數據,降低請求響應時間,增加系統流暢度,提升客戶體驗。
  • 進行讀寫分離,使用從庫提供數據查詢的服務,提升從庫硬件資源利用率,降低主庫讀壓力,增加主庫寫性能。提升整體效率。

冷數據歸檔

  • 對于使用頻率很低或基本不使用的冷數據,如歷史交易、歷史卡券等,進行數據的歸檔,提升數據庫的性能。
  • 也可提供使用頻率較低的歷史交易查詢功能,使用備庫提供服務。
  • 對于交易類數據建議按日期進行分庫分表,每日交易分為一片或多片,對于歷史交易如1年前交易進行定期遷移和歸檔,提升數據庫性能。

DEVOPS與K8S容器化部署

####DEVOPS流水線 本案例中,通過基于jenkins的CICD平臺,將應用代碼從github代碼庫獲取,使用gradle進行構建(前端使用npm構建),通過dockerfile打成鏡像后,部署到K8S容器平臺。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

在進行持續集成的過程中,同時加入了安全檢查,合規檢查以及單元測試(SpringBoot應用使用JUnit,Vue前端應用使用Jest測試框架)的步驟,以保證每一次發布的質量。 ###ConfigMap ConfigMap用于將應用的配置信息與程序的分離,這種方式不僅可以實現應用程序被的復用,而且還可以通過不同的配置實現更靈活的功能。本案例中,SpringBoot應用在K8S部署時,便將application.yml文件以ConfigMap文件的形式進行掛載。需要注意,SpringBoot會優先讀取classpath下的配置文件,因此需要在打出springboot應用jar包時,先將配置文件排除,并通過容器啟動命令參數來制定掛載的應用配置文件。

-spring.profiles.active=prod
-spring.config.location=/config/application.yml
復制代碼

###K8S容器部署 在K8S部署平臺,可以為每一個服務指定初始的資源,以及節點數量配置。比如我們為SpringBoot應用初始配置,2core 4g的資源配置,節點數量則為20個。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

根據需要我們可以采用滾動方式對pod數量進行伸縮。而不會引起服務不可用的情況。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

另外,我們也可以利用彈性伸縮,基于某些關鍵指標,如容器的CPU使用量作為閾值,來觸發容器進行彈性伸縮。在這個案例中,通過彈性伸縮機制,在上班以及中午業務高峰時間段內,將更多pod提供給業務服務組件,而在晚上,則會將pod從業務組件收回,提供給需要跑批處理以及異步消費的服務組件。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

運維與監控

ELK

ELK是一套解決方案而不是一款軟件, 三個字母分別是三個軟件產品的縮寫。 E代表Elasticsearch,負責日志的存儲和檢索; L代表Logstash, 負責日志的收集,過濾和格式化;K代表Kibana,負責日志的展示統計和數據可視化。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

Dynatrace

Dynatrace可能是目前最優秀的應用性能管理工具(APM),它既能監控基礎設施如服務器,K8S容器,又能自動發現并監控在容器內運行的動態微服務,了解它們如何執行、相互之間如何通信,還能立即檢測出性能不佳的微服務。在我們的案例中,通過定制dashboard添加我們所需要關注的監控數據。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

Dynatrace還能自動識別服務,并提供更精細的檢測數據,為開發或運維人員定位問題,帶來了極大的幫助。

基于SpringBoot的微服務架構與K8S容器部署實踐

 

?

一些思考

  • 數據庫分庫分表方案帶來的代碼侵入問題:MyCat+MySQL雖然在物理上實現了分庫分表,但對于開發來說帶來了侵入性問題,需要為分片鍵進行特殊的表結構設計,在進行查詢時也需要額外考慮分片鍵的使用,以提升查詢效率。其他的如事務的處理,由于分庫的關系,我們不再依賴事務,而是通過數據最終一致性,以及錯誤補償等方式進行處理。
  • 未來數據庫的選型:MyCat+MySQL給數據庫運維增加了復雜性,而未來針對超大數據量級的應用,在硬件資源允許的情況下,可以考慮轉向如:TiDB這樣的NewSQL方案進行替代。
  • JVM優化:應用上線后,在高并發情況下曾偶發Long GC問題,通過分析dump文件,優化內存使用,進行了解決。另外,對于內存變化較大的應用,也可以考慮使用jdk13,并開啟ZGC。
  • 緩存優化:案例中通過redis緩存服務配置信息,每次服務響應時都需要讀取redis,這給redis造成了不小的壓力,通過引入Guava cache,在本地建立緩存副本實現多級緩存,并設定合理的失效時間,能夠顯著降低對redis的壓力。
  • 通過應用框架實現低代碼:在應用框架上的投資是非常值得的,通過將共性問題集中在應用框架中解決,可以在一定程度上實現低代碼平臺的特性。開發人員也能更專注于業務邏輯的實現。
  • 開發管理:通過讓每位開發人員充分理解應用框架,并形成解決同類問題的統一Pattern,能夠明顯提高開發效率,減少低質量代碼的產生。

今天先記錄到這里,隨著實踐的深入,相信后面還會有更多新的補充,也歡迎大家一起分享經驗。


作者:技匠
鏈接:https://juejin.cn/post/6925238390161932301

分享到:
標簽:容器 K8S
用戶無頭像

網友整理

注冊時間:

網站: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

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