Dubbo能解決什麼問題
-
怎麼去維護url
通過注冊中心去維護url(zookeeper、redis、memcache…)
-
F5硬體負載均衡器的單點壓力比較大
軟負載均衡
-
怎麼去整理出服務之間的依賴關系
自動去整理各個服務之間的依賴
-
如果伺服器的調用量越來越大,伺服器的容量問題怎麼去評估,擴容的名額
需要一個監控平台,可以監控調用量、響應時間
Dubbo 是什麼
Dubbo 是一個分布式的服務架構,提供高性能的以及透明化的 RPC 遠端服務調用解決方法,以及 SOA 服務治理方案。
Dubbo的核心部分:
遠端通信
叢集容錯
服務的自動發現
負載均衡
Dubbo的架構
核心角色:
Provider
Consumer
Registry
Monitor
Container
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL6FEVOVzaU1UNO1WZ6R2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLxIjM5IzNzQTM0EDNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
Dubbo 的使用入門
簡單實踐
1.建立 dubbo-order 項目,同時建立 order-api 和 order-provider 子產品
<!-- pom.xml(dubbo-order) -->
<dependency>
<groupId>com.spring.dubbo.order</groupId>
<artifactId>order-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.13</version>
</dependency>
<!-- pom.xml(order-provider) -->
<dependency>
<groupId>com.spring.dubbo.order</groupId>
<artifactId>order-api</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
2.order-api 子產品
public class DoOrderRequest implements Serializable {
private static final long serialVersionUID = 4296088277401004361L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "DoOrderRequest{" +
"name='" + name + '\'' +
'}';
}
}
public class DoOrderResponse implements Serializable {
private static final long serialVersionUID = 2243774451440109149L;
private Object data;
private String code;
private String memo;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
@Override
public String toString() {
return "DoOrderResponse{" +
"data=" + data +
", code='" + code + '\'' +
", memo='" + memo + '\'' +
'}';
}
}
public interface IOrderService {
/**
* 下單操作
* @param request
* @return
*/
DoOrderResponse doOrder(DoOrderRequest request);
}
3.order-provider 子產品下,resources 下添加日志配置檔案
log4j.rootLogger=info, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
4.如果需要搭配 zookeeper,resources 下添加
/META-INF/spring/order-provider.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd" default-autowire="byName">
<!-- 目前項目在整個分布式架構的唯一名稱,計算依賴關系的标簽 -->
<dubbo:application name="order-provider" owner="spring"/>
<!-- dubbo這個服務所要暴露的服務位址所對應的注冊中心 -->
<!-- 不使用注冊中心<dubbo:registry address="N/A"/>-->
<!-- 使用 zookeeper 來做為注冊中心 -->
<!--<dubbo:registry address="zookeeper://192.168.174.128:2181?backup=192.168.174.129:2181,192.168.174.130:2181"/>-->
<!-- 寫在前面的不一定是leader,等同于下面 -->
<!--<dubbo:registry protocol="zookeeper" address="192.168.174.128:2181,192.168.174.129:2181,192.168.174.130:2181"/>-->
<dubbo:registry address="zookeeper://192.168.174.128:2181"/>
<!-- 目前服務釋出所依賴的協定:webservice,Thrift,Hessian,http -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 服務釋出的配置,需要暴露的服務接口 -->
<dubbo:service interface="com.spring.dubbo.order.IOrderService" ref="orderService"/>
<!-- Bean 的定義 -->
<bean id="orderService" class="com.spring.dubbo.order.OrderServiceImpl"/>
</beans>
5.order-provider 子產品的實作
public class OrderServiceImpl implements IOrderService {
@Override
public DoOrderResponse doOrder(DoOrderRequest request) {
System.out.println("曾經來過:" + request);
DoOrderResponse response = new DoOrderResponse();
response.setCode("1000");
response.setMemo("處理成功");
return response;
}
}
public class App {
public static void main(String[] args) {
Main.main(args);
}
}
6.将 order-api 子產品打包,已被 dubbo-user 使用
7.建立 dubbo-user 項目,同時引入 order-api-1.0-SNAPSHOT.jar
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
public class App {
public static void main( String[] args ) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("order-consumer.xml");
// 使用者下單過程
IOrderService service = (IOrderService) context.getBean("orderService");
DoOrderRequest request = new DoOrderRequest();
request.setName("spring");
DoOrderResponse response = service.doOrder(request);
System.out.println(response);
}
}
8.在 dubbo-user 項目 resources 中添加檔案 order-consumer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 目前項目在整個分布式架構的唯一名稱,計算依賴關系的标簽 -->
<dubbo:application name="order-provider" owner="spring"/>
<!-- 使用 zookeeper,dubbo這個服務所要暴露的服務位址所對應的注冊中心 -->
<dubbo:registry address="zookeeper://192.168.174.128:2181"/>
<!-- 生成一個遠端服務的調用代理 -->
<dubbo:reference id="orderService" interface="com.spring.dubbo.order.IOrderService"/>
<!-- 不使用 zookeeper 時,dubbo:reference 标簽需要添加 url="dubbo://192.168.174.1:20880/com.spring.dubbo.order.IOrderService" -->
</beans>
服務位址分析
啟動 order-provider 時,控制台會列印服務所要暴露的服務位址:
dubbo://192.168.174.1:20880/com.spring.dubbo.order.IOrderService
?anyhost=true&application=order-provider&dubbo=2.5.3&interface=com.spring.dubbo.order.IOrderService&methods=doOrder&owner=spring&pid=15320&side=provider×tamp=1586852986986, dubbo version: 2.5.3, current host: 127.0.0.1
如果使用 zookeeper 時,在 zookeeper 中可以擷取如下的資訊:
dubbo://192.168.174.1/com.spring.dubbo.order.IOrderService
%3Fanyhost%3Dtrue%26application%3Dorder-provider%26dubbo%3D2.5.3%26interface%3Dcom.spring.dubbo.order.IOrderService%26methods%3DdoOrder%26owner%3Dspring%26pid%3D4200%26side%3Dprovider%26timestamp%3D1586856057540
新版 dubbo-admin 控制台的安裝
控制中心是用來做服務治理的,比如控制服務的權重、服務的路由。
1.下載下傳dubbo的源碼(源碼 github 位址,新版 dubbo-admin github 位址)
2.新版 dubbo-admin 分為 dubbo-admin-server 和 dubbo-admin-ui 兩個子產品
3.dubbo-admin-server 為一個 spring boot 項目,可以在
resources/application.properties
中指定注冊中心位址修改(同時可以修改登入的賬号密碼),可通過正常的 spring boot 項目方式啟動
4.dubbo admin ui 由 npm 管理和建構,在開發環境中,可以運作:
npm install
npm run dev
5.頁面通路 通路 http://localhost:8081
simple 監控中心
監控服務的調用次數、調用關系、響應事件,github 位址
Monitor 也是一個dubbo服務,是以也會有端口和url。
1.修改
/conf/dubbo.properties
:
dubbo.registry.address=zookeeper://127.0.0.1:2181
2.修改服務端配置,即 order-provider 的 order-provider.xml:
<dubbo:monitor protocol="registry"/>
telnet
telnet ip port
ls、cd、pwd、clear、invoker
啟動服務檢查
dubbo:reference
屬性:
check
,預設值是true
如果提供方沒有啟動的時候,預設回去檢查所有以來的服務是否正常提供服務。如果 check 為 false,表示啟動的時候不去檢查。當服務出現循環依賴的時候,check 設定成 false。
dubbo:consumer check=false
,關閉所有服務的啟動時檢查:(沒有提供者時報錯)
dubbo:registry check=false
,關閉注冊中心啟動時檢查:(注冊訂閱失敗時報錯)
多協定支援
dubbo 支援的協定:dubbo,RMI,hessian,webservice,http,Thrift
hessian 協定示範
1.引入 jar 包
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.26</version>
</dependency>
2.修改 order-provider.xml 檔案
<!-- 增加 hessian 協定 -->
<dubbo:protocol name="hessian" port="8090" server="jetty"/>
<!-- 指定 service 服務的協定版本号 -->
<dubbo:service interface="com.spring.dubbo.order.IOrderService" ref="orderService" protocol="hessian"/>
3.消費端改造
<!-- 指定引用服務所需要的協定版本 -->
<dubbo:reference id="orderService" interface="com.spring.dubbo.order.IOrderService" protocol="hessian"/>
服務端在 zookeeper 中注冊的服務位址:
hessian://192.168.174.1:8090/com.spring.dubbo.order.IOrderService
多注冊中心支援
<!-- 多注冊中心 -->
<dubbo:registry id="zkOne" address="zookeeper://192.168.174.128:2181"/>
<dubbo:registry id="zkTwo" address="zookeeper://192.168.174.129:2181"/>
<!-- 針對服務指定注冊中心 -->
<dubbo:service interface="com.spring.dubbo.order.IOrderService" ref="orderService" registry="zkOne" />
多版本支援
服務端:
<dubbo:service interface="com.spring.dubbo.order.IOrderService" ref="orderService" version="1.0.0"/>
<dubbo:service interface="com.spring.dubbo.order.IOrderService" ref="orderService2" version="2.0.0"/>
消費端:
dubbo://192.168.174.1:20880/com.spring.dubbo.order.IOrderService?..&version=1.0.0
dubbo://192.168.174.1:20880/com.spring.dubbo.order.IOrderService?..&version=2.0.0
異步調用
消費端,
async="true"
表示接口異步傳回:
<dubbo:reference id="orderService" interface="com.spring.dubbo.order.IOrderService" async="true"/>
<!-- 可單指定某個方法 -->
<!-- <dubbo:method name="doOrder" async="true"/> -->
public class App {
public static void main( String[] args ) throws ExecutionException, InterruptedException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("order-consumer.xml");
// 使用者下單過程
IOrderService service = (IOrderService) context.getBean("orderService");
DoOrderRequest request = new DoOrderRequest();
request.setName("spring");
service.doOrder(request);
Future<DoOrderResponse> response = RpcContext.getContext().getFuture();
DoOrderResponse r = response.get();
System.out.println(r);
}
}
主機綁定
provider://192.168.174.1:20880
org.apache.dubbo.config.ServiceConfig#findConfigedHosts
String hostToBind = getValueFromConfig(protocolConfig, DUBBO_IP_TO_BIND);
if (hostToBind != null && hostToBind.length() > 0 && isInvalidLocalHost(hostToBind)) {
throw new IllegalArgumentException("Specified invalid bind ip from property:" + DUBBO_IP_TO_BIND + ", value:" + hostToBind);
}
if (StringUtils.isEmpty(hostToBind)) {
hostToBind = protocolConfig.getHost();
if (provider != null && StringUtils.isEmpty(hostToBind)) {
hostToBind = provider.getHost();
}
if (isInvalidLocalHost(hostToBind)) {
anyhost = true;
try {
logger.info("No valid ip found from environment, try to find valid host from DNS.");
hostToBind = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
logger.warn(e.getMessage(), e);
}
if (isInvalidLocalHost(hostToBind)) {
if (CollectionUtils.isNotEmpty(registryURLs)) {
for (URL registryURL : registryURLs) {
if (MULTICAST.equalsIgnoreCase(registryURL.getParameter("registry"))) {
// skip multicast registry since we cannot connect to it via Socket
continue;
}
try (Socket socket = new Socket()) {
SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort());
socket.connect(addr, 1000);
hostToBind = socket.getLocalAddress().getHostAddress();
break;
} catch (Exception e) {
logger.warn(e.getMessage(), e);
}
}
}
if (isInvalidLocalHost(hostToBind)) {
hostToBind = getLocalHost();
}
}
}
}
- 通過
配置的位址去找dubbo:protocol host
- hostToBind = InetAddress.getLocalHost().getHostAddress();
- 通過socket發起連接配接連接配接到注冊中心的位址。再擷取連接配接過去以後本地的ip位址
- hostToBind = getLocalHost()
dubbo 服務隻訂閱
dubbo 服務隻注冊
隻提供服務
負載均衡
1.複制一份 dubbo-order 項目,修改端口号
2.同時啟動 兩個 dubbo-order
3.消費端調用
public class App {
public static void main( String[] args ) throws InterruptedException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("order-consumer.xml");
// 使用者下單過程
IOrderService service = (IOrderService) context.getBean("orderService");
DoOrderRequest request = new DoOrderRequest();
request.setName("spring");
for (int i = 0; i < 10; i++){
DoOrderResponse r = service.doOrder(request);
System.out.println(r);
TimeUnit.SECONDS.sleep(1);
}
}
}
負載均衡算法
在叢集負載均衡時,Dubbo 提供了多種均衡政策,預設為 random 随機調用。可以自行擴充負載均衡政策。
Random LoadBalance
(預設)随機,按權重設定随機機率。
在一個截面上碰撞的機率高,但調用量越大分布越均勻,而且按機率使用權重後也比較均勻,有利于動态調整提供者權重。
roundRobin LoadBalance
輪循,按公約後的權重設定輪循比率。存在慢的提供者累積請求的問題,比如:第二台機器很慢,但沒挂,當請求調到第二台時就卡在那,久而久之,所有請求都卡在調到第二台上。
LeastActive LoadBalance
最少活躍調用數,相同活躍數的随機,活躍數指調用前後計數差。使慢的提供者收到更少請求,因為越慢的提供者的調用前後計數差會越大。
Consistent LoadBaleance
一緻性Hash,相同參數的請求總是發到同一提供者。當某一台提供者挂時,原本發往該提供者的請求,基于虛拟節點,平攤到其它提供者,不會引起劇烈變動。
連接配接逾時 timeout
必須要設定服務的處理的逾時時間
叢集容錯
Failover cluster
(預設),失敗的時候自動切換并重試其他伺服器。 通過
retries=2
,來設定重試次數
failfast cluster
快速失敗,隻發起一次調用 ; 寫操作。比如新增記錄的時候, 非幂等請求
failsafe cluster
失敗安全。 出現異常時,直接忽略異常
failback cluster
失敗自動恢複。 背景記錄失敗請求,定時重發
forking cluster
并行調用多個伺服器,隻要一個成功就傳回。 隻能應用在讀請求
broadcast cluster
廣播調用所有提供者,逐個調用。其中一台報錯就會傳回異常
配置的優先級
消費端有限最高,其次服務端
服務改造
1.dubbo-order 項目和其 order-provider 子產品引入 spring 相關 jar 包
dubbo 中已經省缺配置了
org.springframework:spring-context:jar:4.3.10.RELEASE
<dependency>
<groupId>com.spring.dubbo.order</groupId>
<artifactId>order-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework-version}</version>
</dependency>
2.order-provider.xml
<!-- 不需要在xml中引入bean,可以直接通過注解方式引入bean,@Service(value = "orderService") -->
<context:component-scan base-package="com.spring.dubbo.order"/>
3.order-api 添加
resources\META-INF\client\order-customer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd" default-autowire="byName">
<!-- 生成一個遠端服務的調用代理 -->
<dubbo:reference id="orderServiceSpring" interface="com.spring.dubbo.order.IOrderService" protocol="dubbo" version="2.0.0"/>
</beans>
4.建立一個簡單的 springmvc 項目
pom.xml
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<org.springframework-version>4.3.10.RELEASE</org.springframework-version>
<commons-logging-version>1.1.1</commons-logging-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commons-logging-version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.spring.dubbo.order</groupId>
<artifactId>order-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.13</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<!-- web.xml -->
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>dubbo-spring</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/application*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--配置全局方法的攔截-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
<!-- applictionContext.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd" default-autowire="byName">
<context:component-scan base-package="com.spring">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<dubbo:application name="dubbo-spring"/>
<dubbo:registry protocol="zookeeper" address="192.168.174.128:2181"/>
<import resource="classpath*:META-INF/client/order-customer.xml"/>
</beans>
<!-- springmvc.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 掃描 controller -->
<context:component-scan base-package="com.spring.controller" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
<mvc:annotation-driven/>
<!-- 對靜态資源檔案的通路 -->
<mvc:resources location="/system/" mapping="/system/**"/>
<!-- 配置jsp視圖 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
@Controller
@RequestMapping("/home")
public class HomeController {
@Autowired
private UserService userService;
// 按名稱注入,變量名需要與api.jar提供的id相同
@Autowired
IOrderService orderServiceSpring;
@RequestMapping(value = "/index")
public ModelAndView index(){
DoOrderRequest request = new DoOrderRequest();
request.setName("dubbo-spring");
orderServiceSpring.doOrder(request);
userService.insert();
return new ModelAndView("index");
}
}
服務的最佳實踐
分包
- 服務接口,請求服務模型,異常資訊都放在 api 裡面,符合重用釋出等價原則,共同重用原則
- api 裡面放入 spring 的引用配置。也可以放在子產品的包目錄下。com.spring.dubbo.order/***-reference.xml
粒度
- 盡可能把接口設定成粗粒度,每個服務方法代表一個獨立的功能,而不是某個功能的步驟。否則就會涉及到分布式事務
- 服務接口建議以業務場景為機關劃分。并對相近業務做抽象,防止接口暴增
- 不建議使用過于抽象的通用接口,接口沒有明确的語義,帶來後期的維護
版本
- 每個接口都應該定義版本,為後續的相容性提供前瞻性的考慮
- 建議使用兩位版本号,因為第三位版本号表示的相容性更新,隻有不相容時才需要變更服務版本
- 當接口做到不相容更新的時候,先更新一半或者一台提供者為新版本,再将消費全部更新新版本,然後再将剩下的一半提供者更新新版本(預釋出環境)
推薦配置
- 在 provider 端盡可能配置 consumer 端的屬性,比如timeout、retires、線程池大小、LoadBalance
- 配置管理者資訊,application 上面配置的 owner ,owner建議配置2個人以上。因為owner都能夠在監控中心看到
- 配置 dubbo 緩存檔案
配置 dubbo 緩存檔案
<!-- dubbo-spring,消費端配置 -->
<dubbo:registry protocol="zookeeper" file="/Users/spring_zhang/Code/dubbo.cache" address="127.0.0.1:2181"/>
緩存:注冊中心的清單,服務提供者清單
dubbo.cache
#Dubbo Registry Cache
#Thu Apr 16 21:01:06 CST 2020
com.spring.dubbo.order.IOrderService\:2.0.0=empty\://10.1.1.231/com.spring.dubbo.order.IOrderService?application\=dubbo-spring&category\=configurators&dubbo\=2.6.2&interface\=com.spring.dubbo.order.IOrderService&methods\=doOrder&pid\=5340&protocol\=dubbo&revision\=1.0-SNAPSHOT&side\=consumer×tamp\=1587042064681&version\=2.0.0 empty\://10.1.1.231/com.spring.dubbo.order.IOrderService?application\=dubbo-spring&category\=routers&dubbo\=2.6.2&interface\=com.spring.dubbo.order.IOrderService&methods\=doOrder&pid\=5340&protocol\=dubbo&revision\=1.0-SNAPSHOT&side\=consumer×tamp\=1587042064681&version\=2.0.0 dubbo\://10.1.1.231\:20880/com.spring.dubbo.order.IOrderService2?anyhost\=true&application\=order-provider&dubbo\=2.6.2&generic\=false&interface\=com.spring.dubbo.order.IOrderService&methods\=doOrder&owner\=spring&pid\=4201&revision\=2.0.0&side\=provider×tamp\=1587040010193&version\=2.0.0
com.spring.dubbo.user.IUserService=empty\://10.1.1.231/com.spring.dubbo.user.IUserService?application\=dubbo-spring&category\=configurators&dubbo\=2.6.2&interface\=com.spring.dubbo.user.IUserService&methods\=toLogin,login&pid\=5340&revision\=1.0-SNAPSHOT&side\=consumer×tamp\=1587042066209 empty\://10.1.1.231/com.spring.dubbo.user.IUserService?application\=dubbo-spring&category\=routers&dubbo\=2.6.2&interface\=com.spring.dubbo.user.IUserService&methods\=toLogin,login&pid\=5340&revision\=1.0-SNAPSHOT&side\=consumer×tamp\=1587042066209 dubbo\://10.1.1.231\:20881/com.spring.dubbo.user.IUserService?anyhost\=true&application\=user-provider&dubbo\=2.6.2&generic\=false&interface\=com.spring.dubbo.user.IUserService&methods\=toLogin,login&owner\=spring&pid\=4142&side\=provider×tamp\=1587039921924