微服務調用

01-SpringCloud相關概念介紹

一、什麼是微服務

1、微服務的由來

微服務最早由Martin Fowler與James Lewis於2014年共同提出,微服務架構風格是一種使用一套小服務來開發單個應用的方式途徑,每個服務運行在自己的進程中,並使用輕量級機制通信,通常是HTTP API,這些服務基於業務能力構建,並能夠通過自動化部署機制來獨立部署,這些服務使用不同的編程語言實現,以及不同數據存儲技術,並保持最低限度的集中式管理。

2、爲什麼需要微服務

在傳統的IT行業軟件大多都是各種獨立系統的堆砌,這些系統的問題總結來說就是擴展性差,可靠性不高,維護成本高。到後面引入了SOA服務化,但是,由於 SOA 早期均使用了總線模式,這種總線模式是與某種技術棧強綁定的,比如:J2EE。這導致很多企業的遺留系統很難對接,切換時間太長,成本太高,新系統穩定性的收斂也需要一些時間。

3、微服務與單體架構區別

(1)單體架構所有的模塊全都耦合在一塊,代碼量大,維護困難。

​ 微服務每個模塊就相當於一個單獨的項目,代碼量明顯減少,遇到問題也相對來說比較好解決。

(2)單體架構所有的模塊都共用一個數據庫,存儲方式比較單一。

​ 微服務每個模塊都可以使用不同的存儲方式(比如有的用redis,有的用mysql等),數據庫也是單個模塊對應自己的數據庫。

(3)單體架構所有的模塊開發所使用的技術一樣。

​ 微服務每個模塊都可以使用不同的開發技術,開發模式更靈活。

4、微服務本質

(1)微服務,關鍵其實不僅僅是微服務本身,而是系統要提供一套基礎的架構,這種架構使得微服務可以獨立的部署、運行、升級,不僅如此,這個系統架構還讓微服務與微服務之間在結構上“鬆耦合”,而在功能上則表現爲一個統一的整體。這種所謂的“統一的整體”表現出來的是統一風格的界面,統一的權限管理,統一的安全策略,統一的上線過程,統一的日誌和審計方法,統一的調度方式,統一的訪問入口等等。
(2)微服務的目的是有效的拆分應用,實現敏捷開發和部署 。
(3)微服務提倡的理念團隊間應該是 inter-operate, not integrate 。inter-operate是定義好系統的邊界和接口,在一個團隊內全棧,讓團隊自治,原因就是因爲如果團隊按照這樣的方式組建,將溝通的成本維持在系統內部,每個子系統就會更加內聚,彼此的依賴耦合能變弱,跨系統的溝通成本也就能降低。

5、什麼樣的項目適合微服務

微服務可以按照業務功能本身的獨立性來劃分,如果系統提供的業務是非常底層的,如:操作系統內核、存儲系統、網絡系統、數據庫系統等等,這類系統都偏底層,功能和功能之間有着緊密的配合關係,如果強制拆分爲較小的服務單元,會讓集成工作量急劇上升,並且這種人爲的切割無法帶來業務上的真正的隔離,所以無法做到獨立部署和運行,也就不適合做成微服務了。

6、微服務開發框架

目前微服務的開發框架,最常用的有以下四個:

Spring Cloud:http://projects.spring.io/spring-cloud(現在非常流行的微服務架構)

Dubbo:http://dubbo.io

Dropwizard:http://www.dropwizard.io (關注單個微服務的開發)

Consul、etcd&etc.(微服務的模塊)

7、什麼是Spring Cloud

Spring Cloud是一系列框架的集合。它利用Spring Boot的開發便利性簡化了分佈式系統基礎設施的開發,如服務發現、服務註冊、配置中心、消息總線、負載均衡、 熔斷器、數據監控等,都可以用Spring Boot的開發風格做到一鍵啓動和部署。Spring並沒有重複製造輪子,它只是將目前各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,通過SpringBoot風格進行再封裝屏蔽掉了複雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分佈式系統開發工具包

8、Spring Cloud和Spring Boot是什麼關係

Spring Boot 是 Spring 的一套快速配置腳手架,可以基於Spring Boot 快速開發單個微服務,Spring Cloud是一個基於Spring Boot實現的開發工具;Spring Boot專注於快速、方便集成的單個微服務個體,Spring Cloud關注全局的服務治理框架; Spring Boot使用了默認大於配置的理念,很多集成方案已經幫你選擇好了,能不配置就不配置,Spring Cloud很大的一部分是基於Spring Boot來實現,必須基於Spring Boot開發。可以單獨使用Spring Boot開發項目,但是Spring Cloud離不開 Spring Boot。

