本節內容會用到之前給大家講過的這兩篇:
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模組是二者的依賴項,並非可執行的程序
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在原有程式碼基礎上保持不變!
既然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 —— 這是唯一的區別!
<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 —— 這是唯一的區別!
這裡我們依然沿用上一節講到的知識——以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又該如何自處?!
圍繞這個問題,又有新的概念誕生了——【限流、熔斷、容錯、服務降級】