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

微服務(wù)實(shí)踐目錄,可以參見(jiàn)連接浴鸿。

背景

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

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

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

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

  • 斷路器
    使用專(zhuān)用策略和自定義規(guī)則實(shí)施斷路器模式娩缰,從而可以主動(dòng)關(guān)閉不可用的功能灸撰。

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

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

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

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

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

  • 功能對(duì)比
框架 位置 控制臺(tái) 返回能力 說(shuō)明
FF4J 皆可 不控制 侵入性較大
Togglz 皆可 不控制 侵入性較大
piranha 皆可 無(wú) 不控制 Uber開(kāi)源的特性開(kāi)關(guān)
fitchy 皆可 無(wú) 可以控制 現(xiàn)階段只支持簡(jiǎn)單的特性開(kāi)關(guān)功能曲楚。
flip 皆可 無(wú) 多年前的代碼厘唾。例子居然是jsp的

從功能對(duì)比上來(lái)看的化只有FF4J和Togglz是處于可用狀態(tài)的。其他的幾乎都處于不可使用狀態(tài)龙誊。但是這兩個(gè)可用的還是屬于侵入性較大的工具庫(kù)抚垃,因?yàn)樗麄兌夹枰约簩?xiě)if...else才可以實(shí)現(xiàn)特性開(kāi)關(guān)的功能。

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

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

  • 代碼對(duì)比
    除了以上問(wèn)題后铁坎,兩種框架的代碼的例子都是侵入行非常強(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
}
  • 對(duì)性能影響
    在配置與使用特性開(kāi)關(guān)的過(guò)程中如果對(duì)系統(tǒng)的性能和穩(wěn)定產(chǎn)生影響就需要關(guān)注引入的特性開(kāi)關(guān)的所造成的可用性問(wèn)題了。分析FF4J的開(kāi)關(guān)的代碼:
FF4j.check(String featureID)

上面的方法用來(lái)檢查特性開(kāi)關(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;
    }

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

具體使用

真正開(kāi)始使用是就會(huì)遇到各種個(gè)樣的問(wèn)題,對(duì)于FF4J來(lái)說(shuō)也是如此的买羞。這里先說(shuō)明FF4J的兩種使用方式袁勺。

對(duì)于系統(tǒng)特性開(kāi)關(guān)來(lái)說(shuō)最主要的是對(duì)開(kāi)關(guān)的動(dòng)態(tài)配置管理工作。這部分管理工作FF4J有兩種方式進(jìn)行支撐:web畜普,cli期丰。對(duì)于cli來(lái)說(shuō)只能連接本地的服務(wù)中的開(kāi)關(guān),對(duì)于web來(lái)說(shuō)可以控制多個(gè)服務(wù)中的開(kāi)關(guān)吃挑。所以選擇web方式對(duì)于稍大一點(diǎn)系統(tǒng)是必要的钝荡。而web中有兩種方式:

FF4J使用方式

方式1對(duì)于在SpringBoot上來(lái)說(shuō)是不可用狀態(tài),因?yàn)闆](méi)有辦法將embedded web劃到一個(gè)獨(dú)立的contextpath中儒鹿。因?yàn)槭褂梅?wù)端渲染thymeleaf時(shí)沒(méi)有辦法給ff4j和業(yè)務(wù)等配置獨(dú)立的contextpath化撕,導(dǎo)致使用thymeleaf渲染的頁(yè)面無(wú)法加載几晤。方式2控制的服務(wù)可以更多更完善约炎。所以使用方式2是比選項(xiàng),在進(jìn)行方式2的配置過(guò)程中需要加入:

        <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的話會(huì)報(bào)錯(cuò),所以在FF4j官方文檔的例子中不配置thymeleaf是啟動(dòng)不起來(lái)的圾浅。

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

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

再定義注解處理類(lèi)拯勉,進(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。這些也可以在其他的特性開(kāi)關(guān)庫(kù)中實(shí)現(xiàn)轩性,不過(guò)因?yàn)楹芏嗵匦蚤_(kāi)關(guān)庫(kù)未意識(shí)到這些應(yīng)用點(diǎn)而放棄掉声登。這其實(shí)從某個(gè)方面來(lái)說(shuō)就是:

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

參考:

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蛾派,隨后出現(xiàn)的幾起案子俄认,更是在濱河造成了極大的恐慌,老刑警劉巖洪乍,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眯杏,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡壳澳,警方通過(guò)查閱死者的電腦和手機(jī)岂贩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)巷波,“玉大人萎津,你說(shuō)我怎么就攤上這事∧鳎” “怎么了锉屈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)垮耳。 經(jīng)常有香客問(wèn)我颈渊,道長(zhǎng)遂黍,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任俊嗽,我火速辦了婚禮雾家,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绍豁。我一直安慰自己芯咧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布竹揍。 她就那樣靜靜地躺著敬飒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪芬位。 梳的紋絲不亂的頭發(fā)上驶拱,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音晶衷,去河邊找鬼蓝纲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛晌纫,可吹牛的內(nèi)容都是我干的税迷。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼锹漱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼箭养!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起哥牍,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤毕泌,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后嗅辣,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體撼泛,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年澡谭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了愿题。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蛙奖,死狀恐怖潘酗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情雁仲,我是刑警寧澤仔夺,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站攒砖,受9級(jí)特大地震影響缸兔,放射性物質(zhì)發(fā)生泄漏骆膝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一灶体、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧掐暮,春花似錦蝎抽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至精算,卻和暖如春瓢宦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背灰羽。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工驮履, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人廉嚼。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓玫镐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親怠噪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子恐似,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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