微服務-數(shù)據(jù)聚合

數(shù)據(jù)聚合

1.問題

微服務的難點:

微服務將單體服務中功能模塊按功能拆分成多個微服務項目硕旗,已達到功能解耦的目的肠槽。但倡蝙,由于拆分功能同時會將數(shù)據(jù)存儲也進行拆分(甚至有的時候不同的微服務底層使用的數(shù)據(jù)持久化方案不同佛纫,比如:Mysql残吩,MongoDB等)缰趋,前端請求數(shù)據(jù)時可能存證跨服務數(shù)據(jù)返回捧杉。

例:

微服務:訂單服務,用戶服務秘血,CRM服務

前端請求訂單數(shù)據(jù)需要包含訂單數(shù)據(jù)(訂單服務)味抖,訂單負責人信息(用戶服務),客戶信息(CRM服務)灰粮。

2.解決方案:

前端處理

前端請求數(shù)據(jù)后仔涩,根據(jù)數(shù)據(jù)再分別請求其他服務。

例如:

  1. 請求訂單數(shù)據(jù)
  2. 根據(jù)訂單數(shù)據(jù)中的負責人id粘舟,請求用戶服務數(shù)據(jù)
  3. 根據(jù)訂單數(shù)據(jù)中的客戶數(shù)據(jù)熔脂,請求CRM服務數(shù)據(jù)

缺點:

  • 增加前端工作量
  • 增加響應時間佩研。
后端處理

在服務中調用其他服務將數(shù)據(jù)補全,然后返回到前端

例如:

  1. 訂單服務查詢數(shù)據(jù)庫得到訂單數(shù)據(jù)
  2. 根據(jù)訂單數(shù)據(jù)中的負責人id霞揉,請求用戶服務數(shù)據(jù)
  3. 根據(jù)訂單數(shù)據(jù)中的客戶數(shù)據(jù)旬薯,請求CRM服務數(shù)據(jù)
  4. 返回數(shù)據(jù)

缺點:

  • 增加后端工作量
BFF數(shù)據(jù)聚合(本項目采用的解決方案)

在前后端中間增加BFF數(shù)據(jù)聚合服務。

3.數(shù)據(jù)聚合

3.1數(shù)據(jù)聚合過程

sequenceDiagram
前端->>gateway:請求訂單數(shù)據(jù)
gateway->>聚合服務:請求訂單數(shù)據(jù)
聚合服務->>訂單服務:請求訂單數(shù)據(jù)
訂單服務->>聚合服務:返回訂單數(shù)據(jù)
聚合服務->>用戶服務:請求負責人數(shù)據(jù)
用戶服務->>聚合服務:返回負責人數(shù)據(jù)
聚合服務->>CRM服務:請求客戶數(shù)據(jù)
CRM服務->>聚合服務:返回客戶數(shù)據(jù)
聚合服務->>gateway:返回訂單數(shù)據(jù)(數(shù)據(jù)聚合后)
gateway->>前端:返回訂單數(shù)據(jù)(數(shù)據(jù)聚合后)

3.2注解:

Aggregation
  • 使用在方法上适秩,只能使用在Web響應方法上绊序,表示該方法供數(shù)據(jù)聚合調用返回聚合數(shù)據(jù)
  • 使用在集合屬性上,配合AggregationParam使用
  • 使用在類上秽荞,表示類需要在聚合服務中聚合數(shù)據(jù)
@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Aggregation {
    /**
     * 參數(shù)
     * @return
     */
    AggregationParam[] params() default {};
}

AggregationParam

配合Aggregation的屬性上使用

public @interface AggregationParam {
    /**
     * 查詢參數(shù)名
     * @return
     */
    String name();

    /**
     * 查詢參數(shù)引用或者常量值
     * @return
     */
    String value();

    /**
     * 是否是常量
     * @return
     */
    boolean constant() default false;
}
  • name 參數(shù)名骤公,與聚合服務提供接口的參數(shù)一致
  • value 取值
    • 如果constant為true,則為字面值
    • 如果constant為false蚂会,則使用當前對象的名字為value屬性值

例如:

需求側:

public class DepartmentDetail{
    private String id; // 假設id值為D0001
    private String name;
    /** departmentId為服務提供接口的參數(shù)
     *  因為constant為false
     *  value為id淋样,則調用服務提供接口時,參數(shù)為departmentId=D0001
     */
    @Aggregation(params={@AggregationParam(name="departmentId",value="id")})
    private List<UserAggregation> members;
}

提供側:

@Aggregation
public class UserAggregation {
    private String id; // id需要和UserAggregationController的PathVariable對應
    private String name;
    // 省略getter setter
}

@RestController
@RequestMapping("aggregation/users")
public class UserAggregationController {
    @Aggregation
    @GetMapping()
    public List<UserAggregation> getAggregation(
        @RequestParam("departmentId")String departmentId){
        // 返回UserAggregation數(shù)組
    }
}

注意

如果是非空集合則不需要使用@Aggregation

例如:

@Aggregation
public class UserAggregation {
    private String id; // id需要和UserAggregationController的PathVariable對應
    private String name;
    // 省略getter setter constructure
}

@RestController
@RequestMapping("aggregation/users")
public class UserAggregationController {
    @Aggregation
    @GetMapping("{id}")
    public UserAggregation getAggregation(@PathVariable("id")String id){
        // 省略返回UserAggregation
    }
}

