SpringCloud(二)服務註冊與發現

来源:https://www.cnblogs.com/yuanqinnan/archive/2019/09/06/11470618.html
-Advertisement-
Play Games

離上一篇微服務的基本概念已經過去了幾個月,在寫那篇博客之前,自己還並未真正的使用微服務架構,很多理解還存在概念上。後面換了公司,新公司既用了SpringCloud也用了Dubbo+Zookeeper,就像上一篇文章說的,當一個服務是面向外部或者是直接提供給前端調用的,那麼就使用SpringCloud ...


離上一篇微服務的基本概念已經過去了幾個月,在寫那篇博客之前,自己還並未真正的使用微服務架構,很多理解還存在概念上。後面換了公司,新公司既用了SpringCloud也用了Dubbo+Zookeeper,就像上一篇文章說的,當一個服務是面向外部或者是直接提供給前端調用的,那麼就使用SpringCloud,而一些內部公用的(如發送簡訊),就使用Dubbo+Zookeeper,因為他在內部調用更像調用接一個介面,效率也會比較高,而一些模塊型的功能,我們則使用SpringCloud。

在已經存在了成熟的開發框架後,微服務本身也沒什麼技術難點,架構思想才是最重要的,要在不斷的實踐中去探索,廢話不多說,來學習SpringCloud的技術。

一、SpringCloud技術棧

SpringCloud是一套完整的分散式微服務架構,我們可以去官網上看下整體的架構圖

 SpringCloud基於SpringBoot提供了一套微服務解決方案,包括服務註冊與發現,配置中心,全鏈路監控,服務網關,負載均衡,熔斷器等組件,除了基於NetFlix的開源組件做高度抽象封裝之外,還有一些選型中立的開源組件。

而SpringBoot並沒有重覆製造輪子,它將目前各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,通過SpringBoot風格進行再封裝屏蔽掉了複雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分散式系統開發工具包。

SpringCloud提供了全家桶式技術解決方案,對我們使用者來說是極其簡單的。但是要學會SpringCloud的前提那必定要學會SpringBoot。

瞭解完整體的架構圖後,就來進行一個個的技術棧的學習,學習的網站推薦:

Spring Cloud中國社區:http://springcloud.cn/

Spring Cloud中文網: https://www.springcloud.cc/

二、服務註冊與發現

一般架構的開發過程中,我們也會去調用一些外部服務,這個時候都是直接去調用,沒有服務註冊與發現的概念。但在微服務架構中,我們會按照模塊將系統分為多個微服務,而且每個服務我們會做成集群,那這些服務的數量是很大的,這些服務之間可能會被前端直接調用,也有可能互相調用,而且調用關係十分複雜。

每個服務實例的網路位置(IP與埠)信息,而且這些服務有可能會下線(奔潰),也有可能擴容,那這個時候服務之間相互去記錄這些信息肯定是非常麻煩的,這個時候我們需要一個服務的治理組件。

在定義服務治理之前,我們可以類比一個場景,就是我們工作大樓的物業,公司入駐這棟大樓,就會在物業處註冊自己的一些信息,並且交物業費,那這個物業管理類似服務治理。公司相當於一個一個服務,當外面的人想要找到公司提供服務時,可以去物業處瞭解我們的信息,然後再找到我們,而本身不需要記錄我們公司的信息,因為他記不想記住這麼多信息,而且就算記了,我們公司信息也可能會改變,比如破產倒閉了,或者又發展壯大換了地方了。我們定時向物業交管理費,一旦我們不交物業費了,那物業就認為我們不在這裡了,那其他人在來找也當做公司不存在了,Eureka的服務註冊與發現就有點類似這種場景。

Spring Cloud 封裝了 Netflix 公司開發的 Eureka 模塊來實現服務註冊和發現,Eureka 採用了 C-S 的設計架構。Eureka Server 作為服務註冊功能的伺服器,它是服務註冊中心(物業管理)。而系統中的其他微服務(公司),使用 Eureka 的客戶端連接到 Eureka Server,並維持心跳連接(交物業費)。這樣系統的維護人員就可以通過 Eureka Server 來監控系統中各個微服務是否正常運行。Spring Cloud 的一些其他模塊(訪問人員)就可以通過 Eureka Server 來發現系統中的其他微服務,並執行相關的邏輯。

Eureka包含兩個組件:Eureka ServerEureka Client

Eureka Server提供服務註冊服務各個節點啟動後,會在EurekaServer中進行註冊,這樣EurekaServer中的服務註冊表中將會存儲所有可用服務節點的信息,服務節點的信息可以在界面中直觀的看到。

EurekaClient是一個Java客戶端,用於簡化Eureka Server的交互,客戶端同時也具備一個內置的、使用輪詢(round-robin)負載演算法的負載均衡器。在應用啟動後,將會向Eureka Server發送心跳(預設周期為30秒)。如果Eureka Server在多個心跳周期內沒有接收到某個節點的心跳,EurekaServer將會從服務註冊表中把這個服務節點移除(預設90秒)。

