dubbo优化之本地存根缓存前置

    今年做了一个dubbo的本地存根优化,觉得卓有成效所以在这记录分享下。

    问题:

      1. Account服务如何将日均调用从千万优化到百万?看到这个问题,你是否也在纳闷,如果业务量没有下来,调用量怎么会下来呢?

      答:其实真可以有,Account的getAccount之前dubbo调用量在1000w+,优化到现在基本在100w+左右。如果Account服务的业务方可以充分使用Account的公共资源如缓存等,那么就可以减少dubbo的RPC调用,但是又有个问题,如何做到让业务方不care缓存调用的相关逻辑呢?这个我们用了一个小小的技巧,dubbo的stub。

 

      2. dubbo的stub是啥?

      答:请参照dubbo官网链接

 

    技术实现:

      1. 流程图如下

       
      

   

      2.系统架构图如下:

      
      

 

    3. 缺点

      a) 缓存地址变化,所以使用本地存根的消费者都需要修改配置

      b) 如果缓存从nkv切换到ncr则需要升级jar包中的缓存,影响所有的使用本地存根的消费者。

      c) 无法监控哪些消费者使用者本地存根。

 

    核心代码:

    

// 核心配置支持配置文件和zk的配置方式
public class AccountConfig {
    /** NKV 配置 */
    public String accountNkvConfig;
    public String masterUrl;
    public String slaveUrl;
    public Short namespace;
    public Long timeOut;

    /** 开关控制是否走缓存优化 */
    public boolean useCacheOptimize = true;

    /** Disconf配置 */
    private ConfigService configService;

    /** 0 未初始化, 1 disconf  2 properties */
    private int initType = 0;

    public void init() {
        if(null != configService) {
            accountNkvConfig = configService.getString("account_nkv_config");
            initConfig();
            if(checkConfig()) {
                initType = 1;
            }
        } else {
            if(checkConfig()) {
                initType = 2;
            }
        }
    }

    /** 初始化配置 */
    public void initConfig() {
        try {
            if(StringUtils.isNotBlank(accountNkvConfig)) {
                JSONObject nkvConfigJSON = JSONObject.parseObject(accountNkvConfig);
                masterUrl = nkvConfigJSON.getString("master");
                slaveUrl = nkvConfigJSON.getString("slave");
                namespace = nkvConfigJSON.getShort("namespace");
                timeOut = nkvConfigJSON.getLong("timeout");
            }
        } catch (Exception e) {

        }
    }

    public boolean checkConfig() {
        if( StringUtils.isBlank(masterUrl) || StringUtils.isBlank(slaveUrl) || null == namespace || null == timeOut ) {
            return false;
        }
        return true;
    }


    public boolean getUseCacheOptimize() {
        if(null != configService) {
            return configService.getBoolean("use_cache_optimize", true);
        }
        return useCacheOptimize;
    }
}

  

    

// 初始化cache
public class CacheClient extends MemcacheManagerImpl{

    @Autowired
    public AccountConfig accountConfig;

    public void init() {
        try {
            MemcacheTransactionManagerImpl spaceMemcacheTransactionManager = new MemcacheTransactionManagerImpl();
            DefaultNkvClient nkvClient = new DefaultNkvClient();
            nkvClient.setMaster(accountConfig.masterUrl);
            nkvClient.setSlave(accountConfig.slaveUrl);
            nkvClient.setGroup("group_1");
            nkvClient.setCompressEnabled(true);
            nkvClient.init();

            setMemcacheTransactionManager(spaceMemcacheTransactionManager);
            setClient(nkvClient);
            setNamespace(accountConfig.namespace);
            setTimeoutMilliseconds(accountConfig.timeOut);
        } catch (Exception e) {
            LogUtil.accountOpt.info("Account init Cache Exception ", e);
        }
    }
}

 

    

// 判断cache是否初始化成功
@Component
public class ApplicationContextHolder implements ApplicationContextAware {

    public static ApplicationContext applicationContext;

    /** 是否初始化成功 */
    public static boolean isInitSuccess = false;

    public static AccountConfig accountConfig = null;

    public static  Object getBean(String beanName) {
        return applicationContext.getBean(beanName);
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextHolder.applicationContext = applicationContext;
        try {
            Object accountConfigObj =  applicationContext.getBean("accountConfig");
            LogUtil.accountOpt.info("Account Cache Config : " + (null == accountConfigObj ? null : accountConfigObj.toString()));
            if(null != accountConfigObj) {
                accountConfig = (AccountConfig) accountConfigObj;
                if(accountConfig.getInitType() > 0) {
                    Object memcacheManagerObj = applicationContext.getBean("cacheClient");
                    if(null != memcacheManagerObj) {
                        isInitSuccess = true;
                    }
                }
            }
        } catch (Exception e) {
            LogUtil.accountOpt.error("Account Cache Init exception " , e);
        }
        LogUtil.accountOpt.info("Account Cache Init Result : "  + isInitSuccess);
    }
}

   

   

// 使用本地存根
public class AccountServiceStub extends CacheManager<Account> implements AccountService {
    // dubbo会自动注入该对象,使用注解无效
    private AccountService accountService;

    public AccountServiceStub(AccountService accountService) {
        this.accountService = accountService;
    }

    @Override
    public Account queryByUserId(Long userId) {
        return accountService.queryByUserId(userId);
    }
}

   

<!-- dubbo消费方配置 -->
<dubbo:reference  id="accountService"  
  interface="com.xxx.account.service.AccountService"              
  stub="com.xxx.account.service.AccountServiceStub" />


 

 

 

 

猜你喜欢

转载自labreeze.iteye.com/blog/2354843