
com.alibaba.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dubbo2 Show documentation
Show all versions of dubbo2 Show documentation
The all in one project of dubbo2
The newest version!
/*
* Copyright 1999-2011 Alibaba Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.dubbo.rpc.cluster.support.wrapper;
import java.util.List;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcInvocation;
import com.alibaba.dubbo.rpc.RpcResult;
import com.alibaba.dubbo.rpc.cluster.Directory;
import com.alibaba.dubbo.rpc.support.MockInvoker;
/**
* @author chao.liuc
*/
public class MockClusterInvoker implements Invoker{
private static final Logger logger = LoggerFactory.getLogger(MockClusterInvoker.class);
private final Directory directory ;
private final Invoker invoker;
public MockClusterInvoker(Directory directory, Invoker invoker) {
this.directory = directory;
this.invoker = invoker;
}
public URL getUrl() {
return directory.getUrl();
}
public boolean isAvailable() {
return directory.isAvailable();
}
public void destroy() {
this.invoker.destroy();
}
public Class getInterface() {
return directory.getInterface();
}
public Result invoke(Invocation invocation) throws RpcException {
Result result = null;
String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();
if (value.length() == 0 || value.equalsIgnoreCase("false")){
//no mock
result = this.invoker.invoke(invocation);
} else if (value.startsWith("force")) {
if (logger.isWarnEnabled()) {
logger.info("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;
} else {
if (logger.isWarnEnabled()) {
logger.info("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 minvoker ;
List> mockInvokers = selectMockInvoker(invocation);
if (mockInvokers == null || mockInvokers.size() == 0){
minvoker = (Invoker) new MockInvoker(directory.getUrl());
} else {
minvoker = mockInvokers.get(0);
}
try {
result = minvoker.invoke(invocation);
} catch (RpcException me) {
if (me.isBiz()) {
result = new RpcResult(me.getCause());
} else {
throw new RpcException(me.getCode(), getMockExceptionMessage(e, me), me.getCause());
}
//
} catch (Throwable me) {
throw new RpcException(getMockExceptionMessage(e, me), me.getCause());
}
return result;
}
private String getMockExceptionMessage(Throwable t, Throwable mt){
String msg = "mock error : " + mt.getMessage();
if (t != null){
msg = msg + ", invoke error is :" + StringUtils.toString(t);
}
return msg;
}
/**
* 返回MockInvoker
* 契约:
* directory根据invocation中是否有Constants.INVOCATION_NEED_MOCK,来判断获取的是一个normal invoker 还是一个 mock invoker
* 如果directorylist 返回多个mock invoker,只使用第一个invoker.
* @param invocation
* @return
*/
private List> selectMockInvoker(Invocation invocation){
//TODO generic invoker?
if (invocation instanceof RpcInvocation){
//存在隐含契约(虽然在接口声明中增加描述,但扩展性会存在问题.同时放在attachement中的做法需要改进
((RpcInvocation)invocation).setAttachment(Constants.INVOCATION_NEED_MOCK, Boolean.TRUE.toString());
//directory根据invocation中attachment是否有Constants.INVOCATION_NEED_MOCK,来判断获取的是normal invokers or mock invokers
List> invokers = directory.list(invocation);
return invokers;
} else {
return null ;
}
}
@Override
public String toString() {
return "invoker :" + this.invoker + ",directory: " + this.directory;
}
}