9、Spring Cloud相關基礎服務組件

服務發現——Netflix Eureka (Nacos)

服務調用——Netflix Feign

熔斷器——Netflix Hystrix

服務網關——Spring Cloud GateWay

分佈式配置——Spring Cloud Config (Nacos)

消息總線 —— Spring Cloud Bus (Nacos)

10、Spring Cloud的版本

Spring Cloud並沒有熟悉的數字版本號,而是對應一個開發代號。

Cloud代號 Boot版本(train) Boot版本(tested) lifecycle
Angle 1.2.x incompatible with 1.3 EOL in July 2017
Brixton 1.3.x 1.4.x 2017-07卒
Camden 1.4.x 1.5.x -
Dalston 1.5.x not expected 2.x -
Edgware 1.5.x not expected 2.x -
Finchley 2.0.x not expected 1.5.x -
Greenwich 2.1.x
Hoxton 2.2.x

開發代號看似沒有什麼規律,但實際上首字母是有順序的,比如:Dalston版本,我們可以簡稱 D 版本,對應的 Edgware 版本我們可以簡稱 E 版本。

小版本

Spring Cloud 小版本分爲:

SNAPSHOT: 快照版本,隨時可能修改

M: MileStone,M1表示第1個里程碑版本,一般同時標註PRE,表示預覽版版。

SR: Service Release,SR1表示第1個正式版本,一般同時標註GA:(GenerallyAvailable),表示穩定版本。

02-服務發現-搭建Nacos服務

一、Nacos

1、基本概念

(1) Nacos 是阿里巴巴推出來的一個新開源項目,是一個更易於構建雲原生應用的動態服務發現、配置管理和服務管理平臺。Nacos 致力於幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元數據及流量管理。Nacos 幫助您更敏捷和容易地構建、交付和管理微服務平臺。 Nacos 是構建以“服務”爲中心的現代應用架構 (例如微服務範式、雲原生範式) 的服務基礎設施。

(2) 常見的註冊中心:

  1. Eureka(原生,2.0遇到性能瓶頸,停止維護)

  2. Zookeeper(支持,專業的獨立產品。例如:dubbo)

  3. Consul(原生,GO語言開發)

  4. Nacos

相對於 Spring Cloud Eureka 來說,Nacos 更強大。Nacos = Spring Cloud Eureka + Spring Cloud Config

Nacos 可以與 Spring, Spring Boot, Spring Cloud 集成,並能代替 Spring Cloud Eureka, Spring Cloud Config

  • 通過 Nacos Server 和 spring-cloud-starter-alibaba-nacos-discovery 實現服務的註冊與發現。

(3) Nacos是以服務爲主要服務對象的中間件,Nacos支持所有主流的服務發現、配置和管理。

Nacos主要提供以下四大功能:

  1. 服務發現和服務健康監測

  2. 動態配置服務

  3. 動態DNS服務

  4. 服務及其元數據管理

(4) Nacos結構圖

在這裏插入圖片描述

2、Nacos下載和安裝

(1)下載地址和版本

下載地址:https://github.com/alibaba/nacos/releases

下載版本:nacos-server-1.1.4.tar.gz或nacos-server-1.1.4.zip,解壓任意目錄即可

(2)啓動nacos服務

  • Linux/Unix/Mac

啓動命令(standalone代表着單機模式運行,非集羣模式)

啓動命令:sh startup.sh -m standalone

  • Windows

啓動命令:cmd startup.cmd 或者雙擊startup.cmd運行文件。

訪問:http://localhost:8848/nacos

用戶名密碼:nacos/nacos

在這裏插入圖片描述

在這裏插入圖片描述

二、服務註冊(service_edu爲例)

把service-edu微服務註冊到註冊中心中,service-vod步驟相同

1、在service模塊配置pom

配置Nacos客戶端的pom依賴

<!--服務註冊-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2、添加服務配置信息

配置application.properties,在客戶端微服務中添加註冊Nacos服務的配置信息

# nacos服務地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

3、添加Nacos客戶端註解

在客戶端微服務啓動類中添加註解

@EnableDiscoveryClient

4、啓動客戶端微服務

啓動註冊中心

啓動已註冊的微服務,可以在Nacos服務列表中看到被註冊的微服務

在這裏插入圖片描述

03-服務調用-Feign

一、Feign