public class DepartmentDetail{
    private String id; // 假設id值為D0001
    private String name;
    // members在邏輯中會被添加元素胁住,不需要使用@Aggregation
    // 會調用GET /aggregation/users/{id}
    private List<UserAggregation> members;
}



@RestController
@RequestMapping("departments")
public class DepartmentController{
    @GetMapping("{id}")
    public DepartmentDetail getDepartment(@PathVariable("id")String id){
        DepartmentDetail detail = new DepartmentDetail();
        List<UserAggregation> list = new ArrayList<>();
        list.add(new UserAggregation('U01'));
        list.add(new UserAggregation('U02'));
        list.add(new UserAggregation('U03'));
        detail.setMemebers(list);
        return detail;
    }
}

3.3實現(xiàn)

wy-aggregation-service

實現(xiàn)使用的是Egg框架(node.js)。node 對于IO有好性能刊咳。同時彪见,由于js是弱類型語言,更容易對json數(shù)據(jù)處理娱挨。

3.4示例

用戶服務

@Aggregation
public class UserAggregation {
    private String id; // id需要和UserAggregationController的PathVariable對應
    private String name;
    // 省略getter setter
}

@RestController
@RequestMapping("aggregation/users")
public class UserAggregationController {
    @Aggregation
    @GetMapping("{id}")
    public UserAggregation getAggregation(@PathVariable("id")String id){
        // 省略返回UserAggregation
    }

    @Aggregation
    @GetMapping()
    public List<UserAggregation> getAggregation(
        @RequestParam("departmentId")String departmentId){
        // 返回UserAggregation數(shù)組
    }
}

CRM服務

@Aggregation
public class ClientAggregation {
    private String id;
    private String name;
    // 省略getter setter
}

@RestController
@RequestMapping("aggregation/cleints")
public class CleintAggregationController {
    @Aggregation
    @GetMapping("{id}")
    public ClientAggregation getAggregation(@PathVariable("id")String id){
        // 省略返回ClientAggregation
    }
}

訂單服務

public class Order{
    private String id;
    private String code;
    private UserAggregation admin; // 負責人
    private CleintAggregation client; // 客戶
    // 省略getter setter
}
@RestController
@RequestMapping("orders")
public class OrderController {
    @GetMapping("{id}")
    public Order getOne(@PathVariable("id")String id){
        Order order = new Order();
        order.setAdmin(new UserAggregation('adminId'));// 需要設置adminId
        order.setClient(new ClientAggregation('clientId'));//需要設置clientId
        return order;
    }
}

4.代碼

https://gitee.com/wenyu7980/wy-aggregation
https://gitee.com/wenyu7980/wy-aggregation-service

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末余指,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子跷坝,更是在濱河造成了極大的恐慌酵镜,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柴钻,死亡現(xiàn)場離奇詭異淮韭,居然都是意外死亡,警方通過查閱死者的電腦和手機贴届,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門靠粪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人毫蚓,你說我怎么就攤上這事占键。” “怎么了元潘?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵畔乙,是天一觀的道長。 經(jīng)常有香客問我翩概,道長牲距,這世上最難降的妖魔是什么袖订? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮嗅虏,結果婚禮上洛姑,老公的妹妹穿的比我還像新娘。我一直安慰自己皮服,他們只是感情好楞艾,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著龄广,像睡著了一般硫眯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上择同,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天两入,我揣著相機與錄音,去河邊找鬼敲才。 笑死裹纳,一個胖子當著我的面吹牛,可吹牛的內容都是我干的紧武。 我是一名探鬼主播剃氧,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼阻星!你這毒婦竟也來了朋鞍?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤妥箕,失蹤者是張志新(化名)和其女友劉穎滥酥,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體畦幢,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡坎吻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了呛讲。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片禾怠。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖贝搁,靈堂內的尸體忽然破棺而出吗氏,到底是詐尸還是另有隱情,我是刑警寧澤雷逆,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布弦讽,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏往产。R本人自食惡果不足惜被碗,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仿村。 院中可真熱鬧锐朴,春花似錦、人聲如沸蔼囊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽畏鼓。三九已至酱酬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間云矫,已是汗流浹背膳沽。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留让禀,地道東北人挑社。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像堆缘,于是被迫代替她去往敵國和親滔灶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內容

  • 當我傻啊麻车,用戶在電商網(wǎng)站購買成功缀皱,還在微服務中,那肯定就是有一套微服務架構的電商系統(tǒng)动猬。 設計一套電商系統(tǒng)還不簡單 ...
    360linker閱讀 1,996評論 3 13
  • https://learnku.com/articles/36303要理解微服務啤斗,首先要先理解不是微服務的那些。通...
    mick_閱讀 408評論 1 9
  • 一文詳解微服務架構 轉載請注明出處:https://www.cnblogs.com/skabyy/p/113965...
    hadoop_qin閱讀 76評論 0 1
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月赁咙,有人笑有人哭钮莲,有人歡樂有人憂愁,有人驚喜有人失落彼水,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,536評論 28 53
  • 信任包括信任自己和信任他人 很多時候崔拥,很多事情,失敗凤覆、遺憾链瓦、錯過,源于不自信,不信任他人 覺得自己做不成慈俯,別人做不...
    吳氵晃閱讀 6,190評論 4 8