02 玩轉Dubbo,Dubbo配置參數說明,及使用場景總結

說明:內容主要來至於官方文檔

官方文檔地址: https://dubbo.apache.org/

配置優先級:

Dubbo支持的配置來源,默認有四種配置來源:

  • JVM System Properties,-D參數
  • Externalized Configuration,外部化配置
  • ServiceConfig、ReferenceConfig等編程接口採集的配置
  • 本地配置文件dubbo.properties,在Springboot中application.yml中也可以配置,dubbo-spring-boot-starter做了支持

配置的粒度說明:

dubbo的很多配置粒度可以細化到方法級別,也可以粗放到一個接口(接口又分爲消費者、調用者),甚至可以粗放到所有消費者和服務提供者。

通過上面圖,我們知道針對Dubbo配置的優先級、以及配置的粒度,那麼接一下我對配置的說明都針對@Service、@Reference註解來進行配置。

1、啓動依賴檢查,啓動檢查作用:在服務啓動時檢查可用性,讓服務問題儘早暴露出來。

    /** 可以在指定的接口中設置是否檢查可用性 */
	@Reference(check = true)
	private DemoService demoService;

可以在註解上針對某個服務設置啓動時

或者在 application.yml中可以配置

spring:
  application:
    name: hello-api
    
dubbo:
  # 指定註冊中心
  registry:
    address: zookeeper://192.168.50.220:2181
  # 指定消費者,提供者所在的包路徑
  scan:
    base-packages:
    - com.example.demo.web
  # 設置消費者啓動時不檢查服務可用性,默認是true,需要檢查可用性,建議開啓
  consumer:
    check: true

改配置是針對消費者啓動時,是否進行服務可用性檢查,當然也可以在配置中針對指定服務進行配置,但是不建議那樣配置!至於爲什麼?可以自己想想的。

2、集羣容錯

集羣容錯:我理解的是,保證服務調用可用性,及爲集羣容錯

dubbo提供了多種集羣容錯方案,默認爲failover。

Failover Cluster

失敗自動切換,當出現失敗,重試其它服務器 [1]。通常用於讀操作,但重試會帶來更長延遲。可通過 retries="2" 來設置重試次數(不含第一次)。

重試次數配置如下:

	@Reference(retries = 1)
	private DemoService demoService2;

或者 針對方法進行配置

	@Reference(methods = { @Method(name = "sayHello", retries = 1) })
	private DemoService demoService2;

或者 配置中針對所有提供者

dubbo:
  provider:
    retries: 1

更多配置方式參考官方文檔: https://dubbo.apache.org/zh-cn/docs/user/demos/fault-tolerent-strategy.html

Failfast Cluster

快速失敗,只發起一次調用,失敗立即報錯。通常用於非冪等性的寫操作,比如新增記錄。

	@Reference(cluster = "failfast")
	private DemoService demoService3;

代碼說明:cluster的值,可以點到註解的cluster方法上查看。

Failsafe Cluster

失敗安全,出現異常時,直接忽略。通常用於寫入審計日誌等操作。

Failback Cluster

失敗自動恢復,後臺記錄失敗請求,定時重發。通常用於消息通知操作。

Forking Cluster

並行調用多個服務器,只要一個成功即返回。通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。可通過 forks="2" 來設置最大並行數。

    @Reference(cluster = "forking")
    private DemoService demoService;

我沒有在註解中找到: forks這個配置參數

Broadcast Cluster

廣播調用所有提供者,逐個調用,任意一臺報錯則報錯 [2]。通常用於通知所有提供者更新緩存或日誌等本地資源信息。

 

3、負載均衡

    @Reference(loadbalance = "random")
    private DemoService demoService3;

Random LoadBalance

  • 隨機,按權重設置隨機概率。
  • 在一個截面上碰撞的概率高,但調用量越大分佈越均勻,而且按概率使用權重後也比較均勻,有利於動態調整提供者權重。

RoundRobin LoadBalance

  • 輪詢,按公約後的權重設置輪詢比率。
  • 存在慢的提供者累積請求的問題,比如:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,久而久之,所有請求都卡在調到第二臺上。

LeastActive LoadBalance

  • 最少活躍調用數,相同活躍數的隨機,活躍數指調用前後計數差。
  • 使慢的提供者收到更少請求,因爲越慢的提供者的調用前後計數差會越大。

