35.微服務調用(Nacos,Feign,熔斷器,刪除雲端視頻)


 本章主要介紹了微服務以及微服務所用到的部分組件,完成了刪除小節時刪除雲端視頻(根據視頻id)和刪除課程時刪除雲端視頻(根據課程id) 

一、什么是微服務  二、Nacos   三、Nacos服務注冊

四、Feign   五、熔斷器    六、刪除課程時刪除視頻 

一、什么是微服務

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並沒有熟悉的數字版本號,而是對應一個開發代號。

 

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

小版本

Spring Cloud 小版本分為:

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

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

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

二、Nacos

1、基本概念

(1)Nacos 是阿里巴巴推出來的一個新開源項目,是一個更易於構建雲原生應用的動態服務發現、配置管理和服務管理平台。Nacos 致力於幫助您發現、配置和管理微服務。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服務列表中看到被注冊的微服務

四、Feign

  • 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、需求(實現服務調用

刪除小節的同時刪除雲端視頻(根據視頻id刪除),使用Feign在service_edu模塊調用service_vod中的方法。

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報錯
@FeignClient(name = "service-vod")//調用的服務器名稱
@Component
public interface VodClient {
    //定義調用的方法路徑
    //根據視頻id刪除阿里雲視頻
    @DeleteMapping("/eduvod/video/removeAlyVideo/{id}")
    public R removeAlyVideo(@PathVariable("id") String id);
}

5、調用微服務

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

    //刪除小節,刪除對應阿里雲視頻
    @DeleteMapping("{id}")
    public R deleteVideo(@PathVariable String id){
        //根據小節id獲取視頻id,調用方法實現視頻刪除
        EduVideo eduVideo = videoService.getById(id);
        String videoSourceId = eduVideo.getVideoSourceId();

        //判斷小節里是否有視頻id
        if (!StringUtils.isEmpty(videoSourceId)) {
            //根據視頻id,遠程調用實現視頻刪除
            R result = vodClient.removeAlyVideo(videoSourceId);
            if (result.getCode() == 20001) {
                throw new GuliException(20001,"刪除視頻失敗,熔斷器。。");
            }
        }
        //刪除小節
        videoService.removeById(id);
        return R.ok();
    }

五、熔斷器 

5.1、Hystrix基本概念

5.1.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請求

簡單理解:

  1. 接口化請求調用:設置生產者服務名稱和接口地址
    @FeignClient("service-vod")
    @DeleteMapping("/eduvod/video/removeAlyVideo/{id}")
  2. Feign:根據服務名稱service-vod找到接口地址做調用
  3. Hystrix:熔斷器,當生產者服務器掛了,熔斷器發生熔斷機制,不對生產者服務器進行請求
  4. Ribbon:對請求進行負載均衡,例如生產者中有一個集群,則會將請求分擔到不同服務器中
  5. HttpClient :分擔之后則發送請求,進行接口調用

2、Hystrix概念

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

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

5.2、feign結合Hystrix使用

改造service-edu模塊

5.2.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>

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

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

5.2.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");
    }
}

5.2.4、修改VodClient接口的注解

  主要加上fallback參數,調用熔斷器的實現類

@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);
}

六、刪除課程時刪除視頻 

1、需求

刪除課程的同時刪除雲端多個視頻(根據課程id刪除),使用Feign在service_edu模塊調用service_vod中的方法。

2、在service-vod模塊的VodController創建刪除多個視頻接口

//刪除多個阿里雲視頻的方法
//參數為多個視頻id List videoIdList
@DeleteMapping("delete-batch")
public R removeVideoList(
@ApiParam(name = "videoIdList", value = "雲端視頻id", required = true)
@RequestParam("videoIdList") List<String> videoIdList){

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

3、VodService接口

void removeVideoList(List videoIdList);

4、VodServiceImpl實現類

@Override
public void removeVideoList(List videoIdList) {
try {
//初始化對象
DefaultAcsClient client = InitVodClient.initVodClient(ConstantVodUtils.ACCESS_KEY_ID, ConstantVodUtils.ACCESS_KEY_SECRET);
//創建刪除視頻request對象
DeleteVideoRequest request = new DeleteVideoRequest();

//VideoList
String videoIds = org.apache.commons.lang.StringUtils.join(videoIdList.toArray(), ",");
//向request設置視頻id
request.setVideoIds(videoIds);
//調用初始化對象的方法實現刪除
client.getAcsResponse(request);
}catch (Exception e){
e.printStackTrace();
throw new GuliException(20001,"刪除視頻失敗");
}
}

5、在service-edu調用service-vod接口實現刪除多個視頻功能

5.1 在service-edu的VodClient接口添加service-vod中的接口定義

//定義刪除多個視頻的方法
@DeleteMapping("/eduvod/video/delete-batch")
public R removeVideoList(@RequestParam("videoIdList") List<String> videoIdList);

5.2 修改根據課程id刪除小節方法

    //根據課程id刪除小節
    @Override
    public void removeVideoByCourseId(String courseId) {
        //1 根據課程id查詢出所有的視頻id
        QueryWrapper<EduVideo> wrapperVideo = new QueryWrapper<>();
        wrapperVideo.eq("course_id",courseId);
        wrapperVideo.select("video_source_id");
        List<EduVideo> videoList = baseMapper.selectList(wrapperVideo);

        //List<EduVideo>變成List<String>
        List<String> videoIds = new ArrayList<>();
        for (int i = 0; i < videoList.size(); i++) {
            EduVideo eduVideo = videoList.get(i);
            String videoSourceId = eduVideo.getVideoSourceId();
            if(!StringUtils.isEmpty(videoSourceId)){
                videoIds.add(videoSourceId);
            }
        }
        //根據多個視頻id刪除多個視頻
        if(videoIds.size()>0){
            vodClient.removeVideoList(videoIds);
        }

        QueryWrapper<EduVideo> wrapper = new QueryWrapper<>();
        wrapper.eq("course_id",courseId);
        baseMapper.delete(wrapper);
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM