從零搭建 Spring Cloud 服務(超詳細)

2020-12-10 酷扯兒

本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫

這裡會介紹很多基礎知識,直接想開始搭建微服務的可以看第二章,微服務的搭建。直接看第二章不會有什麼影響,可以先學會開車再學習車的構造的,看個人習慣來。

1.什麼是SpringCloud?

SpringCloud官網:https://spring.io/projects/spring-cloud(個人建議是用谷歌瀏覽器訪問官網打開中文翻譯粗略把官網讀一遍)

把 Spring 全家桶相關的文章整理成了 PDF,關注微信公眾號 Java後端,回復 666 下載這個技術棧手冊。

個人理解:

以前的伺服器就好像,一個會語數外全能的老師,為學生提供服務,這個老師生病了,那全校停課。現在微服務流行後,學校有了數學教研組,語文教研組,外語教研組,每個教研組有一群老師具體負責某科的教學,缺了誰,學校都照樣運轉。

而這個變化中,那些改變歷史的程式設計師就是把一個伺服器中的眾多服務,或好幾臺伺服器中的眾多服務,分類出來,解耦合出來,把他們類似的功能交給同一個集群來做,把互相耦合在一起的功能剝離出來,按業務,按功能來把他們作為一個個微服務放在伺服器上,而這個伺服器就只提供一個服務,或較少的服務。

讓一個超大的服務邏輯,解耦合為一個個小服務,均勻的分布在各自的伺服器中。微服務就微在這。每個教研組就是一個微服務集群。他們提供同樣的服務,而註冊中心Eureka就是這個存放這個教研組老師名單的地方,學生們想先訪問這個註冊中心獲取教師名單,然後根據相應的負載方法去訪問各自老師。不至於讓集群中某一老師累死也不至於讓某一老師閒死。

Zuul網關呢,就是學校的門衛,某些學生來學校找誰,它負責指引(路由),並且通過一些非常簡單的配置,達到阻攔一些人進入(身份驗證),或者控制想學數學的人只能去數學教研組,不能去核能教研組學怎麼造原子彈(權限驗證)。

Hystrix熔斷器呢,可以把它當成學校的志願者,當一個教研組集體罷課後,學生找不到老師了,這些志願者及時的告訴來訪問的學生,相應的結果,異常信息等,免得大量的學生在學校等待,這些志願者趕快把這些等待的學生梳理出去,學生一直在學校等待,那其他需要學生的學校,也會等待學生,最後造成大面積的學校癱瘓。這裡學生我們看成一個個請求。熔斷器就是把某事故的蔓延即使熔斷了。

當然這些組件也是微服務需要註冊到Eureka註冊中心

Spring Cloud 就可以看成是這個學校了。眾多上面提到的組件相當於都是這個學校的各職能部門。

ps: 博主基於Maven+idea搭建。 另外SpringCloud需要基於springboot搭建。

2.1 引入Spring Boot相關依賴 這裡的springboot用的是1.5.7版本

引入Spring Cloud相關依賴 這裡為Edgware.SR5

2.1 工程初始化配置

在Idea中創建工程:File -> New ->Project

點擊 Empty Project -> Next

項目命名 -> 項目位置

選擇模組 modules ->next

進入新的窗口後,開始配置Maven,打開設置 setting

因為我之前做過配置,因此只需要改變框1的路徑,如第一次配置需要自己找到你maven放置的位置,以及settings.xmlrepository的位置,實在不會的百度 maven集成idea

3個框選擇完畢後點擊 ok

接下來新建module

這裡可能會出現加載不出archetype list的問題

用了網上的所有解決辦法花了3個小時解決都沒用,重啟之後竟然可以了····你敢信?????小時候網吧網管的至理名言都忘了!!重啟一下嘛!!

出來之後 選擇quickstart ->下一步

名字自己想 想好後,複製一下你想好的 ArtifactId點擊Next,groupId為組織名 也是自己想一個,一般為公司網址反寫。

粘貼後下一步

提供註冊服務的伺服器pom.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.yun</groupId> <artifactId>springcloud-eureka-server</artifactId> <version>1.0-SNAPSHOT</version> <name>springcloud-eureka-server</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <!--引入springboot-parent父項目--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.7.RELEASE</version> </parent> <dependencies> <!--引入springcloud的euekea server依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> <!--指定下載源和使用springcloud的版本--> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement></project>

點擊Import Changes

等待右下角加載springcloud的依賴

2.2 Springboot的搭建 以及提供註冊服務 的 服務配置

創建resources文件夾

並設置作為資源根目錄,之後文件變成這樣