三大角色:

  • Eureka Server 提供服務註冊和發現。

  • Service Provider服務提供方將自身服務註冊到Eureka,從而使服務消費方能夠找到。

  • Service Consumer服務消費方從Eureka獲取註冊服務列表,從而能夠消費服務。

三、構建

瞭解了概念,我們現在來實踐一下,因為還會學習更多的的組件,那麼我們創建工程也是從整體來創建,還要瞭解的一點是,我們現在做的是微服務項目,那其實這些微服務就是一個個獨立的項目,這些項目可以是完全分開的,跟之前的模塊概念是不一樣的。

3.1 創建整體項目

直接先創建一個名為spring-cloud-learn 的文件夾,這個文件夾是為了放各個工程的,然後通過idea 打開這個文件夾,然後在這個文件夾下麵創建一個文件夾:spring-cloud-learn-parent

 然後在這個文件夾下增加一個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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
    </parent>
    <groupId>com.yuanqinnan</groupId>
    <artifactId>spring-cloud-learn-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <properties>
        <!-- Environment Settings -->
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!-- Spring Settings -->
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>
    <dependencyManagement>
        <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <finalName>spring-cloud-learn-parent</finalName>
        <!-- 資源文件配置 -->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <delimiters>
                        <delimit>$</delimit>
                    </delimiters>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

將這個項目手動托管成maven項目,這個項目是用於管理依賴的,管理一些公共的依賴,就是一些簡單的依賴,需要主要以的是SpringCloud的版本很讓人頭疼,他不僅有數字,還有字母,這些字母是倫敦地鐵站的開頭字母。

3.2 創建服務註冊中心

主要的項目創建完成之後,我們來創建一個用於服務註冊的項目,創建過程與spring-cloud-learn-parent相同,也是創建一個文件夾spring-cloud-learn-eureka,然後在文件夾下增加pom.xml文件,然後再手動托管

 

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

    <parent>
        <groupId>com.yuanqinnan</groupId>
        <artifactId>spring-cloud-learn-parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <artifactId>>spring-cloud-learn-eureka</artifactId>
    <packaging>jar</packaging>
    <dependencies>
        <!--eureka-server服務端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

</project>

然後再按照maven的目錄結構來創建目錄

 然後創建一個啟動類,這些都是Springboot項目中的知識,然後再增加一個啟動類,上面增加@EnableEurekaServer

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

然後增加配置文件application.yml

spring:
  application:
    name: spring-cloud-learn-eureka

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    #表示是否將自己註冊到Eureka Server,預設為true。
    registerWithEureka: false
    #表示是否從Eureka Server獲取註冊信息,預設為true。
    fetchRegistry: false
    serviceUrl:
      #設置與Eureka Server交互的地址,查詢服務和註冊服務都需要依賴這個地址。預設是http://localhost:8761/eureka ;多個地址可使用 , 分隔
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

需要註意的配置都寫在上面了,很好理解,這個時候我們可以啟動項目了:

這個時候相當於已經創建好註冊中心了,也就是Eureka Server,那現在再來創建服務提供者

3.3 創建服務提供者

按照上面創建註冊服務的方式我們再創建一個部門服務提供者,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>

    <parent>
        <groupId>com.yuanqinnan</groupId>
        <artifactId>spring-cloud-learn-parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>

    <artifactId>spring-cloud-learn-provider-dept</artifactId>
    <packaging>jar</packaging>
    <dependencies>
        <!-- Spring Boot Begin -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Boot End -->

        <!-- Spring Cloud Begin -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!-- Spring Cloud End -->
    </dependencies>

</project>

配置文件:

spring:
  application:
    name: spring-cloud-learn-provider-dept

server:
  port: 8762

eureka:
  client:
    serviceUrl:
      #服務註冊地址
      defaultZone: http://localhost:8761/eureka/

然後創建啟動類:

@EnableEurekaClient
@SpringBootApplication
public class ProviderDeptApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderDeptApplication.class, args);
    }
}

啟動時idea會彈出此對話框,選擇第一個這個時候我們可以方便的管理多個啟動服務

@Configuration
public class RestTemplateConfiguration {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

然後我們需要創建一個service,用來請求服務,這裡調用的地方指定了服務名稱,不用管ip 地址與埠

@Service
public class DeptService {
    @Autowired
    private RestTemplate restTemplate;

    public String sayHi(String message) {
        //這裡指指定了服務名稱,不用管ip 地址與埠
        return restTemplate.getForObject("http://SPRING-CLOUD-LEARN-PROVIDER-DEPT/hi?message=" + message, String.class);
    }
}

然後創建一個controller,給前端介面調用

@RestController
public class DeptController {
    @Autowired
    private DeptService deptService;

    @RequestMapping(value = "hi", method = RequestMethod.GET)
    public String sayHi(@RequestParam String message) {
        return deptService.sayHi(message);
    }
}

