1
2
3
4
5
6
|
public class MyCluster implements Cluster{ @Override public <T> Invoker<T> join(Directory<T> directory) throws RpcException { return new MyClusterInvoker(directory); } } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
public class MyClusterInvoker<T> extends MyAbstractClusterInvoker<T> { public MyClusterInvoker(Directory<T> directory) { super (directory); } @Override protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException { //1.查看是否設置了指定ip String ip = (String) RpcContext.getContext().get( "ip" ); if (StringUtils.isBlank(ip)) { throw new RuntimeException( "ip is blank " ); } //2.檢查是否有可用invoker checkInvokers(invokers,invocation); //3.根據指定ip獲取對應invoker Invoker<T> invoked = invokers.stream().filter(invoker -> invoker.getUrl().getHost().equals(ip)) .findFirst().orElse( null ); //4.檢查是否有可用invoker if ( null == invoked) { throw new RpcException(RpcException.NO_INVOKER_AVAILABLE_AFTER_FILTER, "Failed to invoke the method " + invocation.getMethodName() + " in the service " + getInterface().getName() + ". No provider available for the service " + directory.getUrl().getServiceKey() + " from ip " + ip + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version " + Version.getVersion() + ". Please check if the providers have been started and registered." ); } //5.發起遠程調用,失敗則拋出異常 try { return invoked.invoke(invocation); } catch (Throwable e) { if (e instanceof RpcException && ((RpcException) e).isBiz()) { // biz exception. throw (RpcException) e; } throw new RpcException(e instanceof RpcException ? ((RpcException) e).getCode() : 0 , "Fail invoke providers " + (invoked != null ?invoked.getUrl(): "" )+ " " + loadbalance.getClass().getSimpleName() + " select from all providers " + invokers + " for service " + getInterface().getName() + " method " + invocation.getMethodName() + " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), e.getCause() != null ? e.getCause() : e); } } } |
- 如上代碼1,我們從RpcContext.getContext()獲取了屬性值ip,如果指定了改值說明指定了ip,
- 代碼2則檢查是否有可用的服務提供者,如果沒有則拋出異常。
- 代碼3變量invokers列表查找指定IP對應的Invoker
- 代碼4 檢查是否有對應IP對應的Invoker,沒有則拋出異常。
- 代碼5 具體使用選擇的invoker發起遠程調用。
注意我們還修改了框架的AbstractClusterInvoker爲MyAbstractClusterInvoker:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
<font style= "color:rgb(102, 102, 102)" ><font face= "Arial, Helvetica, sans-serif" > public Result invoke( final Invocation invocation) throws RpcException { checkWhetherDestroyed(); // binding attachments into invocation. Map<String, String> contextAttachments = RpcContext.getContext().getAttachments(); if (contextAttachments != null && contextAttachments.size() != 0 ) { ((RpcInvocation) invocation).addAttachments(contextAttachments); } List<Invoker<T>> invokers = list(invocation); LoadBalance loadbalance = null ; //initLoadBalance(invokers, invocation); RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation); return doInvoke(invocation, invokers, loadbalance); } </font></font> |
這裏我們把 LoadBalance loadbalance = initLoadBalance(invokers, invocation);
修改爲了 LoadBalance loadbalance = null;因爲我們不需要負載均衡了。
然後在消費端調用時候進行下面設置就可以指定ip調用了。
//設置集羣容錯策略爲我們自己的
Dubbo是一個高度可擴充的框架,基於SPI的擴展接口,我們可以根據需要定製我們自己的實現,本文我們則基於集羣容錯策略實現了基於ip調用的擴展。