在开发环境下我们需要解决哪些开发问题呢?
假如你公司有100个服务,并且服务间调用错综复杂可能是A-B-C-D-E,并且公司提供了一套开发环境,在多人开发的情况下,你的请求可能被负载到了别的开发者机器上,又或者你想要你的请求负载回你自己的本机,然后请求出去就消失无踪了。然而你又不能用直连的方式,因为你的服务还有对其它服务有依赖。
需解决如下问题
- 当你指定负载的时候优先负载至你自己本机
- 当没有你本机的时候不能负载到别人机器上,必须调用开发环境公共服务。
- 调用链中间隔性存在负载时,需要优先调用至本机
例如:A-B-C-D 我在开发A、D服务但是B、C不存在负载,这个时候我需要服务调用到D的时候是负载到我本机。 - 不影响测试到生产流水线环境。
根据以上问题做出扩展,需要扩展两个Filter、和一个LoadBalance。
github项目地址
核心代码如下
ConsumerDevFilter.java
package com.dubbo.dev.plugin.filter;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.rpc.*;
import com.dubbo.dev.plugin.loadbalance.CurrRequest;
import com.dubbo.dev.plugin.loadbalance.LbConfig;
import com.dubbo.dev.plugin.loadbalance.LbConst;
import com.dubbo.dev.plugin.loadbalance.ReqMeta;
/**
* @author 86180
* @Description:
* @date 2020/6/210:20
*/
@Activate(group = {Constants.CONSUMER})
public class ConsumerDevFilter implements Filter {
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
ReqMeta meta = CurrRequest.getMeta();
boolean b = invocation.getAttachments().containsKey(LbConst.DUBBO_LB_HOST);
if(!b){
CurrRequest.setAttachment(meta);
}
//此filter解决问题:调用链中,间隔性存在负载时,需要优先调用至本机
Result result = invoker.invoke(invocation);
return result;
}
}
ProviderDevFilter.java
package com.dubbo.dev.plugin.filter;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.rpc.*;
import com.dubbo.dev.plugin.loadbalance.CurrRequest;
import com.dubbo.dev.plugin.loadbalance.LbConst;
import com.dubbo.dev.plugin.loadbalance.ReqMeta;
import java.util.Map;
@Activate(group = {Constants.PROVIDER})
public class ProviderDevFilter implements Filter {
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
ReqMeta reqMeta = new ReqMeta();
Map<String, String> attachments = invocation.getAttachments();
String dubboLbHost = attachments.get(LbConst.DUBBO_LB_HOST);
String dubboLbDefault = attachments.get(LbConst.DUBBO_LB_DEFAULT);
if (!StringUtils.isBlank(dubboLbHost)) {
reqMeta.setDubboLbHost(dubboLbHost);
reqMeta.setDubboLbDefault(dubboLbDefault);
}
CurrRequest.setMeta(reqMeta);
Result result = invoker.invoke(invocation);
CurrRequest.remove();
return result;
}
}
DevLoadBalance.java
package com.dubbo.dev.plugin.loadbalance;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance;
import com.alibaba.dubbo.rpc.cluster.loadbalance.RandomLoadBalance;
import java.util.List;
/**
* @author 86180
* @Description: 扩展负载
* @date 2020/6/19:20
*/
public class DevLoadBalance extends AbstractLoadBalance {
@Override
protected <T> Invoker<T> doSelect(List<Invoker<T>> list, URL url, Invocation invocation) {
ReqMeta meta = CurrRequest.getMeta();
ReqMeta reqMeta = CurrRequest.setAttachment(meta);
String dubboLbHost = reqMeta.getDubboLbHost();
String dubboLbDefault = reqMeta.getDubboLbDefault();
//获取当前配置负载
if (dubboLbHost != null) {
for (Invoker<T> invoker : list) {
if (invoker.getUrl().getHost().matches(dubboLbHost)) {
return invoker;
}
}
}
//获取默认的配置
String[] split = dubboLbDefault.split(",");
for (String pattern : split) {
for (Invoker<T> invoker : list) {
if (invoker.getUrl().getHost().matches(pattern)) {
return invoker;
}
}
}
return new RandomLoadBalance().select(list, url, invocation);
}
}
使用此插件就能在开发环境愉快的玩耍了。在也不用担心一个本地请求发出去不知道发到哪里去了,再也不用担心本地请求发出去调用到某人机器上,某人打了个断点拉