之後文件夾變成有黃色的橫槓

在resources下新建文件,文件名為application.yml (對是yml 不是xml ,博主第一次學習時,還以為是其他博主打錯了,踩了一個小坑)

配置yml,注意:如果只配置前兩行埠號信息會報錯

server:port:8700 # 埠自己決定# 指定當前eureka客戶端的註冊地址,也就是eureka服務的提供方,當前配置的服務的註冊服務方eureka: client: service-url: defaultZone:http://${eureka.instance.hostname}:${server.port}/eureka register-with-eureka: false #自身 不在向eureka註冊 fetch-registry: false #啟動時禁用client的註冊 instance: hostname: localhost#指定應用名稱spring: application: name: eureka-server

知識補充:

開發 spring boot 的入口類 EurekaServerApplication.java

EurekaServerApplication.java

package com.yun;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication@EnableEurekaServer //當前使用eureka的serverpublic class EurekaServerApplication {public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class,args); }}

右鍵運行當前類:

運行成功console畫面

嘗試進入eureka管理界面 埠號為 yml裡配置的(埠號自己設置 需要大於公用和保留的埠號)1024~65535

一般我喜歡設置為 8700到8800之間

如下 管理界面已經可以登錄了

2.3 客戶端client 提供真正服務的角色的配置, 它提供服務 在 服務註冊方server (註冊中心)進行註冊

同樣新建module,選擇quickstart點擊下一步

兩個位置 置空

取名 下一步

注意這裡要在根目錄springcloud 下創建模組,content root 會默認在之前的模組之下創建模組 這樣創建模組會出現問題並報錯

推薦這種配置方法 在content root下springcloud後改名字 如下圖配置點下一步,紅框處一般默認為上一個模組的文件目錄名,需要改為你的模組名

成功後為並列狀態,如不為並列或報錯請重新配置

配置servicesupport的pom,與server的pom配置相同,只需要把第一個pom的1的方框處server改為client

和第一個微服務同理 我們需要配置入口類pom.xml application.yml,因為是服務提供者,這裡還需編寫服務類controller

application.yml

server:port:8701 # 服務提供方# 指定當前eureka客戶端的註冊地址,eureka: client: service-url: defaultZone:http://${eureka.instance.hostname}:8700/eureka instance: hostname: localhost#當前服務名稱spring: application: name: eureka-service

pom.xml:

編寫所提供的 服務controller

@RestController@RequestMapping("/Hello")public class Controller {@RequestMapping("/World") public String helloWorld(String s){ System.out.println("傳入的值為:"+s); return "傳入的值為:"+s; }}

入口類並運行此微服務:

@SpringBootApplication@EnableDiscoveryClient//代表自己是一個服務提供方public class EurekaServiceApplication {public static void main(String[] args) { SpringApplication.run(EurekaServiceApplication.class,args); }}

右鍵入口類名點擊 run(當然開啟此服務時需要先開啟server服務 就是我們第一個編寫的微服務)

此時再進入服務註冊的頁面 http://localhost:8700/

可以看見服務提供者已被註冊進服務註冊者

在直接訪問一下服務提供者的 網絡位置http://localhost:8701/Hello/World?s=小沛

我們已經看見 可以訪問了,證明此微服務可用。

但是我們一般不直接調用所需的微服務,而是經過提供註冊服務伺服器server,獲取所需的服務提供者列表(為一個列表,此列表包含了能提供相應服務的伺服器),他們也許是個集群,因此server會返回一個 ip+埠號的表,服務消費者通過相應算法訪問這表上的不同伺服器,這些伺服器提供的是相同的服務,這種在服務消費者一方挑選伺服器為自己服務的方式是一種客戶端的負載均衡。

目前博主所知的有輪詢隨機兩種方式 訪問這些伺服器,輪詢就是循環的意思,假如有3臺伺服器,訪問方式就是1,2,3,1,2,3,1,2,3····,隨機就是隨機,回想一下random方法,一種無規律的方式。這兩種方式都是為了,訪問每個伺服器的可能性儘量的相同。還有權重負載這種算法,意思就是 根據伺服器負載能力的分配相應的服務。能力大的幹得多。能力小的幹得少。

2.4 服務的調用方式

第一種調用方式:restTemplate+ribbon

第二種調用方式:feign

2.4.1 restTemplate+ribbon

ribbon是一種負載均衡的客戶端,它是什麼呢?請詳讀https://www.jianshu.com/p/1bd66db5dc46

可以看見其中的一段如下:

