服务降级常见设置
- **mock="force:return null":**消费方对该服务的方法调用都直接强制性返回 null 值,不发起远程调用。
- **mock="fail:return null":**消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。
- **mock="true":**消费方对该服务的方法调用在失败后,会调用消费方定义的服务降级Mock 类实例的相应方法。而该 Mock 类的类名为“业务接口名+Mock”,且放在与接口相同的包中。
- **mock=降级类的全限定性类名:**与 **mock="true"**功能类似,不同的是,该方式中的降级类名可以是任意名称,在任何包中
InvokerInvocationHandler.java
MockClusterInvoker.java
public Result invoke(Invocation invocation) throws RpcException {
Result result = null;
// 获取mock属性值
String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), MOCK_KEY, Boolean.FALSE.toString()).trim();
// 若没有设置mock属性,或mock属性值为false,则不具有降级功能
if (value.length() == 0 || value.equalsIgnoreCase("false")) {
//no mock 直接进行远程调用(不会降级)
result = this.invoker.invoke(invocation);
} else if (value.startsWith("force")) {
// 代表开启强制降级,直接放弃远程调用,执行本地降级方法调用
if (logger.isWarnEnabled()) {
logger.warn("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl());
}
//force:direct mock 直接降级
result = doMockInvoke(invocation, null);
} else {
//fail-mock
try { // 远程调用
result = this.invoker.invoke(invocation);
} catch (RpcException e) {
// 远程调用出现异常,则再进行服务降级
if (e.isBiz()) {
throw e;
}
if (logger.isWarnEnabled()) {
logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e);
}
// 服务降级
result = doMockInvoke(invocation, e);
}
}
return result;
}
@SuppressWarnings({"unchecked", "rawtypes"})
private Result doMockInvoke(Invocation invocation, RpcException e) {
Result result = null;
Invoker<T> minvoker;
// 重新再从zk中获取一次最新的invoker
List<Invoker<T>> mockInvokers = selectMockInvoker(invocation);
// 若仍没有可用的invoker,则创建一个MockInvoker,否则返回第一个可用的invoker
if (CollectionUtils.isEmpty(mockInvokers)) {
minvoker = (Invoker<T>) new MockInvoker(directory.getUrl(), directory.getInterface());
} else {
minvoker = mockInvokers.get(0);
}
try {
// 执行降级方法调用,跟踪这里
result = minvoker.invoke(invocation);
} catch (RpcException me) {
if (me.isBiz()) {
result = AsyncRpcResult.newDefaultAsyncResult(me.getCause(), invocation);
} else {
throw new RpcException(me.getCode(), getMockExceptionMessage(e, me), me.getCause());
}
} catch (Throwable me) {
throw new RpcException(getMockExceptionMessage(e, me), me.getCause());
}
return result;
}
MockInvoker.java
public Result invoke(Invocation invocation) throws RpcException {
// 获取<dubbo:method/>中的mock属性
String mock = getUrl().getParameter(invocation.getMethodName() + "." + MOCK_KEY);
if (invocation instanceof RpcInvocation) {
((RpcInvocation) invocation).setInvoker(this);
}
// 若<dubbo:method/>中没有设置mock,则获取<dubbo:reference/>中的mock
// 这里就可以看出,方法级别的设置大于接口级别的设置。
if (StringUtils.isBlank(mock)) {
mock = getUrl().getParameter(MOCK_KEY);
}
if (StringUtils.isBlank(mock)) {
throw new RpcException(new IllegalAccessException("mock can not be null. url :" + url));
}
// 解析mock中的值,并返回。为下面的业务做准备
mock = normalizeMock(URL.decode(mock));
// 处理mock以return开头的情况
if (mock.startsWith(RETURN_PREFIX)) {
// 取return后面的内容
mock = mock.substring(RETURN_PREFIX.length()).trim();
try {
Type[] returnTypes = RpcUtils.getReturnTypes(invocation);
Object value = parseMockValue(mock, returnTypes);
return AsyncRpcResult.newDefaultAsyncResult(value, invocation);
} catch (Exception ew) {
throw new RpcException("mock return invoke error. method :" + invocation.getMethodName()
+ ", mock:" + mock + ", url: " + url, ew);
}
// 处理mock以throw开头的情况
} else if (mock.startsWith(THROW_PREFIX)) {
mock = mock.substring(THROW_PREFIX.length()).trim();
if (StringUtils.isBlank(mock)) {
throw new RpcException("mocked exception for service degradation.");
} else { // user customized class
Throwable t = getThrowable(mock);
throw new RpcException(RpcException.BIZ_EXCEPTION, t);
}
} else { //impl mock 调用自定义降级类
try {
// 加载并实例化本地降级类
Invoker<T> invoker = getInvoker(mock);
return invoker.invoke(invocation);
} catch (Throwable t) {
throw new RpcException("Failed to create mock implementation class " + mock, t);
}
}
}
public static String normalizeMock(String mock) {
if (mock == null) { // mock为null,则返回null
return mock;
}
mock = mock.trim();
if (mock.length() == 0) { // mock为空串,则返回空串
return mock;
}
if (RETURN_KEY.equalsIgnoreCase(mock)) { // mock为return,则返回returnnull
return RETURN_PREFIX + "null";
}
// mock为true、default、fail或force,则返回default
if (ConfigUtils.isDefault(mock) || "fail".equalsIgnoreCase(mock) || "force".equalsIgnoreCase(mock)) {
return "default";
}
// mock以fail:开头,则返回fail:后面的子串
if (mock.startsWith(FAIL_PREFIX)) {
mock = mock.substring(FAIL_PREFIX.length()).trim();
}
// mock以force:开头,则返回force:后面的子串
if (mock.startsWith(FORCE_PREFIX)) {
mock = mock.substring(FORCE_PREFIX.length()).trim();
}
// 若mock以return或throw,则将反引号替换为双引号
if (mock.startsWith(RETURN_PREFIX) || mock.startsWith(THROW_PREFIX)) {
mock = mock.replace('`', '"');
}
return mock;
}
private Invoker<T> getInvoker(String mockService) {
Invoker<T> invoker = (Invoker<T>) MOCK_MAP.get(mockService);
if (invoker != null) {
return invoker;
}
// 加载指定业务接口
Class<T> serviceType = (Class<T>) ReflectUtils.forName(url.getServiceInterface());
// 构建出降级类,再加载并实例化
T mockObject = (T) getMockObject(mockService, serviceType);
// 将降级实例封装为一个invoker
invoker = PROXY_FACTORY.getInvoker(mockObject, serviceType, url);
if (MOCK_MAP.size() < 10000) {
MOCK_MAP.put(mockService, invoker);
}
return invoker;
}
public static Object getMockObject(String mockService, Class serviceType) {
// 若mockService的值为default,则构建出降级类名
if (ConfigUtils.isDefault(mockService)) {
mockService = serviceType.getName() + "Mock";
}
// 加载降级类
Class<?> mockClass = ReflectUtils.forName(mockService);
// 若降级类没有实现业务接口,则抛出异常
if (!serviceType.isAssignableFrom(mockClass)) {
throw new IllegalStateException("The mock class " + mockClass.getName() +
" not implement interface " + serviceType.getName());
}
try {
// 实例化
return mockClass.newInstance();
} catch (InstantiationException e) {
throw new IllegalStateException("No default constructor from mock class " + mockClass.getName(), e);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}