在開發環境下我們需要解決哪些開發問題呢?
假如你公司有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);
}
}
使用此插件就能在開發環境愉快的玩耍了。在也不用擔心一個本地請求發出去不知道發到哪裏去了,再也不用擔心本地請求發出去調用到某人機器上,某人打了個斷點拉