- #remoting:遠程通訊基礎,提供對多種NIO框架抽象封裝,包括“同步轉異步”和“請求-響應”模式的信息交換方式。
- #cluster: 服務框架核心,提供基於接口方法的遠程過程調用,包括多協議支持,並提供軟負載均衡和容錯機制的集群支持。
-
#registry: 服務注冊中心,使服務消費方能動態的查找服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。

當服務調用失敗時(比如響應超時),根據我們的業務不同,可以使用不同的策略來應對這種失敗。比如我們調用的服務是一個查詢服務,不會修改數據庫,那么可以給該服務設置容錯方式為failover <失敗重試方式>,當調用失敗時,自動切換到其他服務提供者去調用,當失敗次數超過指定重試次數,那么就拋出錯誤。如果服務是更新數據的服務,那就不能使用失敗重試的方式了, 因為這樣可能產生數據重復修改的問題,比如調用提供者A的插入用戶方法,但是該方法業務邏輯復雜,執行過程很慢,導致響應超時,那么此時如果再去調用另外一個服務提供者的插入用戶方法,將會又重復插入同一個用戶。對於這種類型的服務,可以使用容錯方式為failfast,如果第一次調用失敗,立即報錯,不需要重試。
另外還有下面幾種容錯類型,failsafe 出現錯誤,直接忽略,不重試也不報錯; failback 失敗后不報錯,會將該失敗請求,定時重發,適合消息通知類型的服務。forking,並行調用多個服務器,只要在某一台提供者上面成功,那么方法返回,適合實時性要求較高的查詢服務,但是要犧牲性能。因為每台服務器會做同一個操作;broadcast 廣播調用所有服務提供者,逐個調用,任意一台報錯則報錯。適合與更新每台提供者上面的緩存,這種類型的服務。
案例:我們在點我吧的APP消息推送就是采用的failback方式,點我吧的短信通知則采用的是failover方式。
如上圖所示,是環形的hash空間,按照常用的hash算法來將對應的key哈希到一個具有2^32次方個桶的空間中,即0~(2^32)-1的數字空間中。現在我們可以將這些數字頭尾相連,想象成一個閉合的環形。我們把數據通過hash算法處理后映射到環上,現在我們將object1、object2、object3、object4四個對象通過特定的Hash函數計算出對應的key值,然后散列到Hash環上。Hash(object1) = key1;Hash(object2) = key2;Hash(object3) = key3;Hash(object4) = key4;


1 public interface SolrSearchService { 2 String search(String collection, String q, ResponseType type, int start, int rows); 3 public enum ResponseType {JSON, XML} 4 }

1 package org.shirdrn.platform.dubbo.service.rpc.server; 2 3 import java.io.IOException; 4 import java.util.HashMap; 5 import java.util.Map; 6 7 import org.apache.commons.logging.Log; 8 import org.apache.commons.logging.LogFactory; 9 import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService; 10 import org.shirdrn.platform.dubbo.service.rpc.utils.QueryPostClient; 11 import org.springframework.context.support.ClassPathXmlApplicationContext; 12 13 public class SolrSearchServer implements SolrSearchService { 14 15 private static final Log LOG = LogFactory.getLog(SolrSearchServer.class); 16 private String baseUrl; 17 private final QueryPostClient postClient; 18 private static final Map<ResponseType, FormatHandler> handlers = new HashMap<ResponseType, FormatHandler>(0); 19 static { 20 handlers.put(ResponseType.XML, new FormatHandler() { 21 public String format() { 22 return "&wt=xml"; 23 } 24 }); 25 handlers.put(ResponseType.JSON, new FormatHandler() { 26 public String format() { 27 return "&wt=json"; 28 } 29 }); 30 } 31 public SolrSearchServer() { 32 super(); 33 postClient = QueryPostClient.newIndexingClient(null); 34 } 35 public void setBaseUrl(String baseUrl) { 36 this.baseUrl = baseUrl; 37 } 38 public String search(String collection, String q, ResponseType type, 39 int start, int rows) { 40 StringBuffer url = new StringBuffer();
url.append(baseUrl).append(collection).append("/select?").append(q);
url.append("&start=").append(start).append("&rows=").append(rows); 41 url.append(handlers.get(type).format()); 42 LOG.info("[REQ] " + url.toString()); 43 return postClient.request(url.toString()); 44 } 45 interface FormatHandler { 46 String format(); 47 } 48 public static void main(String[] args) throws IOException { 49 String config = SolrSearchServer.class.getPackage().getName().replace('.', '/') + "/search-provider.xml"; 50 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config); 51 context.start(); 52 System.in.read(); 53 } 54 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 4 http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> 5 <dubbo:application name="search-provider" /> 6 <dubbo:registry address="zookeeper://slave1:2188?backup=slave3:2188,slave4:2188" /> 7 <dubbo:protocol name="dubbo" port="20880" /> 8 <bean id="searchService" class="org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer"> 9 <property name="baseUrl" value="http://nginx-lbserver/solr-cloud/" /> 10 </bean> 11 <dubbo:service interface="org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService" ref="searchService" /> 12 </beans>
上面,Dubbo服務注冊中心指定ZooKeeper的地址:zookeeper://slave1:2188?backup=slave3:2188,slave4:2188,使用Dubbo協議。配置服務接口的時候,可以按照Spring的Bean的配置方式來配置,注入需要的內容,我們這里指定了搜索集群的Nginx反向代理地址http://nginx-lbserver/solr-cloud/。

/* * 使用Dubbo服務接口 */ // 首先,在API包中定義服務接口,同時部署於Provider端和Consumer端 public interface HelloService { public String sayHello(); } // 其次,在服務端的Provider實現代碼 public class HelloServiceImpl implements HelloService { public String sayHello() { return "Welcome to dubbo!"; } } // 配置:提供者暴露服務;消費者消費服務 /*provider端服務實現類*/ <bean id="helloService" class="com.alibaba.hello.impl.HelloServiceImpl" /> /*provider端暴露服務*/ <dubbo:service interface="com.alibaba.hello.HelloService" version="1.0.0" ref="helloService"/> /*consumer端引入服務*/ <dubbo:reference id="helloService" interface="com.alibaba.hello.HelloService" version="1.0.0" /> /*consumer端使用服務*/ <bean id="xxxAction" class="com.alibaba.xxx.XxxAction" ><property name="helloService" ref="helloService" /></bean>
