全部产品

故障排查之 DRM

更新时间:2020-10-09 14:10:24

本文汇总梳理了动态配置(DRM)在使用过程中遇到的常见问题,主要内容如下:

如何利用 DRM 动态设置 loglevel?

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

  • application.properties:
  1. # log level for current application with groupid com.hula.sofa
  2. logging.level.com.hula.sofa=INFO
  • logback-spring.xml:
  1. <springProperty scope="context" name="logging.level"
  2. source="logging.level.com.hula.sofa" />

我们可以使用 DRM 来动态更新 loglevel,步骤如下:

  1. 定义对应的动态配置类,示例如下:

    1. import com.alipay.drm.client.DRMClient;
    2. import com.alipay.drm.client.api.annotation.DAttribute;
    3. import com.alipay.drm.client.api.annotation.DObject;
    4. import com.alipay.drm.client.api.model.DependencyLevel;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.beans.factory.annotation.Value;
    7. import org.springframework.boot.logging.LogLevel;
    8. import org.springframework.boot.logging.LoggingSystem;
    9. @DObject(region= "hula", appName = "dynamic-log-level", id = "com.hula.sofa.config.DynamicConfig")
    10. public class DynamicConfig {
    11. // 取application.properties配置的值作为默认值
    12. @DAttribute
    13. @Value("${logging.level.com.hula.sofa}")
    14. private String loglevel;
    15. @Autowired
    16. LoggingSystem loggingSystem;
    17. public void init() {
    18. DRMClient.getInstance().register(this);
    19. }
    20. public String getLoglevel() {
    21. return loglevel;
    22. }
    23. public void setLoglevel(String loglevel) {
    24. this.loglevel = loglevel;
    25. LogLevel level = LogLevel.valueOf(loglevel.toUpperCase());
    26. // 使用springboot的LoggingSystem设置目标logger的loglevel
    27. loggingSystem.setLogLevel("com.hula.sofa", level);
    28. }
    29. }
  2. 在 SOFA 微服务平台上配置对应的动态配置,即可实现动态更新 loglevel。DRM推送.png

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

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

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

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

依赖等级 依赖描述
NONE 无依赖,启动期不加载服务端值,启动此级别后,客户端仅会接收服务端在运行期间产生的配置推送。
ASYNC 异步更新,启动期异步加载服务端值,不关注加载结果。
NONE 无依赖,启动期不加载服务端值,启动此级别后,客户端仅会接收服务端在运行期间产生的配置推送。
WEAK 弱依赖,启动期同步加载服务端推送值。
- 当服务端不可用时不影响应用正常启动。
- 服务端可用后,客户端会依靠心跳检测重新拉取到服务端值。
STRONG 强依赖,启动期同步加载服务端值。
- 如服务端未设置值,则使用代码初始化值。
- 如从服务端获取数据请求异常,或客户端设值异常时,均会抛出异常,应用启动失败。
EAGER 最强依赖,启动期必须拉取到服务端值。如服务端未推送过值则抛异常,应用启动失败。

如何给属性赋初始值?

有下述几种方式:

  • 直接在定义式赋值。
  • application.properties 中获取,示例如下:
  1. //正确方式
  2. @DAttribute private String loglevel = "info"; //初始值为info
  3. //或者
  4. @Value("${logging.level.com.hula.sofa}")
  5. @DAttribute private String loglevel;

注意常见错误方式:在 init 方法里面赋值。

这样赋值时,在重启后,会覆盖推送值,并变回默认值,会造成后续推送无法生效。示例如下:

  1. //错误方式
  2. public void init() {
  3. DRMClient.getInstance().register(this);
  4. setLoglevel("info");
  5. }