摘要:最近一個(gè)使用的項(xiàng)目中需要進(jìn)行性能調(diào)優(yōu)。是不允許進(jìn)入進(jìn)行操作的。如上的寫法表示和是啟用的。從開(kāi)始提供的注解。最后啟用這兩個(gè)在項(xiàng)目啟動(dòng)入口小結(jié)通過(guò)上述幾步,在項(xiàng)目啟動(dòng)時(shí)通過(guò)注解的條件判斷,實(shí)現(xiàn)不同的裝配,從而啟用不同的。
最近一個(gè)使用Spring的項(xiàng)目中需要進(jìn)行性能調(diào)優(yōu)。方式基本上是編寫新的代碼實(shí)現(xiàn)原來(lái)一樣的業(yè)務(wù)邏輯,只是實(shí)現(xiàn)方式有一些調(diào)整,例如增加cache,優(yōu)化算法等等。
一開(kāi)始大家希望直接在原有代碼基礎(chǔ)上修改,但是這樣一來(lái),就要跟上每周一次的發(fā)布節(jié)奏,一周搞定難度太大。于是決定拷貝出的package來(lái)重構(gòu)。在沒(méi)啟用之前這個(gè)package下都是dead code。這樣做的好處有幾點(diǎn):
在調(diào)優(yōu)后的code啟用前,業(yè)務(wù)至少不會(huì)受影響。
利用docker的特性,可以實(shí)現(xiàn)灰度發(fā)布,比如啟動(dòng)兩個(gè)docker,一個(gè)是老的code,一個(gè)啟用新的code,利用nginx實(shí)現(xiàn)分流。
灰度發(fā)布后發(fā)現(xiàn)有緊急bug,只需要devOps修改一點(diǎn)配置,重啟docker可以再切回老的code。
出發(fā)點(diǎn)既然要實(shí)現(xiàn)上述第三點(diǎn),也就是利用配置來(lái)實(shí)現(xiàn)切換,那么這個(gè)Enable的flag就不應(yīng)該寫到代碼里,甚至是配置文件里,因?yàn)轫?xiàng)目啟動(dòng)都是在docker中通過(guò)spring-boot的cmd直接啟動(dòng)的。DevOps是不允許進(jìn)入docker進(jìn)行操作的。
實(shí)現(xiàn)想到我們的整個(gè)部署架構(gòu)是基于Kubernetes的,可以通過(guò)修改工程的deployment.yaml文件來(lái)實(shí)現(xiàn)。原理就是deployment里面設(shè)置一個(gè)docker的Env,Key是FeatureToggle,Value可以是這樣FeatureA,FeatureB ,當(dāng)docker啟動(dòng)時(shí),JVM(Java代碼)可以通過(guò)System.getenv()來(lái)獲得環(huán)境變量,從來(lái)知道這個(gè)Feature是需要啟用還是不啟用。如上的寫法表示FeatureA和FeatureB是啟用的。
我們可以寫一個(gè)簡(jiǎn)單的接口實(shí)現(xiàn)來(lái)判斷:
public boolean isFeatureEnable(String featureName) { // 用System.getenv("FeatureToggle")讀取環(huán)境變量判斷是否包含參數(shù)的featureName // ... }進(jìn)一步使用
雖然我們有了判斷方法,但是因?yàn)轫?xiàng)目組的人都有潔癖,我們不希望代碼中到處都是
if(isFeatureEnable(featureA)) { // new code } else { // old code }
這樣實(shí)在是太ugly了。
我們需要利用spring的IoC特性來(lái)切換implementations。Spring從4.0開(kāi)始提供Conditional的注解。結(jié)合@Configuration就可以實(shí)現(xiàn)app啟動(dòng)時(shí)的不同Bean的注入。
寫一個(gè)FeatureA的Condition Class
public class FeatureACondition implements Condition{ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return isFeatureEnable("featureA") } }
再寫一個(gè)Spring的Configuration來(lái)使用這個(gè)Condition
@Configuration @Conditional(FeatureACondition.class) public class FeatureAConfiguration { @Bean(name="bizService") public BizService bizService(){ return new EnhancedBizService(); } }
當(dāng)然如果要實(shí)現(xiàn)互斥的切換,即啟用FeatureA另一個(gè)Bean就不能加載的話,那么再寫一個(gè)NotFeatureA的Configuration就可以了。
@Configuration @Conditional(NotFeatureACondition.class) public class NotFeatureAConfiguration { @Bean(name="bizService") public BizService bizService(){ return new OldBizService(); } }
這樣一來(lái),當(dāng)FeatureA啟用時(shí)BizService這個(gè)interface的實(shí)現(xiàn)就是EnhancedBizService,反之它的實(shí)現(xiàn)就是OldBizService。
當(dāng)然你在configuration上用@ComponentScan,@Import等等都是沒(méi)問(wèn)題的,在啟動(dòng)時(shí)都會(huì)最先判斷Conditional,如果不滿足spring根本不會(huì)繼續(xù)下面的掃描或者加載操作。
最后啟用這兩個(gè)Config
在項(xiàng)目啟動(dòng)入口
@SpringBootApplication @Import({NotFeatureAConfiguration.class, FeatureAConfiguration.class}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }小結(jié)
通過(guò)上述幾步,在spring項(xiàng)目啟動(dòng)時(shí)通過(guò)conditional注解的條件判斷,實(shí)現(xiàn)不同Bean的裝配,從而啟用不同的Feature。
對(duì)于Devops而言,只需要在deployment里面修改Env的內(nèi)容,再重啟deploy這個(gè)app就可以實(shí)現(xiàn)Feature Toggle了。即使你不使用Kubernetes,docker-compose也是一樣的道理。
通過(guò)修改docker-compose.yml實(shí)現(xiàn):
environment: - FeatureToggle=FeatureA,FeatureB - SESSION_SECRET
總而言之就是充分利用OO語(yǔ)言的優(yōu)勢(shì),實(shí)現(xiàn)可拔插的FeatureToggle。接下來(lái)我們還會(huì)繼續(xù)研究如何Runtime的啟用Feature,我也發(fā)現(xiàn)了一個(gè)已有的輪子togglz。如果有朋友用過(guò),歡迎反饋使用感受。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/65246.html
摘要:顧名思義,其主要作用是解析標(biāo)簽。本例中沒(méi)有用到上述的注解,所以均為。繼續(xù)追蹤這行代碼的內(nèi)部實(shí)現(xiàn)獲取的名稱調(diào)用的方法注冊(cè)過(guò)程見(jiàn)處理的別名,本例中沒(méi)有別名,不進(jìn)入循環(huán)的具體內(nèi)容有待研究,不展開(kāi)。到此為止,已經(jīng)被注冊(cè)到中。 接上篇 3 reader 注冊(cè)配置類 該 part 的起點(diǎn): public AnnotationConfigApplicationContext(Class... ann...
摘要:走向自動(dòng)裝配模式注解裝配走向自動(dòng)裝配課程介紹手動(dòng)裝配自動(dòng)裝配自動(dòng)裝配是以手動(dòng)裝配為基礎(chǔ)實(shí)現(xiàn)的手動(dòng)裝配模式注解模式注解是一種用于聲明在應(yīng)用中扮演組件角色的注解。 2.走向自動(dòng)裝配 Spring 模式注解裝配 2-1 走向自動(dòng)裝配 課程介紹 spring framework手動(dòng)裝配 spring boot自動(dòng)裝配 spring boot自動(dòng)裝配是以spring framework手動(dòng)裝...
摘要:用法先創(chuàng)建個(gè)組件,,,分別在類上加上注解。發(fā)現(xiàn)有一個(gè)屬性源碼注釋這樣說(shuō)的自動(dòng)檢測(cè)使用組件。在的方法中,表示不匹配,代表匹配。這就說(shuō)明使用注冊(cè)組件有種方式。 Spring注解應(yīng)用篇--IOC容器Bean組件注冊(cè) 這是Spring注解專題系類文章,本系類文章適合Spring入門者或者原理入門者,小編會(huì)在本系類文章下進(jìn)行企業(yè)級(jí)應(yīng)用實(shí)戰(zhàn)講解以及spring源碼跟進(jìn)。 環(huán)境準(zhǔn)備 編譯器IDEA...
摘要:這里有一個(gè)參數(shù),主要是用來(lái)指定該配置項(xiàng)在配置文件中的前綴。創(chuàng)建一個(gè)配置類,里面沒(méi)有顯式聲明任何的,然后將剛才創(chuàng)建的導(dǎo)入。創(chuàng)建實(shí)現(xiàn)類,返回的全類名。創(chuàng)建實(shí)現(xiàn)類,實(shí)現(xiàn)方法直接手動(dòng)注冊(cè)一個(gè)名叫的到容器中。前言 小伙伴們是否想起曾經(jīng)被 SSM 整合支配的恐懼?相信很多小伙伴都是有過(guò)這樣的經(jīng)歷的,一大堆配置問(wèn)題,各種排除掃描,導(dǎo)入一個(gè)新的依賴又得添加新的配置。自從有了 SpringBoot 之后,咋...
摘要:通過(guò)操作系統(tǒng)進(jìn)行條件判斷,從而進(jìn)行配置。分別對(duì)布爾,字符串和數(shù)字三種類型進(jìn)行判斷。通過(guò)指定的資源文件是否存在進(jìn)行條件判斷,比如判斷來(lái)決定是否自動(dòng)裝配組件。判斷當(dāng)前環(huán)境是否是應(yīng)用。 Spring Boot中的那些Conditional spring boot中為我們提供了豐富的Conditional來(lái)讓我們得以非常方便的在項(xiàng)目中向容器中添加Bean。本文主要是對(duì)各個(gè)注解進(jìn)行解釋并輔以代碼...
閱讀 3544·2021-09-02 09:53
閱讀 1879·2021-08-26 14:13
閱讀 2822·2019-08-30 15:44
閱讀 1405·2019-08-30 14:03
閱讀 2050·2019-08-26 13:42
閱讀 3079·2019-08-26 12:21
閱讀 1352·2019-08-26 11:54
閱讀 1959·2019-08-26 10:46