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