微服務(wù)實踐01--微服務(wù)管理25--特性開關(guān)

微服務(wù)實踐目錄,可以參見連接。

背景

之前翻譯過一篇文章《[翻譯]功能切換(又稱功能標(biāo)志)》。在這篇文章中介紹了各種需要特性開關(guān)的點,并且以Nodejs的例子展示了特性開關(guān)的一些細(xì)節(jié)。基于這片文章這里討論一下在Java上有哪些點可能會用到特性開關(guān),并進(jìn)行特性開關(guān)技術(shù)的具體討論。

特性開關(guān)的特性

在特性開關(guān)最通用的用法中有解決功能沖突、藍(lán)綠發(fā)布、新特性驗證(卡方檢驗)等功能外,特性開關(guān)還可以完成以下的幾個功能:

  • 優(yōu)雅降級
    對于在較大壓力到達(dá)系統(tǒng)中之后,可以騰空一些不重要業(yè)務(wù)的資源消耗。讓這部分資源頂?shù)礁又匾臉I(yè)務(wù)中去。可以總結(jié)為:保護(hù)高業(yè)務(wù)價值的請求,并動態(tài)丟棄其他請求。例如一個電商系統(tǒng)最主要的就是商品展示、購買流程,而客服服務(wù)、物流等是較為次要的系統(tǒng)。就可以拋棄次要系統(tǒng)專注于主要系統(tǒng)的流程保證。
    這里其實也是互聯(lián)網(wǎng)中的一個概念:服務(wù)分級。可以把一個互聯(lián)網(wǎng)服務(wù)的平臺拆分成多個層次。核心業(yè)務(wù)服務(wù)、周邊業(yè)務(wù)服務(wù)、次要業(yè)務(wù)服務(wù)這樣就可以針對不同的服務(wù)制定不同的保障策略。

  • 斷路器
    使用專用策略和自定義規(guī)則實施斷路器模式,從而可以主動關(guān)閉不可用的功能。

特性開關(guān)的層次

整個特性開關(guān)可以針對不同的層次進(jìn)行管理以滿足特性要求。對于從客戶端到服務(wù)端的方式可以定義為:設(shè)備->客戶端->用戶/用戶群->自定義策略->全站這幾種層次。每個層次上可以實現(xiàn)不同類型的功能開關(guān)功能。

  • 設(shè)備層
    對于廣泛認(rèn)知的同一個APP蘋果版和安卓班功能不同的問題可以很好的體現(xiàn)出來。
  • 客戶端
    現(xiàn)在比較流行XXX極速版。比如京東和京東極速版,抖音和抖音極速版。
  • 用戶/用戶群
    之前微信的新功能發(fā)布都是需要申請才可以進(jìn)行新功能體驗的。這一個層面就是對于不同的用戶進(jìn)行用戶的A/B測試。
  • 自定義策略
    按照地域(中國版,美國版),按照語言(中文版,英文版),按照國家法律(敏感字審查等)等等都可以進(jìn)行不同的可行開關(guān)
  • 全站
    對于未開發(fā)完成的,但是已經(jīng)合入到線上分支。進(jìn)行線上驗證的功能是很有必要做全站屏蔽的。

技術(shù)解決方案對比

現(xiàn)階段有很多框架、工具庫可以滿足特性快關(guān)的需求,這里就對這些特性開關(guān)的實現(xiàn)進(jìn)行一些對比方便在技術(shù)選型中進(jìn)行使用。

  • 功能對比
框架 位置 控制臺 返回能力 說明
FF4J 皆可 不控制 侵入性較大
Togglz 皆可 不控制 侵入性較大
piranha 皆可 不控制 Uber開源的特性開關(guān)
fitchy 皆可 可以控制 現(xiàn)階段只支持簡單的特性開關(guān)功能。
flip 皆可 多年前的代碼。例子居然是jsp的

從功能對比上來看的化只有FF4J和Togglz是處于可用狀態(tài)的。其他的幾乎都處于不可使用狀態(tài)。但是這兩個可用的還是屬于侵入性較大的工具庫,因為他們都需要自己寫if...else才可以實現(xiàn)特性開關(guān)的功能。

從上面的功能對比中可以看到只有兩個框架是可用的FF4J和Togglz。而針對這兩個框架進(jìn)行對比FF4J有739star、開發(fā)團(tuán)隊56人、最后提交代碼8天前,Togglz有586star、開發(fā)團(tuán)隊58人、最后提交代碼是2個月前。最新版的jar包是在Togglz是2018年7月發(fā)布,F(xiàn)F4J是在2020年5月發(fā)布。

FF4J和Togglz的文檔和issue處理進(jìn)度來說,F(xiàn)F4J略勝一籌。從更多功能考慮FF4J還可以支撐審計、策略開關(guān)、權(quán)限開關(guān)、監(jiān)控等。從功能和文檔完備度來說FF4J比較好一點。

  • 代碼對比
    除了以上問題后,兩種框架的代碼的例子都是侵入行非常強(qiáng)的代碼。
    FF4J:
        if (ff4j.check(FEATURE_ADMIN_ONLY)) {
            htmlPage.append("<li>THIS LINE IS SHOWN ONLY FOR PEOPLE WITH ROLE <b>ADMIN</b></li>");
        }