客戶端負載均衡服務端負載均衡最大的不同點在於上面所提到服務清單所存儲的位置。在客戶端負載均衡中,所有客戶端節點都維護著自己要訪問的服務端清單,而這些服務端端清單來自於服務註冊中心,比如上一章我們介紹的Eureka服務端。同服務端負載均衡的架構類似,在客戶端負載均衡中也需要心跳去維護服務端清單的健康性,默認會創建針對各個服務治理框架的Ribbon自動化整合配置,比如Eureka中的org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,Consul中的org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration。在實際使用的時候,我們可以通過查看這兩個類的實現,以找到它們的配置詳情來幫助我們更好地使用它。

接下來我們來搭建基於ribbon的客戶端,他用於消費服務。

同理先搭建springboot的環境

與之前搭建servicesupport不同的是:

第一步:現在pom中需要在dependencies中添加ribbon依賴

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

第二步:yml如下配置:

server:port:8702 # 服務消費方# 指定當前eureka客戶端的註冊地址,eureka: client: service-url: defaultZone:http://${eureka.instance.hostname}:8700/eureka instance: hostname: localhost#當前服務名稱spring: application: name: eureka-consumer

服務的消費方依舊需要在註冊方8700埠去註冊。配置當前服務消費方的埠8072,名字為eureka-consumer

第三步:依舊需要啟動類,因為它是一個springboot的架構:

@SpringBootApplication@EnableDiscoveryClient //當前使用eureka的serverpublic class EurekaConsumerApplication {public static void main(String[] args) { SpringApplication.run(EurekaConsumerApplication.class,args); }}

如上圖:

我們需要一個controller類來編寫ribbon的代碼。

