乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      美利好車的微服務(wù)實(shí)踐

       xujin3 2018-06-17
      前言

      美麗好車的微服務(wù)實(shí)踐是基于 Spring Cloud 體系來(lái)做的,在具體的開(kāi)發(fā)過(guò)程中遇到了不少問(wèn)題,踩了不少坑,對(duì)于微服務(wù)也有了實(shí)際的切身體會(huì)和理解,而不再是泛泛而談。在整個(gè) Spring Cloud 技術(shù)棧中,基于不同職責(zé)需要,我們選擇了相應(yīng)組件來(lái)支持我們的服務(wù)化,同時(shí)配合 Swagger 和 Feign 實(shí)現(xiàn)接口的文檔化和聲明式調(diào)用,在實(shí)際開(kāi)發(fā)過(guò)程中極大地降低了溝通成本,提高了研發(fā)聯(lián)調(diào)和測(cè)試的效率。

      從應(yīng)用架構(gòu)來(lái)看,正是由于基于 Spring Cloud 來(lái)實(shí)現(xiàn),整個(gè)系統(tǒng)完全秉承了微服務(wù)的原則,無(wú)論是 Spring Cloud 組件還是業(yè)務(wù)系統(tǒng),都體現(xiàn)了服務(wù)即組件、獨(dú)立部署、去中心化的特性,由此提供了快速交付和彈性伸縮的能力。

      接下來(lái)我們基于各個(gè)組件具體介紹一下美利好車的微服務(wù)實(shí)踐,首先最基本的就是 Eureka,其承載著微服務(wù)中的服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)的職責(zé),是最基礎(chǔ)的組件,必然有高可用的要求。

      基于高可用的 Eureka 集群實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)

      美利好車在生產(chǎn)實(shí)踐中部署了一個(gè)三節(jié)點(diǎn)的 Eureka Server 的集群,每個(gè)節(jié)點(diǎn)自身也同時(shí)基于 Eureka Client 向其它 Server 注冊(cè),節(jié)點(diǎn)之間兩兩復(fù)制,實(shí)現(xiàn)了高可用。在配置時(shí)指定所有節(jié)點(diǎn)機(jī)器的 hostname 既可,即做到了配置部署的統(tǒng)一,又簡(jiǎn)單實(shí)現(xiàn)了 IP 解耦,不需要像官方示例那樣用 profile 機(jī)制區(qū)分節(jié)點(diǎn)配置。這主要是由于 Eureka 節(jié)點(diǎn)在復(fù)制時(shí)會(huì)剔除自身節(jié)點(diǎn),向其它節(jié)點(diǎn)復(fù)制實(shí)例信息,保證了單邊同步原則:只要有一條邊將節(jié)點(diǎn)連接,就可以進(jìn)行信息傳播和同步。在生產(chǎn)環(huán)境中并不要過(guò)多調(diào)整其它配置,遵循默認(rèn)的配置既可。


       服務(wù)發(fā)現(xiàn)

      作為服務(wù)提供者的 Eureka Client 必須配置 register-with-eureka 為 true,即向 Eureka Server 注冊(cè)服務(wù),而作為服務(wù)消費(fèi)者的 Eureka Client 必須配置 fetch-registry=true,意即從 Eureka Server 上獲取服務(wù)信息。如果一個(gè)應(yīng)用服務(wù)可能既對(duì)外提供服務(wù),也使用其它領(lǐng)域提供的服務(wù),則兩者都配置為 true,同時(shí)支持服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)。由于 Ribbon 支持了負(fù)載均衡,所以作為服務(wù)提供者的應(yīng)用一般都是采用基于 IP 的方式注冊(cè),這樣更靈活。


       健康檢查

      在開(kāi)發(fā)測(cè)試環(huán)境中,常常都是 standlone 方式部署,但由于 Eureka 自我保護(hù)模式以及心跳周期長(zhǎng)的原因,經(jīng)常會(huì)遇到 Eureka Server 不剔除已關(guān)停的節(jié)點(diǎn)的問(wèn)題,而應(yīng)用在開(kāi)發(fā)測(cè)試環(huán)境的啟停又比較頻繁,給聯(lián)調(diào)測(cè)試造成了不小的困擾。為此我們調(diào)整了部分配置讓 Eureka Server 能夠迅速有效地踢出已關(guān)停的節(jié)點(diǎn),主要包括在 Server 端配置關(guān)閉自我保護(hù) (eureka.server.enableSelfPreservation=false),同時(shí)可以縮小 Eureka Server 清理無(wú)效節(jié)點(diǎn)的時(shí)間間隔(eureka.server.evictionIntervalTimerInMs=1000)等方式。

      另外在 Client 端開(kāi)啟健康檢查,并同步縮小配置續(xù)約更新時(shí)間和到期時(shí)間 (eureka.instance.leaseRenewalIntervalInSeconds=10 和 eureka.instance.leaseExpirationDurationInSeconds=20)。

      健康檢查機(jī)制也有助于幫助 Eureka 判斷 Client 端應(yīng)用的可用性。沒(méi)有健康檢查機(jī)制的 Client 端,其應(yīng)用狀態(tài)會(huì)一直是 UP,只能依賴于 Server 端的定期續(xù)約和清理機(jī)制判斷節(jié)點(diǎn)可用性。配置了健康檢查的 Client 端會(huì)定時(shí)向 Server 端發(fā)送狀態(tài)心跳,同時(shí)內(nèi)置支持了包括 JDBC、Redis 等第三方組件的健康檢查,任何一個(gè)不可用,則應(yīng)用會(huì)被標(biāo)為 DOWN 狀態(tài),將不再提供服務(wù)。在生產(chǎn)環(huán)境下也是開(kāi)啟了客戶端健康檢查的機(jī)制,但沒(méi)有調(diào)節(jié)配置參數(shù)。


       Eureka 的一致性

      在 CAP 原則中,Eureka 在設(shè)計(jì)時(shí)優(yōu)先保證 AP。Eureka 各個(gè)節(jié)點(diǎn)都是平等的,幾個(gè)節(jié)點(diǎn)掛掉不會(huì)影響正常節(jié)點(diǎn)的工作,剩余的節(jié)點(diǎn)依然可以提供注冊(cè)和查詢服務(wù)。而 Eureka 的客戶端在向某個(gè) Eureka 注冊(cè)時(shí)如果發(fā)現(xiàn)連接失敗,則會(huì)自動(dòng)切換至其它節(jié)點(diǎn),只要有一臺(tái) Eureka 還在,就能保證注冊(cè)服務(wù)可用 (保證可用性),只不過(guò)查到的信息可能不是最新的 (不保證強(qiáng)一致性)。除此之外,Eureka 還有一種自我保護(hù)機(jī)制:如果在 15 分鐘內(nèi)超過(guò) 85% 的節(jié)點(diǎn)都沒(méi)有正常的心跳,那么 Eureka 就認(rèn)為客戶端與注冊(cè)中心出現(xiàn)了網(wǎng)絡(luò)故障,開(kāi)啟自我保護(hù),支持可讀不可寫。

      Eureka 為了保證高可用,在應(yīng)用存活、服務(wù)實(shí)例信息、節(jié)點(diǎn)復(fù)制等都采用了緩存機(jī)制及定期同步的控制策略,比如客戶端的定期獲?。╡ureka.client.registryFetchIntervalSeconds),實(shí)例信息的定期復(fù)制(eureka.client.instanceInfoReplicationIntervalSeconds),Server 的定期心跳檢查 (eureka.instance.leaseExpirationDurationInSeconds),客戶端定期存活心跳(eureka.instance.leaseRenewalIntervalInSeconds)等等,加強(qiáng)了注冊(cè)信息的不一致性。服務(wù)消費(fèi)者應(yīng)用可以選擇重試或者快速失敗的方式,但作為服務(wù)提供者在基于 Spirng Cloud 的微服務(wù)機(jī)制下應(yīng)當(dāng)保證服務(wù)的冪等性,支持重試。因此如果對(duì)一致性的要求較高,可以適當(dāng)調(diào)整相應(yīng)參數(shù),但明顯這樣也增加了通信的頻率,這種平衡性的考慮更多地需要根據(jù)生產(chǎn)環(huán)境實(shí)際情況來(lái)調(diào)整,并沒(méi)有最優(yōu)的設(shè)置。

      Config 的高可用及實(shí)時(shí)更新


       高可用方案

      Config 的高可用方案比較簡(jiǎn)單,只需將 Config Server 作為一個(gè)服務(wù)發(fā)布到注冊(cè)中心上,客戶端基于 Eureka Client 完成服務(wù)發(fā)現(xiàn),既可實(shí)現(xiàn)配置中心的高可用。這種方式要求客戶端應(yīng)用必須在 bootstrap 階段完成發(fā)現(xiàn)配置服務(wù)并獲取配置,因此關(guān)于 Eureka Client 的配置也必須在 bootstrap 的配置文件中存在。同時(shí)我們引入了 Spring Retry 支持重試,可多次從 Server 端拉取配置,提高了容錯(cuò)能力。另外,在啟動(dòng)階段,我們配置了 failFast=true 來(lái)實(shí)現(xiàn)快速失敗的方式檢查應(yīng)用啟動(dòng)狀態(tài),避免對(duì)于失敗的無(wú)感知帶來(lái)應(yīng)用不可用的情況。


       配置實(shí)時(shí)同步

      在實(shí)際的生產(chǎn)中,我們同時(shí)基于 Spring Cloud Bus 機(jī)制和 Kafka 實(shí)現(xiàn)了實(shí)時(shí)更新,當(dāng)通過(guò) git 提交了更新的配置文件后,基于 webhook 或者手動(dòng)向 Config Server 應(yīng)用發(fā)送一個(gè) /bus/refresh 請(qǐng)求,Config Server 則通過(guò) Kafka 向應(yīng)用節(jié)點(diǎn)發(fā)送了一個(gè)配置更新的事件,應(yīng)用接收到配置更新的事件后,會(huì)判斷該文件的 version 和 state,如果任一個(gè)發(fā)生變化,則從 Config Server 新拉取配置,內(nèi)部基于 RefreshRemoteApplicationEvent 廣播更新 RefreshScope 標(biāo)注的配置。默認(rèn)的 Kafka 的 Topic 為 springCloudbus,同時(shí)需要注意的是應(yīng)用集群的節(jié)點(diǎn)不能采用 consumer group 的方式消費(fèi),應(yīng)采用廣播模式保證每個(gè)節(jié)點(diǎn)都消費(fèi)配置更新消息。Spring CloudBus 又是基于 Spring Cloud Stream 機(jī)制實(shí)現(xiàn)的,因此配置需要按照 Steam 的方式設(shè)置。具體為:

      spring.cloud.stream.kafka.binder.brokers=ip:portspring.cloud.stream.kafka.binder.zk-nodes=ip:portspring.cloud.stream.bindings.springCloudBusInput.destination=springCloudbus.dev

      如果需要重定義 Topic 名稱,則需要如上所示進(jìn)行調(diào)整,由于多套開(kāi)發(fā)環(huán)境的存在,而 Kafka 只有一套,我們對(duì) Topic 進(jìn)行了不同環(huán)境的重定義。

      但需要注意的一點(diǎn)是,這種實(shí)時(shí)刷新會(huì)導(dǎo)致拒絕任務(wù)的異常 (RejectedExecutionException),必現(xiàn)(當(dāng)前 Edgware.RELEASE 版本)但不影響實(shí)際刷新配置,已被證實(shí)是個(gè) Bug,具體參見(jiàn) https://github.com/spring-cloud/spring-cloud-netflix/issues/2228,可簡(jiǎn)單理解為在刷新時(shí)會(huì)關(guān)閉 context 及關(guān)聯(lián)的線程池重新加載,但刷新事件又同時(shí)提交了一個(gè)新的任務(wù),導(dǎo)致拒絕執(zhí)行異常。

      Zuul 的網(wǎng)關(guān)的安全及 session

       安全處理

      針對(duì)外網(wǎng)請(qǐng)求,必然需要一個(gè)網(wǎng)關(guān)系統(tǒng)來(lái)進(jìn)行統(tǒng)一的安全校驗(yàn)及路由請(qǐng)求,Zuul 很好地支持了這一點(diǎn),在實(shí)際生產(chǎn)中,我們盡量讓 gateway 系統(tǒng)不集成任何業(yè)務(wù)邏輯,基于 EnableZuulProxy 開(kāi)啟了服務(wù)發(fā)現(xiàn)模式實(shí)現(xiàn)了服務(wù)路由。且只做安全和路由,降低了網(wǎng)關(guān)系統(tǒng)的依賴和耦合,也因此使 gateway 系統(tǒng)可以線性擴(kuò)展,無(wú)壓力和無(wú)限制地應(yīng)對(duì)流量和吞吐的擴(kuò)張。

      需要注意的是,重定向的問(wèn)題需要配置 add-host-header=true 支持;為了安全保障,默認(rèn)忽略所有服務(wù)(ignored-services='*'),基于白名單進(jìn)行路由,同時(shí)開(kāi)啟 endpoints 的安全校驗(yàn),以避免泄露信息,還要通過(guò) ignored-patterns 關(guān)閉后端服務(wù)的 endpoints 訪問(wèn)請(qǐng)求。


       Session 管理

      Zuul 支持自定義 Http Header,我們借助于該機(jī)制,實(shí)現(xiàn)了 Session 從網(wǎng)關(guān)層向后端服務(wù)的透?jìng)?。主要是基?pre 類型的 ZuulFilter,通過(guò) RequestContex.addZuulRequestHeader 方法可實(shí)現(xiàn)請(qǐng)求轉(zhuǎn)發(fā)時(shí)增加自定義 Header,后端基于 SpringMVC 的攔截器攔截處理即可。

      ZuulFilter 不像 SpringMVC 的攔截器那么強(qiáng)大,它是不支持請(qǐng)求路徑的過(guò)濾的。Zuul 也沒(méi)有集成 SpringMVC 的攔截器,這就需要我們自己開(kāi)發(fā)實(shí)現(xiàn)類似的功能。如果需要支持 SpringMVC 攔截器,只需要繼承 InstantiationAwareBeanPostProcessorAdapter 重寫初始化方法 postProcessAfterInstantiation,向 ZuulHandlerMapping 添加攔截器既可。為了支持請(qǐng)求的過(guò)濾,還可以將攔截器包裝為 MappedInterceptor,這就可以像 SpringMVC 的攔截器一樣支持 include 和 exclude。具體代碼示例如下:

      1.       public static class ZuulHandlerBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {  2.      3.        @Value('${login.patterns.include}')  4.        private String includePattern;  5.        @Value('${login.patterns.exclude}')  6.        private String excludePattern;  7.      8.        @Autowired  9.        private AuthenticateInterceptor authenticateInterceptor;  10.          11.      12.        public MappedInterceptor pattern(String[] includePatterns, String[] excludePatterns, HandlerInterceptor interceptor) {  13.            return new MappedInterceptor(includePatterns, excludePatterns, interceptor);  14.        }  15.      16.        @Override  17.        public boolean postProcessAfterInstantiation(final Object bean, final String beanName) throws BeansException {  18.            if (bean instanceof ZuulHandlerMapping) {  19.                ZuulHandlerMapping zuulHandlerMapping = (ZuulHandlerMapping) bean;  20.                String[] includePatterns = Iterables.toArray(Splitter.on(',').trimResults().omitEmptyStrings().split(includePattern), String.class);  21.                String[] excludePatterns = Iterables.toArray(Splitter.on(',').trimResults().omitEmptyStrings().split(excludePattern), String.class);  22.                zuulHandlerMapping.setInterceptors(pattern(includePatterns, excludePatterns, authenticateInterceptor));  23.            }  24.            return super.postProcessAfterInstantiation(bean, beanName);  25.        }  26.      27.    }


       關(guān)閉重試機(jī)制

      Zuul 底層是基于 Ribbon 和 Hystrix 實(shí)現(xiàn)的,因此超時(shí)配置需要注意,如果基于服務(wù)發(fā)現(xiàn)的方式,則超時(shí)主要受 Ribbon 控制。另外由于 Spring Config 引入了 Spring Retry 導(dǎo)致 Zuul 會(huì)至少進(jìn)行一次失敗請(qǐng)求的重試,各種開(kāi)關(guān)配置都不生效,最后通過(guò)將 Ribbon 的 MaxAutoRetries 和 MaxAutoRetriesNextServer 同時(shí)設(shè)置為 0,避免了重試。在整個(gè)微服務(wù)調(diào)用中,由于不能嚴(yán)格保證服務(wù)的冪等性,我們是關(guān)閉了所有的重試機(jī)制的,包括 Feign 的重試,只能手動(dòng)進(jìn)行服務(wù)重試調(diào)用,以確保不會(huì)產(chǎn)生臟數(shù)據(jù)。

      基于 Sleuth 的服務(wù)追蹤

      Zipkin 是大規(guī)模分布式跟蹤系統(tǒng)的開(kāi)源實(shí)現(xiàn),基于 2010 年 Google 發(fā)表的 Dapper 論文開(kāi)發(fā)的,Spring Cloud Sleuth 提供了兼容 Zipkin 的實(shí)現(xiàn),可以很方便地集成,提供了較為直觀的可視化視圖,便于人工排查問(wèn)題。美利好車系統(tǒng)在實(shí)際的生產(chǎn)實(shí)踐中,將日志同步改為適用于 Zipkin 格式的 pattern,這樣后端 ELK 組件日志的收集查詢也兼容,基于 traceId 實(shí)現(xiàn)了服務(wù)追蹤和日志查詢的聯(lián)動(dòng)。

      在日志的上報(bào)和收集上我們?nèi)匀换?spring-cloud-starter-bus-kafka 來(lái)實(shí)現(xiàn)。

      Swagger 支持的接口文檔化和可測(cè)性

      在前后端分離成為主流和現(xiàn)狀的情況下,前后端就接口的定義和理解的不一致性成為開(kāi)發(fā)過(guò)程中效率的制約因素,解決這個(gè)問(wèn)題可以幫助前后端團(tuán)隊(duì)很好地協(xié)作,高質(zhì)量地完成開(kāi)發(fā)工作。我們?cè)趯?shí)際開(kāi)發(fā)過(guò)程中使用了 Swagger 來(lái)生成在線 API 文檔,讓 API 管理和使用變得極其簡(jiǎn)單,同時(shí)提供了接口的簡(jiǎn)單測(cè)試能力。雖然這帶來(lái)了一定的侵入性,但從實(shí)際生產(chǎn)效率來(lái)說(shuō)遠(yuǎn)超出了預(yù)期,因此也特別予以強(qiáng)調(diào)和推薦。

      實(shí)際開(kāi)發(fā)過(guò)程中,我們?nèi)匀惶峁┝?API 的 SDK 讓調(diào)用方接入,雖然這個(gè)方式是微服務(wù)架構(gòu)下不被推崇的,但現(xiàn)階段我們認(rèn)為 SDK 可以讓調(diào)用 API 更簡(jiǎn)單、更友好。版本問(wèn)題基于 Maven 的 snapshot 機(jī)制實(shí)現(xiàn)實(shí)時(shí)更新,唯一需要注意的是要保證向后兼容。

      以上就是美利好車系統(tǒng)微服務(wù)實(shí)施的一些實(shí)踐,有些地方可能不是特別恰當(dāng)和正確,但在當(dāng)前階段也算基本滿足了開(kāi)發(fā)需要,而且我們秉承擁抱變化的態(tài)度,對(duì)整個(gè)體系結(jié)構(gòu)也在持續(xù)進(jìn)行改善和優(yōu)化,積極推動(dòng)美利好車架構(gòu)的演進(jìn),希望能更好地支持美利好車的業(yè)務(wù)需求。


       作者介紹

      王文堯,曾在京東等多家知名互聯(lián)網(wǎng)電商領(lǐng)域公司任職,也創(chuàng)業(yè)做過(guò)垂直電商平臺(tái),現(xiàn)任美利金融好車技術(shù)部架構(gòu)師。對(duì)電商領(lǐng)域的業(yè)務(wù)比較了解,同時(shí)對(duì)敏捷、領(lǐng)域建模、高并發(fā)高可用的分布式系統(tǒng)設(shè)計(jì)及服務(wù)化等方面有較為深入的研究和實(shí)踐。


       More

      P2P如何將視頻直播帶寬降低75%?

      阿里盒馬領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)實(shí)踐

       其它

      2017 年軟件研發(fā)領(lǐng)域有很多新的變化,比如 Java 9 正式發(fā)布;Kotlin 得到 Google Android 正式支持;Spark、Kafka 等框架紛紛引入流式計(jì)算能力;AI 技術(shù)蓬勃發(fā)展等等。

      新一年的技術(shù)新趨勢(shì) QCon 全球軟件開(kāi)發(fā)大會(huì)也與你一同關(guān)注。目前,我們已經(jīng)確認(rèn)多位技術(shù)專家:Netflix 工程總監(jiān) Katharina Probst、Kotlin 團(tuán)隊(duì)工程師 Roman Elizarov、Apache Spark Structured Streaming 的核心開(kāi)發(fā)人員朱詩(shī)雄、愛(ài)奇藝科學(xué)家李典等老師將在現(xiàn)場(chǎng)分享前沿技術(shù)案例,共呈技術(shù)盛宴。

      2018 北京站現(xiàn)在報(bào)名享 7 折優(yōu)惠,立減 2040 元。有任何問(wèn)題可咨詢購(gòu)票經(jīng)理 Hanna,電話:15110019061,微信:qcon-0410。


        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多