dubbo-gateway
dubbo-gateway 提供了http協議到dubbo協議的轉換,但【並非】使用dubbo的【泛化】呼叫(泛化呼叫效能比普通呼叫有10-20%的損耗,通過普通非同步的呼叫方式與基於webflux系列的響應式閘道器整合提高系統的吞吐量,普通呼叫需要依賴api jar包,需要對介面定義進行改造,除此之外不需要做任何其它改造.另外也支援基於servlet類的應用或閘道器進行整合
泛化缺點
- 泛化過程資料流會經過了三次轉換, 會產生大量的臨時物件, 有很大的記憶體要求。使用反射方式對於旨在榨乾伺服器效能以獲取高吞吐量的系統來說, 難以達到效能最佳
- 同時服務端也會對泛化請求多一重 Map <-> POJO 的來回轉換的過程。整體上,與普通的Dubbo呼叫相比有10-20%的損耗
- 泛化呼叫在閘道器或服務消費者階段無法校驗引數型別的有效性,資料要到服務提供者反序列化時才能校驗出引數型別的有效性
開源地址
開源地址
https://github.com/smallbeanteng/dubbo-gateway
相關注解
@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: http://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進行編碼