1、基本概念

  • Feign是Netflix開發的聲明式、模板化的HTTP客戶端, Feign可以幫助我們更快捷、優雅地調用HTTP API。
  • Feign支持多種註解,例如Feign自帶的註解或者JAX-RS註解等。
  • Spring Cloud對Feign進行了增強,使Feign支持了Spring MVC註解,並整合了Ribbon和Eureka,從而讓Feign的使用更加方便。
  • Spring Cloud Feign是基於Netflix feign實現,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供這兩者的強大功能外,還提供了一種聲明式的Web服務客戶端定義的方式。
  • Spring Cloud Feign幫助我們定義和實現依賴服務接口的定義。在Spring Cloud feign的實現下,只需要創建一個接口並用註解方式配置它,即可完成服務提供方的接口綁定,簡化了在使用Spring Cloud Ribbon時自行封裝服務調用客戶端的開發量。

二、實現服務調用

1、需求

刪除課時的同時刪除雲端視頻

2、在service模塊添加pom依賴

<!--服務調用-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

3、在調用端的啓動類添加註解

@EnableFeignClients

4、創建包和接口

創建client包

@FeignClient註解用於指定從哪個服務中調用功能 ,名稱與被調用的服務名保持一致。

@GetMapping註解用於對被調用的微服務進行地址映射。

@PathVariable註解一定要指定參數名稱,否則出錯

@Component註解防止,在其他位置注入CodClient時idea報錯

package com.guli.edu.client;

@FeignClient("service-vod")
@Component
public interface VodClient {
    @DeleteMapping(value = "/eduvod/vod/video/{videoId}")
    public R removeVideo(@PathVariable("videoId") String videoId);
}

5、調用微服務

在調用端的VideoServiceImpl中調用client中的方法

@Override
public boolean removeVideoById(String id) {

    //查詢雲端視頻id
    Video video = baseMapper.selectById(id);
    String videoSourceId = video.getVideoSourceId();
    //刪除視頻資源
    if(!StringUtils.isEmpty(videoSourceId)){
        vodClient.removeVideo(videoSourceId);
    }

    Integer result = baseMapper.deleteById(id);
    return null != result && result > 0;
}

6、測試

啓動相關微服務

測試刪除課時的功能

04-完善刪除課程業務

需求

刪除課程的同時刪除雲端視頻

一、vod服務

1、業務

業務接口:VideoService.java

void removeVideoList(List<String> videoIdList);

業務實現:VideoServiceImpl.java

@Override
public void removeVideoList(List<String> videoIdList) {
    try {
        //初始化
        DefaultAcsClient client = AliyunVodSDKUtils.initVodClient(
            ConstantPropertiesUtil.ACCESS_KEY_ID,
            ConstantPropertiesUtil.ACCESS_KEY_SECRET);

        //創建請求對象
        //一次只能批量刪20個
        String str = org.apache.commons.lang.StringUtils.join(videoIdList.toArray(), ",");
        DeleteVideoRequest request = new DeleteVideoRequest();
        request.setVideoIds(str);

        //獲取響應
        DeleteVideoResponse response = client.getAcsResponse(request);

        System.out.print("RequestId = " + response.getRequestId() + "\n");

    } catch (ClientException e) {
        throw new GuliException(20001, "視頻刪除失敗");
    }
}

2、web層接口

controller:VideoAdminController.java

/**
     * 批量刪除視頻
     * @param videoIdList
     * @return
     */
@DeleteMapping("delete-batch")
public R removeVideoList(
    @ApiParam(name = "videoIdList", value = "雲端視頻id", required = true)
    @RequestParam("videoIdList") List videoIdList){

    videoService.removeVideoList(videoIdList);
    return R.ok().message("視頻刪除成功");
}

3、Swagger測試

輸入多個id,每個一行

在這裏插入圖片描述

二、edu服務

1、client

VodClient.java

@DeleteMapping(value = "/admin/vod/video/delete-batch")
public R removeVideoList(@RequestParam("videoIdList") List<String> videoIdList);

2、業務

VideoServiceImpl.java

