微服务实践我的微服务

1.微服务管理-23.特性开关

2020-05-25  本文已影响0人  Wales_Kuo

微服务实践目录,可以参见连接。

背景

之前翻译过一篇文章《[翻译]功能切换(又称功能标志)》。在这篇文章中介绍了各种需要特性开关的点,并且以Nodejs的例子展示了特性开关的一些细节。基于这片文章这里讨论一下在Java上有哪些点可能会用到特性开关,并进行特性开关技术的具体讨论。

特性开关的特性

在特性开关最通用的用法中有解决功能冲突、蓝绿发布、新特性验证(卡方检验)等功能外,特性开关还可以完成以下的几个功能:

特性开关的层次

整个特性开关可以针对不同的层次进行管理以满足特性要求。对于从客户端到服务端的方式可以定义为:设备->客户端->用户/用户群->自定义策略->全站这几种层次。每个层次上可以实现不同类型的功能开关功能。

技术解决方案对比

现阶段有很多框架、工具库可以满足特性快关的需求,这里就对这些特性开关的实现进行一些对比方便在技术选型中进行使用。

框架 位置 控制台 返回能力 说明
FF4J 皆可 不控制 侵入性较大
Togglz 皆可 不控制 侵入性较大
piranha 皆可 不控制 Uber开源的特性开关
fitchy 皆可 可以控制 现阶段只支持简单的特性开关功能。
flip 皆可 多年前的代码。例子居然是jsp的

从功能对比上来看的化只有FF4J和Togglz是处于可用状态的。其他的几乎都处于不可使用状态。但是这两个可用的还是属于侵入性较大的工具库,因为他们都需要自己写if...else才可以实现特性开关的功能。

从上面的功能对比中可以看到只有两个框架是可用的FF4J和Togglz。而针对这两个框架进行对比FF4J有739star、开发团队56人、最后提交代码8天前,Togglz有586star、开发团队58人、最后提交代码是2个月前。最新版的jar包是在Togglz是2018年7月发布,FF4J是在2020年5月发布。

FF4J和Togglz的文档和issue处理进度来说,FF4J略胜一筹。从更多功能考虑FF4J还可以支撑审计、策略开关、权限开关、监控等。从功能和文档完备度来说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
}
FF4j.check(String featureID)

上面的方法用来检查特性开关的检查。它其中的代码为:

/**
     * 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;
    }

从这里以及其他衍生的方法中检查几乎没有需要进行计算,远程通信的内容。所以,可以认为它对于业务代码的影响几乎很小。

具体使用

真正开始使用是就会遇到各种个样的问题,对于FF4J来说也是如此的。这里先说明FF4J的两种使用方式。

对于系统特性开关来说最主要的是对开关的动态配置管理工作。这部分管理工作FF4J有两种方式进行支撑:web,cli。对于cli来说只能连接本地的服务中的开关,对于web来说可以控制多个服务中的开关。所以选择web方式对于稍大一点系统是必要的。而web中有两种方式:

FF4J使用方式

方式1对于在SpringBoot上来说是不可用状态,因为没有办法将embedded web划到一个独立的contextpath中。因为使用服务端渲染thymeleaf时没有办法给ff4j和业务等配置独立的contextpath,导致使用thymeleaf渲染的页面无法加载。方式2控制的服务可以更多更完善。所以使用方式2是比选项,在进行方式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的注解会发现有很多的问题。所以自定义注解:

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

再定义注解处理类,进行特性的管理工作。

@Aspect // 1:通过改注解声明一个切面
@Component // 2让切面称为spring管理的bean
@Slf4j
@ConditionalOnBean(FF4j.class)
public class FeatureFlippingAspect {
    @Autowired
    public FF4j ff4j;

    //切面
    @Around("@annotation(cn.eduplus.uc.common.flipping.FeatureFlippingAnnotation)") //6:直接拦截方法名
    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("方法规则式拦截," + method.getName());
            return null;
        }
    }
}

使用它的方式:

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

总结

FF4J的功能还以应用于Avoid Feature Branching,Blue/Green Deployments,Canary Release,Dark Launch,Graceful degradation,Thin client application,Business Toggle,A/B Testing,Circuit Breaker。这些也可以在其他的特性开关库中实现,不过因为很多特性开关库未意识到这些应用点而放弃掉。这其实从某个方面来说就是:

思维决定认识,认识决定高度,高度决定人生

参考:

微服务版本分支管理与特性开关
特性开关框架选型之FF4J vs Togglz
SpringAOP整合Togglz!你的周末健身时光不再被打扰!!!
ff4j 特性开关功能开发的一些实践理论
FF4J: Feature Toggling for Spring/Spring Boot Applications

上一篇 下一篇

猜你喜欢

热点阅读