dubbo-gateway 高性能dubbo網關

dubbo-gateway

dubbo-gateway 提供了http協議到dubbo協議的轉換,但【並非】使用dubbo的【泛化】調用(泛化調用性能比普通調用有10-20%的損耗,通過普通非同步的調用方式與基於webflux系列的響應式網關整合提高系統的吞吐量,普通調用需要依賴api jar包,需要對介面定義進行改造,除此之外不需要做任何其它改造.另外也支援基於servlet類的應用或網關進行整合

泛化缺點

  • 泛化過程數據流會經過了三次轉換, 會產生大量的臨時對象, 有很大的記憶體要求。使用反射方式對於旨在榨乾伺服器性能以獲取高吞吐量的系統來說, 難以達到性能最佳
  • 同時服務端也會對泛化請求多一重 Map <-> POJO 的來迴轉換的過程。整體上,與普通的Dubbo調用相比有10-20%的損耗
  • 泛化調用在網關或服務消費者階段無法校驗參數類型的有效性,數據要到服務提供者反序列化時才能校驗出參數類型的有效性

開源地址

開源地址

相關註解

@GateWayDubbo

標識這個介面需要自動進行協議轉換

/**
 * 服務id,可以和dubbo普通調用的配置屬性關聯.
 */
@AliasFor("id")
String value() default "";

/**
 * 服務id,可以和dubbo普通調用的配置屬性關聯.
 * 例如: 
		com.atommiddleware.cloud.config.dubboRefer.<userService>.version=1.1.0
		com.atommiddleware.cloud.config.dubboRefer.<userService>.group=userSystem
		以上相當於會調用版本號為1.1.0並且groupw為userSystem的dubbo服務,與@DubboReference的參數對齊,具體支援哪些參數詳見配置類DubboReferenceConfigProperties
 */
@AliasFor("value")
String id() default "";

@PathMapping

標記這個介面方法需要進行協議自動轉換

/**
 * 路徑表達式
 */
@AliasFor("path")
String value() default "";

/**
 * 路徑表達式
 */
@AliasFor("value")
String path() default "";

/**
 * 提交方法,GET或POST
 */
RequestMethod requestMethod() default RequestMethod.POST;

public enum RequestMethod {
	GET, POST

}

@FromBody

表示參數對象來源於消息體

/**
 * 是否檢查參數
 */
@AliasFor(annotation = ParamAttribute.class)
boolean required() default true;

@FromHeader

表示參數對象來源於消息頭

/**
 * 消息頭名稱
 */
@AliasFor(annotation = ParamAttribute.class)
String value() default "";

/**
 * 消息頭名稱
 */
@AliasFor(annotation = ParamAttribute.class)
String name() default "";

/**
 * 是否檢查參數
 */
@AliasFor(annotation = ParamAttribute.class)
boolean required() default true;

@FromCookie

表示參數對象來源於cookie

/**
 * cookie名稱
 */
@AliasFor(annotation = ParamAttribute.class)
String value() default "";

/**
 * cookie名稱
 */
@AliasFor(annotation = ParamAttribute.class)
String name() default "";

/**
 * 是否檢查參數
 */
@AliasFor(annotation = ParamAttribute.class)
boolean required() default true;

@FromPath

表示參數對象來源於path,支援path表達式

/**
 * path佔位符名稱
 */
@AliasFor(annotation = ParamAttribute.class)
String value() default "";

/**
 * path佔位符名稱
 */
@AliasFor(annotation = ParamAttribute.class)
String name() default "";

/**
 * 是否檢查參數
 */
@AliasFor(annotation = ParamAttribute.class)
boolean required() default true;

@FromQueryParams

表示參數來源於query部分

/**
 * query名稱
 */
@AliasFor(annotation = ParamAttribute.class)
String value() default "";

/**
 * query名稱
 */
@AliasFor(annotation = ParamAttribute.class)
String name() default "";

/**
 * 是否檢查參數
 */
@AliasFor(annotation = ParamAttribute.class)
boolean required() default true;

@FromAttribute

表示參數來源於attribute

/**
 * attribute 名稱
 */
@AliasFor(annotation = ParamAttribute.class)
String value() default "";

/**
 * attribute 名稱
 */
@AliasFor(annotation = ParamAttribute.class)
String name() default "";

/**
 * 是否檢查參數
 */
@AliasFor(annotation = ParamAttribute.class)
boolean required() default true;

配置示例

@GateWayDubbo("userService")
public interface UserService {
/**
 * 數據來源消息體
 */
@PathMapping("/sample/registerUser")
Result registerUser(@FromBody User user);
/**
 * 對象數據源來自header
 * @param user 用戶資訊
 * @return 結果
 */
@PathMapping(value="/sample/registerUserFromHeader",requestMethod=RequestMethod.GET)
Result registerUserFromHeader(@FromHeader("user") User user);
/**
 * 對象數據源來自cookie
 * @param user 用戶資訊
 * @return 結果
 */
@PathMapping(value="/sample/registerUserFromCookie",requestMethod=RequestMethod.GET)
Result registerUserFromCookie(@FromCookie("user") User user);
/**
 * 對象數據源來自path
 * @param user 用戶資訊
 * @return 結果
 */
@PathMapping(value="/sample/registerUserFromPath/{user}",requestMethod=RequestMethod.GET)
Result registerUserFromPath(@FromPath("user") User user);
/**
 * 數據來源queryParam
 * @param userId 用戶id
 * @return 取消註銷結果
 */
@PathMapping(value="/sample/unRegisterUser",requestMethod=RequestMethod.GET)
Result unRegisterUser(@FromQueryParams("userId")Long userId);
/**
 * 數據來源path
 * @param userId
 * @return
 */
@PathMapping(value="/sample/getUserInfo/{userId}/{gender}",requestMethod=RequestMethod.GET)
Result getUserInfo(@FromPath("userId") Long userId,@FromPath("gender") Short gender);
/**
 * 數據來源header 和cookie
 * @param userId 用戶id
 * @param age 年齡
 * @return 返回插敘結果
 */
@PathMapping(value="/sample/getUserInfo/byHeaderAndCookie",requestMethod=RequestMethod.GET)
Result getUserInfo(@FromHeader("userId")Long userId,@FromCookie("age")Integer age);

/**
 * 全場景
 * @param userId 用戶id
 * @param age 年齡
 * @param gender 性別
 * @param user 用戶資訊
 * @return 查詢結果
 */
@PathMapping("/sample/getUserUserInfoAll/{userId}")
Result getUserUserInfoAll(@FromPath("userId") Long userId,@FromCookie("age")Integer age,@FromHeader("gender")Long gender,@FromBody User user);
}

使用步驟

第一步:按照示例改造api介面,介面需要引入dubbo-gateway-api jar包

  	<dependency>
		<groupId>com.atommiddleware</groupId>
		<artifactId>dubbo-gateway-api</artifactId>
		<version>1.0.5</version>
	</dependency>

第二步:網關引入改造後的jar包,同時引用以下jar包

`	<dependency>
		<groupId>com.atommiddleware</groupId>
		<artifactId>dubbo-gateway-spring-boot-starter</artifactId>
		<version>1.0.5</version>
	</dependency>`

第三步:沒有了。。就是這麼簡單

項目說明

  • dubbo-gateway-api 是核心的api,相關註解都是在此項目中定義
  • dubbo-gateway-core 核心實現,實現dubbo-gateway的相關邏輯都在此項目中
  • dubbo-gateway-spring-boot-autoconfigure dubbo-gateway的自動裝配
  • dubbo-gateway-spring-boot-starter dubbo-gateway的starter
  • dubbo-gateway-sample-api 示例服務api定義在此項目中
  • dubbo-gateway-sample-provider 基於spring cloud的dubbo 服務提供者示例
  • dubbo-gateway-sample 基於webflux(spring cloud gateway、zuul2)的接入dubbo-gateway示例
  • dubbo-gateway-sample-web-provider 基於sevlet類型的dubbo服務提供者示例
  • dubbo-gateway-sample-web-consumer 基於sevlet類型的項目(包括網關比如zuul-1)接入dubbo-gateway示例

配置中心

按照dubbo的正常接入配置進行配置就好了,以下貼出例子使用的配置在nacos配置中心的配置,其中filters使用了Dubbo作為過濾器

服務提供者配置:

dubbo:
  protocol:
    name: dubbo
    port: 20861
server:
  port: 8861
spring:
  cloud:
    nacos:
      discovery:
        namespace: dev
        server-addr: 127.0.0.1:8848

服務消費者配置:

dubbo:
  cloud:
    subscribed-services: dubbo-gateway-sample-provider
server:
  port: 8862
spring:
  cloud:
    nacos:
      discovery:
        namespace: dev
        server-addr: 127.0.0.1:8848
    gateway:
      routes:
      - id: myGateway
        uri: //127.0.0.1:8862
        predicates:
        - Path=/**
        filters:
        - Dubbo

注意:其中filters下面配的”Dubbo”表示使用的是DubboGatewayFilter去處理,如果不配置則不會生效.

其它說明

基於webflux的網關與基於servlet類的web應用接入整合方式是一樣的步驟,例子使用的nacos版本2.0.3,如果需要在cookie,header,url,傳遞複雜參數【非java基本類型】,需先將參數轉為json,然後使用UrlEncode進行編碼,js中可以使用encodeURIComponent進行編碼