@Override
public boolean removeByCourseId(String courseId) {

    //根據課程id查詢所有視頻列表
    QueryWrapper<Video> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("course_id", courseId);
    queryWrapper.select("video_source_id");
    List<Video> videoList = baseMapper.selectList(queryWrapper);

    //得到所有視頻列表的雲端原始視頻id
    List<String> videoSourceIdList = new ArrayList<>();
    for (int i = 0; i < videoList.size(); i++) {
        Video video = videoList.get(i);
        String videoSourceId = video.getVideoSourceId();
        if(!StringUtils.isEmpty(videoSourceId)){
            videoSourceIdList.add(videoSourceId);
        }
    }

    //調用vod服務刪除遠程視頻
    if(videoSourceIdList.size() > 0){
        vodClient.removeVideoList(videoSourceIdList);
    }

    //刪除video表示的記錄
    QueryWrapper<Video> queryWrapper2 = new QueryWrapper<>();
    queryWrapper2.eq("course_id", courseId);
    Integer count = baseMapper.delete(queryWrapper2);
    return null != count && count > 0;
}

CourseServiceImpl.java

@Override
public boolean removeCourseById(String id) {

    //根據id刪除所有視頻
    videoService.removeByCourseId(id);

    //根據id刪除所有章節
    chapterService.removeByCourseId(id);

    //根據id刪除所有課程詳情
    courseDescriptionService.removeById(id);

    //刪除封面 TODO 獨立完成

    Integer result = baseMapper.deleteById(id);
    return null != result && result > 0;
}

05-熔斷器

一、Hystrix基本概念

1、Spring Cloud調用接口過程

Spring Cloud 在接口調用上,大致會經過如下幾個組件配合:

Feign ----->Hystrix —>Ribbon —>Http Client``(apache http components 或者 Okhttp) 具體交互流程上,如下圖所示:

在這裏插入圖片描述

(1)接口化請求調用當調用被@FeignClient註解修飾的接口時,在框架內部,將請求轉換成Feign的請求實例feign.Request,交由Feign框架處理。

(2)Feign :轉化請求Feign是一個http請求調用的輕量級框架,可以以Java接口註解的方式調用Http請求,封裝了Http調用流程。

(3) Hystrix:熔斷處理機制 Feign的調用關係,會被Hystrix代理攔截,對每一個Feign調用請求,Hystrix都會將其包裝成HystrixCommand,參與Hystrix的流控和熔斷規則。如果請求判斷需要熔斷,則Hystrix直接熔斷,拋出異常或者使用FallbackFactory返回熔斷Fallback結果;如果通過,則將調用請求傳遞給Ribbon組件。

(4) Ribbon:服務地址選擇 當請求傳遞到Ribbon之後,Ribbon會根據自身維護的服務列表,根據服務的服務質量,如平均響應時間,Load等,結合特定的規則,從列表中挑選合適的服務實例,選擇好機器之後,然後將機器實例的信息請求傳遞給Http Client客戶端,HttpClient客戶端來執行真正的Http接口調用;

(5)HttpClient :Http客戶端,真正執行Http調用根據上層Ribbon傳遞過來的請求,已經指定了服務地址,則HttpClient開始執行真正的Http請求

**
**

2 、Hystrix概念

Hystrix 是一個供分佈式系統使用,提供延遲和容錯功能,保證複雜的分佈系統在面臨不可避免的失敗時,仍能有其彈性。

比如系統中有很多服務,當某些服務不穩定的時候,使用這些服務的用戶線程將會阻塞,如果沒有隔離機制,系統隨時就有可能會掛掉,從而帶來很大的風險。SpringCloud使用Hystrix組件提供斷路器、資源隔離與自我修復功能。下圖表示服務B觸發了斷路器,阻止了級聯失敗

在這裏插入圖片描述

二、feign結合Hystrix使用

改造service-edu模塊

1、在service的pom中添加依賴

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

        <!--hystrix依賴,主要是用  @HystrixCommand -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

        <!--服務註冊-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--服務調用-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2、在配置文件中添加hystrix配置

     
#開啓熔斷機制
feign.hystrix.enabled=true
# 設置hystrix超時時間,默認1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000

3、在service-edu的client包裏面創建熔斷器的實現類

@Component
public class VodFileDegradeFeignClient implements VodClient {
    @Override
    public R removeVideo(String videoId) {
        return R.error().message("time out");
    }

    @Override
    public R removeVideoList(List videoIdList) {
        return R.error().message("time out");
    }
}

4、修改VodClient接口的註解

@FeignClient(name = "service-vod", fallback = VodFileDegradeFeignClient.class)
@Component
public interface VodClient {
    @DeleteMapping(value = "/eduvod/vod/{videoId}")
    public R removeVideo(@PathVariable("videoId") String videoId);

    @DeleteMapping(value = "/eduvod/vod/delete-batch")
    public R removeVideoList(@RequestParam("videoIdList") List videoIdList);
}

5、測試熔斷器效果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章