@RestController@RequestMapping("/Hello")class ConsumerController {@Autowired private LoadBalancerClient loadBalancerClient; @Autowired private RestTemplate restTemplate; @RequestMapping("/Consumer") public String helloWorld(String s){ System.out.println("傳入的值為:"+s); //第一種調用方式 //String forObject = new RestTemplate().getForObject("http://localhost:8071/Hello/World?s=" + s, String.class); //第二種調用方式 //根據服務名 獲取服務列表 根據算法選取某個服務 並訪問某個服務的網絡位置。 //ServiceInstance serviceInstance = loadBalancerClient.choose("EUREKA-SERVICE"); //String forObject = new RestTemplate().getForObject("http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/Hello/World?s="+s,String.class); //第三種調用方式 需要restTemplate注入的方式 String forObject = restTemplate.getForObject("http://EUREKA-SERVICE/Hello/World?s=" + s,String.class); return forObject; }}

我們常用第三種調用方式。

第一種是直接調用:不經過註冊中心那服務列表,直接訪問的servicesupport

第二種:是根據服務名選擇調用,如上圖需要做如下注入

@Autowired private LoadBalancerClient loadBalancerClient;

如上圖代碼中第二種調用方法的代碼所示。

用服務名去註冊中心獲取服務列表,當前客戶端底層會做隨機算法的選取獲得服務並訪問。

第三種需要一個@Bean的註解自動注入並直接調用restTemplate對象調用服務。底層調用模式與第二種調用方式一樣。如下:

@Configurationpublic class Beans {//管理簡單對象 @Bean @LoadBalanced public RestTemplate getRestTemplate(){ return new RestTemplate(); }}

@Bean註解告訴工廠,這個方法需要自動注入。

@LoadBalanced,表示需要做負載勻衡。

然後如controller中一樣注入一下restTemplate,並且使用他,區別是可以直接使用服務名訪問了

String forObject = restTemplate.getForObject("http://EUREKA-SERVICE/Hello/World?s=" + s, String.class);

開始測試:

1.運行server的啟動類:

2.運行servicesupport的啟動類:

3.運行serviceconsume的啟動類:

瀏覽器訪問:

8072為服務消費方的埠

訪問方法解析:

訪問服務消費方@RequestMapping指定的路徑及消費方的埠來訪問消費方的controllercontroller根據服務名去server方獲取獲取服務列表,獲取服務列表後根據隨機的模式負載勻衡後去選擇服務地址去訪問servicesupport:如下圖

2.5 Eureka server的高可用配置

點擊下圖配置

接下來配置三臺01,02,03的虛擬機參數

01:8699

02:8698

03:8697

之後點ok保存,可看見多出三個啟動項

接下來分別改註冊埠號,defaultZone分別啟動三個啟動項

打開server的yml配置,刪掉前兩行埠號配置(圖中有錯,請把instance 和hostname那兩行刪掉)

配置好yml後點擊啟動

同理,我們再次改動埠號為8699和8697後,把啟動項改為02,之後啟動(圖中有錯,請把instance 和hostname那兩行刪掉)

同理把yml埠改為8699 和 8698後,把啟動項改為03,之後啟動(圖中有錯,請把instance 和hostname那兩行刪掉)

啟動後分別訪問三個01,02,03埠,已經可以看見可以訪問了。

打開服務提供方的yml配置如下,把埠號改為三個中其中的一個。

啟動服務提供方之後,再次訪問三個01,02,03我們會發現

重點:即使服務提供方只註冊了一個埠號8699,但是另外兩個埠號,也能感知到服務提供方8701的存在了。如下圖:

接下來像服務消費方中添加服務註冊者的埠號,這樣在server掛掉任何一個的時候,都能有其他的server也能獲取服務列表

訪問以下服務消費方,發現可以通過消費方調用server服務列表並且訪問service了

我麼隨便關閉其中兩個server的副本,重啟serviceconsume,再進行訪問。必須重啟serviceconsume才能清空緩存,清掉consume裡面有的服務列表。

上圖發現即使關閉兩臺server後依舊可以訪問,如下圖,依舊從server中獲取了服務列表,從中也能看見之後不用再獲取服務列表了。

但是當我們關掉所有server後。訪問還是沒問題,因為緩存了服務列表。

但是讓我們來重啟一下serviceconsume,再訪問就不行了。

綜上我們就完成了springcloud中server的高可用配置

相關焦點

  • Spring Cloud 和 Dubbo,到底用哪個好?
    從公司整體規劃:我不會選擇很久沒人維護的dubbo,重啟之後也未必是原班人馬從程式設計師招聘難度:招springcloud的程式設計師會更好招,因為更新更炫從系統結構簡易程序:springcloud的系統結構更簡單
  • 7.spring cloud系列教程第六篇-Eureka集群版
    spring cloud系列教程第六篇-Eureka集群版本文主要內容:1:Eureka執行步驟理解2:集群原理3:Eureka集群搭建4:修改payment和order項目註冊到集群中本文是由凱哥(凱哥Java:kagejava)發布的《spring cloud系列教程》教程的總第六篇:《spring cloud系列教程第六篇-Eureka集群版》。
  • SpringCloud服務間通信方式
    總結:在springcloud中服務間調用方式主要是使用 http restful方式進行服務間調用1|0 1.說明spring框架提供的RestTemplate類可用於在應用中調用rest服務,它簡化了與http服務的通信方式,統一了RESTful的標準,封裝了http連結, 我們只需要傳入url及返回值類型即可。相較於之前常用的HttpClient,RestTemplate是一種更優雅的調用RESTful服務的方式。
  • 擁抱Kubernetes,再見了Spring Cloud
    (2016年12月):升級到spring4.2,新的spring-boot-devtools,緩存技術的自動配置(ehcache,hazelcast,redis,guava和infinispan)以及完全可執行的jar支持Spring boot 1.4(2017年1月):升級到spring 4.3,couchbase/neo4j支持,啟動失敗分析和RestTemplateBuilderSpring
  • 初識Spring Cloud Stream,什麼是消息驅動微服務框架
    同樣,消費該事件的服務也不一定需要知道該事件是由哪個服務所發布。事件生產者和消費者之間的虛線代表的是一種相互鬆散、沒有直接調用的關聯關係。滿足以上特性的系統代表著一種鬆耦合的架構,通常被稱為事件驅動架構,而這裡的事件也可以被理解是服務與服務之間發送的一種消息。事件驅動架構本質上是一種架構設計風格,實現方法和工具有很多。
  • springcloud的五大組件是什麼?讀完這篇就懂了
    概括而言,springcloud的五大組件包括Netflix Eurek,Netflix Ribbon,Netflix Hystrix,Netflix Zuul和Spring Cloud Config。
  • 使用IDEA 快速搭建 Spring 的源碼環境
    說明想深入學習下 spring,了解下 spring 生命周期的一些細節,學習下一些中間件是怎麼整合到 spring 裡面的,如果自己寫的中間件要怎麼整合到 spring 中呢?從而讓其他同學使用的時候非常方便;看了文檔、書、博客、專欄之後想讀讀源碼,順便讀源碼的時候做一點注釋,或者修改點代碼啥的,所以需要搭建一個環境;說實話,很多人估計想搭建個 spring 的源碼環境,但是 spring 的這個源碼環境還是稍微有點複雜的,機緣巧合,之前有朋友(@上傑)研究了一個星期,並且最後把環境搞好了,還順便給我把環境也搞了下,大概幾分鐘操作就行,其他就讓電腦在那邊下載就行了
  • Spring全家桶、Dubbo、分布式、消息隊列後端必備全套開源項目
    《Spring Cloud Alibaba 服務調用 Dubbo 入門》 對應 labx-07-spring-cloud-alibaba-dubbo《Spring Cloud Alibaba 服務容錯 Sentinel 入門》 對應 labx-04-spring-cloud-alibaba-sentinel
  • 詳解SpringCloud中RabbitMQ消息隊列原理及配置,一篇就夠!
    下單服務系統:用戶使用下單服務後,將下單信息寫入資料庫,下單成功。簡訊服務系統:用戶下單後,將簡訊信息寫入消息隊列,以發送簡訊信息通知用戶交易信息。郵件服務系統:用戶下單後,將郵件信息寫入消息隊列,以發送郵件信息通知用戶交易信息。
  • Spring Cloud系列各子項目在微服務架構中的作用分析
    Springcloud一般用於搭建微服務項目,那麼微服務項目是怎麼工作的呢?Springcloud的幾個子項目分別扮演什麼角色?網關:Spring Cloud Netflix Zuul / Spring Cloud Gateway微服務開發要把一整個系統不同模塊分成不同的服務項目,每個服務都有自己的調用地址埠信息,那麼前端用戶怎麼調用呢?總不能把所有服務的接口地址給前端吧。
  • Spring Boot 快速入門教程(附詳細圖文)
    設計目的:用來簡化新 Spring 應用的初始搭建以及開發過程。從最根本上來講,Spring Boot 就是一些庫的集合,它能夠被任意項目的構建系統所使用。它使用 「習慣優於配置」 (項目中存在大量的配置,此外還內置一個習慣性的配置)的理念讓你的項目快速運行起來。
  • 從零開始,搭建自己的NAS媒體伺服器,附plex和emby對比
    這篇文章的初衷很簡單,我本來也是比較頭疼折騰NAS的,因為NAS並非是小白向家電,它是個比較複雜的系統,成品NAS只是給了你一個硬體平臺,安裝各類應用都需要有一定基礎,所以寫了兩篇比較詳細的NAS原創文後,我決定綜合一下,一步一步教大家從零開始,完美搭建屬於自己的NAS遠程影音伺服器,也是基於我自己的原因,這篇文章比較詳細,從IOS和安卓,從plex到emby,
  • zuihou-admin-cloud 2.3 發布,完美支持分布式事務 - OSCHINA...
    今日更新日誌:優化: spring.cloud.version
  • spring框架之註解的使用
    JavaWeb項目的搭建。Spring的Web集成。本來還計劃學Spring的junit測試集成的,結果又沒時間了。其實無論是spring註解也好,還是配置xml也罷,都是省略new對象這個步驟。將dao層和service層對象關聯起來了,沒有new對象實例化,也能調用dao層代碼。當然spring肯定不止這麼簡單,只不過目前來說還沒有學到其它的知識點。
  • 基於SpringCloud的面試刷題系統,項目經驗統統搞定
    這篇文章我會從系統架構設計層面詳細介紹這個開源項目,並且會把微服務常用的一些技術都介紹一下。即使你對這個項目不感興趣,也能了解到很多微服務相關的知識。美滋滋!昨晚肝了很久~原創不易,若有幫助,求贊求轉發啊!不得不說,這個刷題系統確實是有點東西,你真的值得擁有!
  • IT之家學院:BT 下載利器 CloudTorrent 安裝教程詳解
    2.JuiceSSH(能夠連結VPS的SSH工具即可,本地Linux用戶直接在終端中執行命令)3.Chrome(能夠訪問用以搭建CloudTorrent的主機的網絡的瀏覽器即可,某些瀏覽器排版會有誤)二、下載應用檢查CloudTorrent當前版本:https://github.com/jpillora/cloud-torrent
  • 從Spring Cloud到UCloud UK8S的微服務遷移實踐 - 軟體與服務...
    在 Kubernetes 環境中,ETCD 已經擁有了服務發現所必要的信息,沒有必要再使用 Eureka,通過 Discovery 就能夠獲取 Kubernetes ETCD 中註冊的服務列表進行服務發現。2. 去掉 Feign 負載均衡,改用 Spring Cloud Kubernetes Ribbon。
  • 基礎篇:Spring Boot入門體驗(圖文教程)
    設計目的:用來簡化新 Spring 應用的初始搭建以及開發過程。從最根本上來講,Spring Boot 就是一些庫的集合,它能夠被任意項目的構建系統所使用。它使用 「習慣優於配置」 (項目中存在大量的配置,此外還內置一個習慣性的配置)的理念讓你的項目快速運行起來。