2流高手速成記(之七):基於Dubbo&Nacos的微服務簡要實現

2022-11-04 06:01:33

本節內容會用到之前給大家講過的這兩篇:

2流高手速成記(之六):從SpringBoot到SpringCloudAlibaba

2流高手速成記(之三):SpringBoot整合mybatis/mybatis-plus實現資料持久化

連結掛出來,方便咱們中途對比著看

老規矩,先放出本節的專案結構:

 

 

我們參考上一節中講到的建立SpringCloudAlibaba工程模板的步驟,在工程下在建立三個子模組,建立過程中勾選相同的依賴項

 

 

這三個子模組也是三個獨立的可執行的工程,他們的用途分別為:

dubbo-nacos-provider:服務(Service)提供方

dubbo-nacos-consumer:消費方,服務的呼叫者

dubbo-nacos-api:介面及模型類定義,同時作為前邊二者的依賴方

接下來,我們共同見證神奇的一幕:

大家都知道,我們在第三節中實現的工程是一個結構相對完備(包含Service、Controller,View由Postman替代)且可以直接執行的獨立程序

本節我們依靠上一節講到的微服務技術,以幾乎不改變原有程式碼為前提,將其一分為三:

provider和consumer分別獨立執行

consumer藉助微服務技術完成對provider的呼叫

api模組是二者的依賴項,並非可執行的程序

1. Service介面、Model宣告遷移到dubbo-nacos-api

 

 

package com.example.dubbonacosapi.model;

import java.io.Serializable;

public class Person implements Serializable {
    private Integer id = 0;

    private String name = "";

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package com.example.dubbonacosapi.service;

import com.example.dubbonacosapi.model.Person;

import java.util.List;

public interface PersonService {
    Integer insert(Person person);

    Integer update(Person person);

    Integer delete(int id);

    List<Person> select();
}

因為api的作用僅是構成provider、consumer的二者依賴,所以其僅是持有相關宣告即可

Person類及PersonService在原有程式碼基礎上保持不變!

2. Service介面實現類、Mapper宣告(mybatis-plus)遷移到dubbo-nacos-provider

 

 

既然provider保有mybatis-plus存取mysql的能力,所以相關的依賴必定不可或缺

        <!-- 引入mybatis、mybatis-plus、mysql等依賴 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>com.example</groupId>
            <artifactId>dubbo-nacos-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

引入的方式和第三節講到的方式一樣

此外還包含了對於剛才我們建立的dubbo-nacos-api的依賴,引入非常的方便

package com.example.dubbonacosprovider.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.dubbonacosapi.model.Person;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Mapper
@Repository
public interface PersonMapper extends BaseMapper<Person> {
}
package com.example.dubbonacosprovider.service.impl;

import com.example.dubbonacosapi.model.Person;
import com.example.dubbonacosapi.service.PersonService;
import com.example.dubbonacosprovider.mapper.PersonMapper;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

@DubboService
public class PersonServiceImpl implements PersonService {

    @Autowired
    PersonMapper mapper;

    public Integer insert(Person person) {
        return mapper.insert(person);
    }

    public Integer update(Person person) {
        return mapper.updateById(person);
    }

    public Integer delete(int id) {
        return mapper.deleteById(id);
    }

    public List<Person> select() {
        return mapper.selectList(null);
    }
}

Mapper的宣告沒有任何變化,而PersonServiceImpl依然保有對介面PersonService的實現,區別在於後者來自api模組

唯一的區別在於PesonServiceImpl類的註解,由原有的@Service變更為@DubboService —— 這是唯一的區別!

3. Controller遷移到dubbo-nacos-consumer

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.example</groupId>
            <artifactId>dubbo-nacos-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

consumer作為外部可存取的web服務,自然需要持有web相關依賴項

同時,與provicer相同,其與api模組保持依賴關係

 

 

package com.example.dubbonacosconsumer.controller;

import com.example.dubbonacosapi.model.Person;
import com.example.dubbonacosapi.service.PersonService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/person")
public class PersonController {
    @DubboReference
    PersonService service;

    @PostMapping("/insert")
    public Integer insert(Person person) {
        return service.insert(person);
    }

    @PostMapping("/update")
    public Integer update(Person person) {
        return service.update(person);
    }

    @PostMapping("/delete")
    public Integer delete(int id) {
        return service.delete(id);
    }

    @GetMapping("/select")
    public List<Person> select() {
        return service.select();
    }
}

留意PersonService的引入方式:不再是@Autowired,而是變更為@DubboReference —— 這是唯一的區別!

4. Consumer和Provider的設定項

這裡我們依然沿用上一節講到的知識——以nacos作為設定中心

二者同時僅在本地保留一個bootstrap.properties組態檔,application.properties託管給nacos

 

 

# Nacos幫助檔案: https://nacos.io/zh-cn/docs/concepts.html
# Nacos認證資訊
spring.cloud.nacos.config.username=nacos
spring.cloud.nacos.config.password=nacos
spring.cloud.nacos.config.contextPath=/nacos
# 設定設定中心伺服器端地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# Nacos 設定中心的namespace。需要注意,如果使用 public 的 namcespace ,請不要填寫這個值,直接留空即可
# spring.cloud.nacos.config.namespace=

# 應用名稱
spring.application.name=dubbo-nacos-consumer
# Nacos幫助檔案: https://nacos.io/zh-cn/docs/concepts.html
# Nacos認證資訊
spring.cloud.nacos.config.username=nacos
spring.cloud.nacos.config.password=nacos
spring.cloud.nacos.config.contextPath=/nacos
# 設定設定中心伺服器端地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# Nacos 設定中心的namespace。需要注意,如果使用 public 的 namcespace ,請不要填寫這個值,直接留空即可
# spring.cloud.nacos.config.namespace=

# 應用名稱
spring.application.name=dubbo-nacos-provider

內容均為nacos相關設定,以及各自宣告了自己的應用名稱(spring.application.name)

然後是他們在nacos上託管的設定資料:

 

 

 注意,新建立設定的Data Id需要與他們的應用名稱同名

 

 

 provider需要持有mysql相關設定

 

consumer作為controller的持有者,需要宣告外部的可存取埠

全部的移植工作到這裡就完畢了!

我們分別執行provider、consumer兩個獨立程序

此時我們開啟nacos服務列表,會看到dubbo-nacos-consumer、dubbo-nacos-provider兩個執行中的服務

 

 執行結果如下:

 

怎麼樣?是不是非常神奇?我們只改動了兩個註解,原本還是一個整體的工程就被一分為二了,並且是兩個可以彼此獨立運轉在兩臺獨立機器上的服務

—— 這就是微服務的神奇之處!

藉助於強大的SpringCloudAlibaba,我們不僅可以對所有的業務實現統合拆分,充分調動團隊人員設定各司其職各自編寫自己的服務模組,

更大的意義在於我們可以充分調動多臺獨立裝置的技能,使之串聯為一個龐大服務叢集,較之於單臺機器實現整個架構效能成千上萬倍的飛躍!

但是,微服務帶來研發、管理、效能便捷的同時,整個叢集也在運維層面面對了前所未有的挑戰,最明顯的:

consumer在業務上依賴於後端的provider,如果provider運轉不正常,前方的consumer又該如何自處?!

圍繞這個問題,又有新的概念誕生了——【限流、熔斷、容錯、服務降級】

Sentinel要來咯~ 敬請期待!
properties