ConsistentHash LoadBalance

  • 一致性 Hash,相同參數的請求總是發到同一提供者。
  • 當某一臺提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動。
  • 算法參見:http://en.wikipedia.org/wiki/Consistent_hashing
  • 缺省只對第一個參數 Hash,如果要修改,請配置 <dubbo:parameter key="hash.arguments" value="0,1" />
  • 缺省用 160 份虛擬節點,如果要修改,請配置 <dubbo:parameter key="hash.nodes" value="320" />

從官網的配置看,存在4中負載均衡策略,但是從配置中看是3中配置,一致性Hash不再,需要專題看看這個問題。以及自定義負載均衡器。

    /**
     * Load balance strategy, legal values include: random, roundrobin, leastactive
     *
     * see Constants#DEFAULT_LOADBALANCE
     */
    String loadbalance() default "";

4、直連、只訂閱

這兩種方式的組合,正好支持本地開發調試的操作。

只訂閱配置:

dubbo:
  registry:
    address: zookeeper://192.168.50.220:2181
    register: false

直連配置:

	@Reference(url = "dubbo://192.168.50.30:12345")
	private DemoService demoService;

4、只註冊

如果有兩個鏡像環境,兩個註冊中心,有一個服務只在其中一個註冊中心有部署,另一個註冊中心還沒來得及部署,而兩個註冊中心的其它應用都需要依賴此服務。這個時候,可以讓服務提供者方只註冊服務到另一註冊中心,而不從另一註冊中心訂閱服務。

目的:讓另一個註冊中心的其他服務可以使用該服務,但是該服務運行時所需要的服務不從另一個註冊中心訂閱。

基於application.yml的多註冊中心支持配置: https://blog.csdn.net/q258523454/article/details/103481326

5、多協議暴露

Dubbo 允許配置多協議,在不同服務上支持不同協議或者同一服務上同時支持多種協議。

不同服務在性能上適用不同協議進行傳輸,比如大數據用短連接協議,小數據大併發用長連接協議

一個服務也可以同時暴露多種協議。

基於application.yml的多協議暴露配置: https://blog.csdn.net/u013887008/article/details/89738398 

6、多註冊中心配置

支持一個服務同時註冊到多個註冊中心

支持不同的服務從不同的註冊到不同的註冊中心。

支持不同服務從不同的註冊中心註冊。

多註冊中心配置,豎號分隔表示同時連接多個不同註冊中心,同一註冊中心的多個集羣地址用逗號分隔

7、服務分組

當一個接口有多種實現時,可以用 group 區分。

@Service(group = "message")
public class DemoServiceImpl implements DemoService {
	
	private final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
	
	@Override
	public String sayHello(String name) {
		logger.info("welcome {}", name);
		return name + ", hi";
	}

}

8、多版本

當一個接口實現,出現不兼容升級時,可以用版本號過渡,版本號不同的服務相互間不引用。

可以按照以下的步驟進行版本遷移:

  1. 在低壓力時間段,先升級一半提供者爲新版本
  2. 再將所有消費者升級爲新版本
  3. 然後將剩下的一半提供者升級爲新版本

9、分組聚合

基於註解不支持聚合!!!!

10、回聲檢查

回聲測試用於檢測服務是否可用,回聲測試按照正常請求流程執行,能夠測試整個調用是否通暢,可用於監控。

所有服務自動實現 EchoService 接口,只需將任意服務引用強制轉型爲 EchoService,即可使用。

package com.example.demo.web;

import java.util.List;

import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.rpc.service.EchoService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.hello.service.DemoService;


@RestController
public class TestController {

	@Reference
	private DemoService demoService;

	@GetMapping("/test")
	public String hello(String name) {
		EchoService echoService = (EchoService) demoService;
		Object status = echoService.$echo("hello");
		System.out.println("回聲檢查:" + status);
		return demoService.sayHello(name);
	}
	
	
}

11、參數回調

參數回調方式與調用本地 callback 或 listener 相同,只需要在 Spring 的配置文件中聲明哪個參數是 callback 類型即可(註解中指明也可以)。Dubbo 將基於長連接生成反向代理,這樣就可以從服務器端調用客戶端邏輯。

