package net.dubboclub.circuitbreaker; import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.utils.ConfigUtils; import com.alibaba.dubbo.common.utils.NetUtils; import com.alibaba.dubbo.rpc.Invocation; import com.alibaba.dubbo.rpc.Invoker; import org.apache.commons.lang.StringUtils; import java.net.InetAddress; /** * Created by bieber on 2015/6/15. */ public class Config { //默认情况下1分钟内出现10个异常,同时默认情况下当满足1分钟内10个异常,然后每发生10次错误就会进行一次重试,检查服务是否恢复 private static final String DEFAULT_BREAK_LIMIT="10"; private static final String DEFAULT_RETRY_FREQUENCY="10"; protected static final String DUBBO_REFERENCE_PREFIX="dubbo.reference."; private static final String DUBBO_REFERENCE_CIRCUIT_BREAKER_SWITCH=DUBBO_REFERENCE_PREFIX+"circuit.breaker"; /** * 获取当前调用的服务方法是否开启了服务降级功能 * @param invoker * @param invocation * @return */ public static boolean checkFunctionSwitch(Invoker<?> invoker, Invocation invocation){ //先动态从调用地址里面获取开关配置信息,这个配置可以在配置中心的动态配置{methodName.}circuit.bread=true/false String circuitBreak = invoker.getUrl().getMethodParameter(invocation.getMethodName(),"circuit.break"); if(StringUtils.isEmpty(circuitBreak)){ String interfaceName = invoker.getUrl().getParameter(Constants.INTERFACE_KEY); String method = invocation.getMethodName(); StringBuffer interfaceConfig = new StringBuffer(DUBBO_REFERENCE_PREFIX); interfaceConfig.append(interfaceName); StringBuffer methodConfig = new StringBuffer(interfaceConfig.toString()); methodConfig.append(".").append(method); return getSwitch(interfaceConfig,methodConfig); } return Boolean.parseBoolean(StringUtils.trim(circuitBreak)); } public static int getBreakLimit(Invoker<?> invoker,Invocation invocation){ String dynamicConfig = invoker.getUrl().getMethodParameter(invocation.getMethodName(),"break.limit"); if(StringUtils.isEmpty(dynamicConfig)){ return getBreakLimit(getInterfacePropertyName(invoker),getMethodPropertyName(invoker,invocation)); } int limit = Integer.parseInt(dynamicConfig); int retries = invoker.getUrl().getParameter(Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES); retries++; return limit*retries; } public static StringBuffer getInterfacePropertyName(Invoker<?> invoker){ String interfaceName = invoker.getUrl().getParameter(Constants.INTERFACE_KEY); StringBuffer interfaceConfig = new StringBuffer(DUBBO_REFERENCE_PREFIX); interfaceConfig.append(interfaceName); return interfaceConfig; } public static StringBuffer getMethodPropertyName(Invoker<?> invoker, Invocation invocation){ String interfaceName = invoker.getUrl().getParameter(Constants.INTERFACE_KEY); String method = invocation.getMethodName(); StringBuffer interfaceConfig = new StringBuffer(DUBBO_REFERENCE_PREFIX); interfaceConfig.append(interfaceName); StringBuffer methodConfig = new StringBuffer(interfaceConfig.toString()); methodConfig.append(".").append(method); return methodConfig; } public static InetAddress getLocalAddress(){ return NetUtils.getLocalAddress(); } /** * 获取某个方法或者某个接口的判定为出现异常的次数 * 提供在配置中心和dubbo.properties两种途径配置 * 如果两个地方均有配置,配置中心的为准 * @param interfaceConfig * @param methodConfig * @return */ public static int getBreakLimit(StringBuffer interfaceConfig,StringBuffer methodConfig){ methodConfig.append(".break.limit"); interfaceConfig.append(".break.limit"); String breakLimitConf = ConfigUtils.getProperty(methodConfig.toString(), ConfigUtils.getProperty(interfaceConfig.toString(), ConfigUtils.getProperty("dubbo.reference.default.break.limit", DEFAULT_BREAK_LIMIT))); return Integer.parseInt(breakLimitConf); } /** * 获取某个方法或者接口是否开启服务降级的功能,默认是开启降级功能 * 提供在配置中心和dubbo.properties两种途径配置 * 如果两个地方均有配置,配置中心的为准 * @param interfaceConfig * @param methodConfig * @return */ public static boolean getSwitch(StringBuffer interfaceConfig, StringBuffer methodConfig){ methodConfig.append(".circuit.break"); interfaceConfig.append(".circuit.break"); //从dubbo.properties的配置中获取 String switchConfig = ConfigUtils.getProperty(methodConfig.toString(), ConfigUtils.getProperty(interfaceConfig.toString(), ConfigUtils.getProperty("dubbo.reference.circuit.break", "false"))); return Boolean.parseBoolean(switchConfig); } public static int getRetryFrequency(Invoker<?> invoker,Invocation invocation){ String retryFrequency = invoker.getUrl().getMethodParameter(invocation.getMethodName(),"retry.frequency"); if(StringUtils.isEmpty(retryFrequency)){ return getRetryFrequency(getInterfacePropertyName(invoker),getMethodPropertyName(invoker,invocation)); } return Integer.parseInt(retryFrequency); } /** * 获取某个方法或者接口重试频次,及每出现多少次异常,就重试一次远程接口 * 提供在配置中心和dubbo.properties两种途径配置 * 如果两个地方均有配置,配置中心的为准 * @param interfaceConfig * @param methodConfig * @return */ public static int getRetryFrequency(StringBuffer interfaceConfig, StringBuffer methodConfig){ methodConfig.append(".retry.frequency"); interfaceConfig.append(".retry.frequency"); String retryFrequencyConf = ConfigUtils.getProperty(methodConfig.toString(), ConfigUtils.getProperty(interfaceConfig.toString(), ConfigUtils.getProperty("dubbo.reference.default.retry.frequency", DEFAULT_RETRY_FREQUENCY))); return Integer.parseInt(retryFrequencyConf); } }