 啟動成功後,刷新Eureka 服務可以看到服務已經註冊上來了,這裡的紅色提示是指Eureka 服務只部署了一臺,不具備高可用,後面我們再來部署集群

 不過這個時候服務者沒有提供確切的服務,添加一個方法

@RestController
public class DeptController {
    @Value("${server.port}")
    private String port;

    @RequestMapping(value = "hi", method = RequestMethod.GET)
    public String sayHi(@RequestParam(value = "message") String message) {
        return String.format("Hi,your message is : %s i am from port : %s", message, port);
    }
}

這裡為了後面顯示集群效果,我們返回埠號

3.4 創建服務消費者

上面的註冊中心和提供者都已建好,那現在來創建一個消費者,我們使用Ribbon,先不用管這個,依然按照上面的創建方式再創建一個工程,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>

    <parent>
        <groupId>com.yuanqinnan</groupId>
        <artifactId>spring-cloud-learn-parent</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>

    <artifactId>spring-cloud-learn-consumer-dept-ribbon</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <!-- Spring Boot Begin -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Boot End -->

        <!-- Spring Cloud Begin -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        <!-- Spring Cloud End -->
    </dependencies>

</project>

配置文件:

spring:
  application:
    name: spring-cloud-learn-consumer-dept-ribbon
server:
  port: 8764

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

啟動項:

@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerDeptRibbonApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerDeptRibbonApplication.class, args);
    }
}

這個服務我們稍微要給一個配置,因為我們要調用服務提供者,會使用到RestTemplate調用方式,添加一個配置項,這裡面還有一個負載均衡功能,用起來也很簡單

@RestController
public class DeptController {
    @Autowired
    private DeptService deptService;

    @RequestMapping(value = "hi", method = RequestMethod.GET)
    public String sayHi(@RequestParam String message) {
        return deptService.sayHi(message);
    }
}

這樣消費者就算完成了,我們可以訪問這個消費者了,這個消費者調用的是提供者的方法

 

 這樣就已經完成了服務的註冊中心開發,提供者開發及消費者開發,用起來非常簡單,這裡我們看到有@LoadBalanced這個註解,但是服務只有一個,所有沒有效果,我們可以再啟動一個提供者,這裡我們可以直接修改埠號再啟動,只要註意修改一個地方的配置

 

 我們把提供者的埠號改成8763,再啟動一次

 

 這裡啟動了兩個提供者,我們刷新下註冊中心:

 

 增加了一個服務,但是消費者是感受不到的,然後我們在多次刷新消費者,可以看到兩個服務在輪訓調用,這裡我們就實現了負載均衡:

 

 使用這些組件就是這麼簡單,這裡只是做了最簡單的微服務註冊與發現,未做服務中心集群,後面我們將再深入的學習。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 代碼: ...
  • 如果為了避免 js addEventListener事件多次綁定問題,可以使用.onclick直接綁定,後一次click綁定會覆蓋調前一次。 ...
  • 前言: jquery是每個前端都會的基礎技能,眾所周知,jquery返回的是jquery實例方法,但是我們似乎是直接使用$就可以獲取到jquery的方法啦,可以在瀏覽器中判斷一下 window.$ 和window.jQuery,jQuery 之間的關係,就會發現他們之間是全等的; 不使用new方法調 ...
  • 摘要: 是時候支持TS了! Fundebug前端異常監控服務 "Fundebug" 提供專業的前端異常監控服務,我們的插件可以提供全方位的異常監控,可以幫助開發者第一時間定位各種前端異常,包括但不限於JavaScript執行錯誤以及HTTP請求錯誤。 並且,Fundebug支持Source Map還 ...
  • 單一職責原則: 對象不應承擔太多功能,正如一心不能而用,比如太多的工作(種類)會使人崩潰。唯有專註才能保證對象的高內聚;唯有唯一,才能保證對象的細粒度。 解決問題: 假如有A和B兩個類,當A需求發生改變需要修改時,不能導致B類出問題。 現狀: 在實際情況很難去做到單一職責原則,因為隨著業務的不斷變更 ...
  • 架構設計原則 合適原則 合適優於業界領先 簡單原則 簡單優於複雜 演化原則 演化優於一步到位 ...
  • > sleep/wait/notify/notifyAll分別有什麼作用?它們的區別是什麼?wait時為什麼要放在迴圈里而不能直接用if? ## 簡介 首先對幾個相關的方法做個簡單解釋,Object中有幾個用於線程同步的方法:wait、notify、notifyAll。 ```java public ...
  • 一、方法 1.返回值類型如果不是void,表示這個方法執行結束之後必須返回一個具體的數值,當方法執行結束的時候沒有返回任何數值,編譯器會報錯,怎麼返回值呢?並且要求“值”的數據類型必須和“方法的返回值類型”是一致的,不然編譯器報錯。 2.返回值類型是void的時候,在方法體中不能編寫"return ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...