示例:以創建訂單爲例,創建完成後回調調用方,告知最終狀態。

定義回調接口:

package com.example.hello.service.callback;

@FunctionalInterface
public interface CreatedOrderCallback {
	Boolean done(Integer orderId, Integer orderStatus);
}

定義創建訂單接口:

package com.example.hello.service;

import com.example.hello.service.callback.CreatedOrderCallback;

public interface CreateOrderService {
	Integer createdOrder(Integer id, Integer count, CreatedOrderCallback callback);
}

服務提供者 - 實現創建訂單:

package com.example.demo.provider.service;

import org.apache.dubbo.config.annotation.Argument;
import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.annotation.Service;

import com.example.hello.service.CreateOrderService;
import com.example.hello.service.callback.CreatedOrderCallback;

@Service(callbacks = 1000, connections = 1, methods = { 
		@Method(name = "createdOrder", arguments = {
				@Argument(index = 2, callback = true)
		}) 
	}
)
public class CreateOrderServiceImpl implements CreateOrderService {

	@Override
	public Integer createdOrder(Integer id, Integer count, CreatedOrderCallback callback) {
		System.out.println("created, id: " + id + ", count: " + count);
		// 可以先將callback示例存儲起來,可以在異步處理後進行callback,執行這個回調
		callback.done(id, -10);
		return id;
	}

}

註解說明: 配置callbacks的超時時間,通過methods定義方法配置,通過Method的arguments指定參數配置,在參數配置中指定第幾個參數是回調對象,index從0開始,callback設置爲true

服務消費者-調用方實現

    @Reference
    private CreateOrderService createOrderService;
	
    @GetMapping("/order")
    public Integer order(Integer id, Integer count) {
        return createOrderService.createdOrder(id, count, (orderId, status) -> {
            System.out.println("callback success, orderId: " + orderId + ", status: " + status);
            return Boolean.TRUE;
        });
    }

執行結果:

12、本地存根,類似Feign的異常Handler

基於【參數回調】中的例子,進行測試

新建CreateOrderServiceStub.java,用於本地存根處理,該代碼放到公共Jar中

package com.example.hello.service.stub;

import com.example.hello.service.CreateOrderService;
import com.example.hello.service.callback.CreatedOrderCallback;

public class CreateOrderServiceStub implements CreateOrderService {

	private final CreateOrderService createOrderService;

	public CreateOrderServiceStub(CreateOrderService createOrderService) {
		this.createOrderService = createOrderService;
	}

	@Override
	public Integer createdOrder(Integer id, Integer count, CreatedOrderCallback callback) {
		// 此代碼在客戶端執行, 你可以在客戶端做ThreadLocal本地緩存,或預先驗證參數是否合法,等等
		try {
			return createOrderService.createdOrder(id, count, callback);
		} catch (Exception e) {
			System.out.println(e.getMessage());
			// 你可以容錯,可以做任何AOP攔截事項
			return -1;
		}
	}

}

說明:

  1. Stub 必須有可傳入 Proxy 的構造函數。 ↩︎

  2. 在 interface 旁邊放一個 Stub 實現,它實現 BarService 接口,並有一個傳入遠程 BarService 實例的構造函

 

服務提供者,修改一下註解配置

package com.example.demo.provider.service;

import org.apache.dubbo.config.annotation.Argument;
import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.annotation.Service;

import com.example.hello.service.CreateOrderService;
import com.example.hello.service.callback.CreatedOrderCallback;

@Service(callbacks = 1000, connections = 1, methods = { 
			@Method(name = "createdOrder", arguments = {
					@Argument(index = 2, callback = true)
			}) 
		}, stub = "com.example.hello.service.stub.CreateOrderServiceStub"
)
public class CreateOrderServiceImpl implements CreateOrderService {

	@Override
	public Integer createdOrder(Integer id, Integer count, CreatedOrderCallback callback) {
		System.out.println("created, id: " + id + ", count: " + count);
		// 這一步callback操作,可以在異步處理後,執行這個回調
		callback.done(id, -10);
		if(id.intValue() == -100) {
			throw new RuntimeException("任性的異常拋出");
		}
		return id;
	}

}

說明: @Service註解上新增stub屬性,指定stub的實現類的類名

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章