DRM 常见问题

本文汇介绍动态配置(DRM)在使用过程中遇到的常见问题及解决方法。

如何利用 DRM 动态设置日志等级?

基于 SOFABoot 开发的程序,对于日志有如下默认配置:

  • application.properties

# log level for current application with groupid com.hula.sofa
 logging.level.com.hula.sofa=INFO
  • logback-spring.xml

<springProperty scope="context" name="logging.level" source="logging.level.com.hula.sofa"/>

您可以通过 DRM 来动态更新日志等级,步骤如下:

  1. 在 SOFABoot 工程中定义对应的动态配置类。

    示例如下:

            import com.alipay.drm.client.DRMClient;
            import com.alipay.drm.client.api.annotation.DAttribute;
            import com.alipay.drm.client.api.annotation.DObject;
            import com.alipay.drm.client.api.model.DependencyLevel;
            import org.springframework.beans.factory.annotation.Autowired;
            import org.springframework.beans.factory.annotation.Value;
            import org.springframework.boot.logging.LogLevel;
            import org.springframework.boot.logging.LoggingSystem;
            @DObject(region="hula", appName ="dynamic-log-level", id ="com.hula.sofa.config.DynamicConfig")
            public class DynamicConfig{
                // 取 application.properties 配置的值作为默认值。
                @DAttribute
                @Value("${logging.level.com.hula.sofa}")
                private String loglevel;
                @Autowired
                LoggingSystem loggingSystem;
                public void init(){
                    DRMClient.getInstance().register(this);
                }
                public String getLoglevel(){
                     return loglevel;
                }
                public void setLoglevel(String loglevel){
                    this.loglevel = loglevel;
                    LogLevel level =LogLevel.valueOf(loglevel.toUpperCase());
                    // 使用 springboot的LoggingSystem 设置目标 logger 的日志等级。
                    loggingSystem.setLogLevel("com.hula.sofa", level);
                }
            }
  2. 在 SOFA 微服务平台上新增如下动态配置。

    操作步骤,请参见 新增动态配置DRM推送.png

    说明

    在客户端值处,推送成功的情况下不会显示新的值。

重启服务后,为何属性获取的是动态配置推送过的值,而不是默认值?

动态配置的默认用法是:当服务端推送配置后启动,客户端会默认同步加载服务端配置值。如果您不想使用该默认同步加载,需设置 @DAttribute(dependency = DependencyLevel.NONE

更多依赖级别,说明如下:

依赖等级

依赖描述

NONE

无依赖,启动期不加载服务端值。启动此级别后,客户端仅会接收服务端在运行期间产生的配置推送。

ASYNC

异步更新,启动期异步加载服务端值,不关注加载结果。

WEAK

弱依赖,启动期同步加载服务端推送值。

  • 当服务端不可用时不影响应用正常启动。

  • 当服务端可用后,客户端会依靠心跳检测重新拉取到服务端值。

STRONG

强依赖,启动期同步加载服务端值。

  • 如服务端未设置值,则使用代码初始化值。

  • 如从服务端获取数据请求异常,或客户端设值异常时,均会抛出异常,应用启动失败。

EAGER

最强依赖,启动期必须拉取到服务端值。如服务端未推送过值则抛异常,应用启动失败。

如何给属性赋初始值?

您可以通过以下方式为属性赋值:

  • 直接在定义式赋值。例如:private String loglevel = "info"

  • application.properties 中获取,示例如下:

    @DAttribute private String loglevel ="info";   //初始值为 info

    @Value("${logging.level.com.hula.sofa}")
    @DAttributeprivate String loglevel;
    注意

    请勿在 init 方法里赋值,否则客户端重启后会覆盖推送值,并变回默认值,造成后续推送无法生效。示例如下:

    public void init(){
             DRMClient.getInstance().register(this);
             setLoglevel("info");
    }

发布部署卡在部署服务中,直到超时,导致发布部署失败

问题现象:

发布部署卡在部署服务中,直到 8 分钟后超时,导致发布部署失败。

问题原因:

在 DRM 中设置了 RefreshCacheDRM.refreshCacheType = GEOHASH,业务代码在收到该项更新后,需花费十几分钟处理业务逻辑。

解决方案:

  • 临时方案:设置 RefreshCacheDRM.refreshCacheType = null,这样暂时不会触发业务处理逻辑。

  • 长期方案:需要优化您的业务代码,在收到 DRM 的属性更新后,使用异步线程,延迟处理该业务,并及时反馈更新成功的信号给 DRM。