Togglz:

if (MyFeatures.HOT_NEW_FEATURE.isActive()) {
  // do cool new stuff here
}
  • 對性能影響
    在配置與使用特性開關(guān)的過程中如果對系統(tǒng)的性能和穩(wěn)定產(chǎn)生影響就需要關(guān)注引入的特性開關(guān)的所造成的可用性問題了。分析FF4J的開關(guān)的代碼:
FF4j.check(String featureID)

上面的方法用來檢查特性開關(guān)的檢查。它其中的代碼為:

/**
     * Elegant way to ask for flipping.
     * 
     * @param featureID
     *            feature unique identifier.
     * @param executionContext
     *            current execution context
     * @return current feature status
     */
    public boolean check(String featureID, FlippingExecutionContext executionContext) {
        Feature fp = getFeature(featureID);
        boolean flipped = fp.isEnable();

        // If authorization manager provided, apply security filter
        if (flipped && getAuthorizationsManager() != null) {
            flipped = isAllowed(fp);
        }

        // If custom strategy has been defined, delegate flipping to
        if (flipped && fp.getFlippingStrategy() != null) {
            flipped = fp.getFlippingStrategy().evaluate(featureID, getFeatureStore(), executionContext);
        }
        
        // Update current context
        flippingExecutionContext.set(executionContext);
        
        // Any access is logged into audit system
        publishCheck(featureID, flipped);

        return flipped;
    }

從這里以及其他衍生的方法中檢查幾乎沒有需要進(jìn)行計算,遠(yuǎn)程通信的內(nèi)容。所以,可以認(rèn)為它對于業(yè)務(wù)代碼的影響幾乎很小。

具體使用

真正開始使用是就會遇到各種個樣的問題,對于FF4J來說也是如此的。這里先說明FF4J的兩種使用方式。

對于系統(tǒng)特性開關(guān)來說最主要的是對開關(guān)的動態(tài)配置管理工作。這部分管理工作FF4J有兩種方式進(jìn)行支撐:web,cli。對于cli來說只能連接本地的服務(wù)中的開關(guān),對于web來說可以控制多個服務(wù)中的開關(guān)。所以選擇web方式對于稍大一點系統(tǒng)是必要的。而web中有兩種方式:

FF4J使用方式

方式1對于在SpringBoot上來說是不可用狀態(tài),因為沒有辦法將embedded web劃到一個獨立的contextpath中。因為使用服務(wù)端渲染thymeleaf時沒有辦法給ff4j和業(yè)務(wù)等配置獨立的contextpath,導(dǎo)致使用thymeleaf渲染的頁面無法加載。方式2控制的服務(wù)可以更多更完善。所以使用方式2是比選項,在進(jìn)行方式2的配置過程中需要加入:

        <ff4j.version>1.8.6</ff4j.version>

        <dependency>
            <groupId>org.ff4j</groupId>
            <artifactId>ff4j-spring-boot-starter</artifactId>
            <version>${ff4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.ff4j</groupId>
            <artifactId>ff4j-web</artifactId>
            <version>${ff4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
        </dependency>

如果不配置thymeleaf的話會報錯,所以在FF4j官方文檔的例子中不配置thymeleaf是啟動不起來的。

然后使用FF4J的注解會發(fā)現(xiàn)有很多的問題。所以自定義注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeatureFlippingAnnotation {
}

再定義注解處理類,進(jìn)行特性的管理工作。

@Aspect
@Component
@Slf4j
@ConditionalOnBean(FF4j.class)
public class FeatureFlippingAspect {
    @Autowired
    public FF4j ff4j;

    //切面
    @Around("@annotation(cn.eduplus.uc.common.flipping.FeatureFlippingAnnotation)") 
    public Object before(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("FeatureFlippingAspect before aspect");
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method method = ms.getMethod();

        String className = method.getDeclaringClass().getSimpleName();
        String ffName = className + "." + method.getName();
        log.info("FeatureFlippingAspect before aspect. ffName = " + ffName);
        if (ff4j.check(ffName)) {
            return joinPoint.proceed();
        } else {
            log.info("方法規(guī)則式攔截," + method.getName());
            return null;
        }
    }
}

使用它的方式:

public class foo {
    @FeatureFlippingAnnotation
    void bar(){
        System.out.println('bar");
    }
}

總結(jié)

FF4J的功能還以應(yīng)用于Avoid Feature Branching,Blue/Green Deployments,Canary Release,Dark Launch,Graceful degradation,Thin client application,Business Toggle,A/B Testing,Circuit Breaker。這些也可以在其他的特性開關(guān)庫中實現(xiàn),不過因為很多特性開關(guān)庫未意識到這些應(yīng)用點而放棄掉。這其實從某個方面來說就是:

思維決定認(rèn)識,認(rèn)識決定高度,高度決定人生

參考:

微服務(wù)版本分支管理與特性開關(guān)
特性開關(guān)框架選型之FF4J vs Togglz
SpringAOP整合Togglz!你的周末健身時光不再被打擾!!!
ff4j 特性開關(guān)功能開發(fā)的一些實踐理論
FF4J: Feature Toggling for Spring/Spring Boot Applications

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內(nèi)容