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,再啟動一次

 

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

 

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

 

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

 


免責聲明!

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



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