從零開始搭建spring-cloud(1) ----eureka

什麼是Eureka,什麼是服務註冊與發現?

Spring Boot做爲目前最火爆的web框架。那麼spring boot與Eureka又有什麼關聯呢?前端

Eureka是Netflix開源的一個RESTful服務,主要用於服務的註冊發現。
Eureka由兩個組件組成:Eureka服務器和Eureka客戶端。Eureka服務器用做服務註冊服務器。
Eureka客戶端是一個java客戶端,用來簡化與服務器的交互、做爲輪詢負載均衡器,並提供服務的故障切換支持。
Netflix在其生產環境中使用的是另外的客戶端,它提供基於流量、資源利用率以及出錯狀態的加權負載均衡。
SpringCloud Eureka是SpringCloud Netflix服務套件中的一部分,它基於Netflix Eureka作了二次封裝,主要負責完成微服務架構中的服務治理功能。java

從零開始搭建Eureka。

咱們在建立新的項目時,若是選擇了相關SpringCloud的依賴,則會自動在pom.xml配置文件內添加SpringCloud最新穩定版本依賴配置。
spring-cloud-dependencies這個依賴是SpringCloud內所須要依賴的版本維護,在maven項目內若是被<dependencyManagement>內修飾的<dependency>,子項目或者本項目在使用時能夠不用設置版本號,默認使用<dependencyManagement>下<dependency>內設置的版本信息。
正因如此,這也是爲何咱們添加了spring-cloud-dependencies依賴後,在使用相關SpringCloud插件時能夠不用添加version標籤設置導入指定版本的依賴。web

Eureka-server項目,Eureka註冊中心

新建maven項目,其中pom.xml內容以下:spring

<?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.vincent</groupId>
    <artifactId>spring-cloud-eureka-server</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.4.RELEASE</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    </dependencies>

</project>

能夠看到,這裏與普通的springboot惟一區別是添加了eureka-server依賴包。如何使用Eureka?apache

僅僅須要在啓動類上開啓一個註解@EnableEurekaServer就能夠,App.java以下:瀏覽器

package com.vincent;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * Created by iie4b on 2019-6-18 21:27
 */
@SpringBootApplication
@EnableEurekaServer
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

配置application.properties,內容以下:springboot

server.port=8080

eureka.instance.hostname=127.0.0.1
# 是否向服務中心註冊本身
eureka.client.register-with-eureka=false
# 是否檢索服務
eureka.client.fetch-registry=false
# 服務註冊中心的配置內容,指定服務註冊中心的位置
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

其中「defaultZone」是一個魔術字符串後備值,爲任何不表示首選項的客戶端提供服務URL(即它是有用的默認值)。服務器

Eureka是一個高可用的組件,每個實例註冊以後須要向註冊中心發送心跳包,在默認狀況下erureka server也是一個eureka client ,必需要指定一個 server。eureka.client.register-with-eureka=false表示是否向註冊中心註冊本身,默認爲true,true將會在註冊中心看到server本身的服務。架構

啓動App.java,在瀏覽器上輸入http://127.0.0.1:8080/app

能夠看到可視化界面,可是咱們發現這裏並無Application服務,「No instances available」,若是設置eureka.client.register-with-eureka=true將會在這裏顯示出本身的服務,目前尚未其餘服務向服務中心註冊,因此沒有其餘服務。

Eureka-client項目,做爲Eureka服務提供者,provider-A-1

當客戶端註冊Eureka時,它提供關於自身的元數據,例如主機和端口,健康指示符URL,主頁等。Eureka從屬於服務的每一個實例接收心跳消息。若是心跳失敗超過可配置的時間表,則一般將該實例從註冊表中刪除。

新建maven項目,其中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.vincent</groupId>
    <artifactId>spring-cloud-eureka-provider-A-1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.4.RELEASE</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    </dependencies>

</project>

client的依賴與server的依賴幾乎同樣。

在Spring-boot的啓動類上經過註解@EnableEurekaClient 代表本身是一個eurekaclient. 

App.java內容以下:

package com.vincent;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * Created by vincent on 2019-6-18 21:56
 */
@SpringBootApplication
@EnableEurekaClient
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

同時provider-A項目提供一個服務,新建controller/UserController.java

package com.vincent.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by vincent on 2019-6-18 21:58
 */
@RestController
public class UserController {

    @GetMapping("/user/{name}")
    public Map<String,Object> getUser(@PathVariable("name") String userName) {
        Map<String,Object> data = new HashMap<>();
        data.put("id",userName);
        data.put("from","provider-A-1");
        return data;
    }

}

而後配置application.properties,內容以下:

# 註冊中心的註冊地址
eureka.client.service-url.defaultZone=http://127.0.0.1:8080/eureka/

# 服務名稱--調用的時候根據名稱來調用該服務的方法
spring.application.name=service-provider-A
server.port=8081

啓動App.java

從界面裏咱們能夠看到,這個客戶端已經向註冊中心註冊服務了,刷新http://localhost:8080/

能夠看到SERVICE-PROVIDER-A-1已經成功加入進去了。

有標紅的,由於註冊的服務都是高可用的,這裏只檢測到一個服務,產生的預警,不影響使用,等下咱們啓動多個實例就不會了。

測試客戶端方法是否可用:

說明客戶端正常。

再創建一個Eureka-client項目,做爲Eureka服務提供者,provider-A-2

這個服務提供者與上一個服務提供者幾乎同樣。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.vincent</groupId>
    <artifactId>spring-cloud-eureka-provider-A-2</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.4.RELEASE</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    </dependencies>

</project>

爲了與provider-A-1區別,provider-A-2中的UserController.java以下:

@RestController
public class UserController {

    @GetMapping("/user/{name}")
    public Map<String,Object> getUser(@PathVariable("name") String userName) {
        Map<String,Object> data = new HashMap<>();
        data.put("id",userName);
        data.put("from","provider-A-2");
        return data;
    }

}

provider-A-2中的application.properties以下:

# 註冊中心的註冊地址
eureka.client.service-url.defaultZone=http://127.0.0.1:8080/eureka/

# 服務名稱--調用的時候根據名稱來調用該服務的方法
spring.application.name=service-provider-A
server.port=8082

注意這裏的application.name都是service-provider-A

啓動App.java

查看Eureka Server後臺:

發現紅色的警告沒有了,由於咱們有了兩個一樣的服務,提供了高可用服務,還能夠負載均衡。

這兩個服務能夠分別訪問如下:

端口8081表示Provider-A-1的服務

端口8082表示Provider-A-2的服務

創建Eureka-client項目,做爲Eureka服務消費者,consumer-A-1

咱們目前已經提供好了服務provider-A-1和provider-A-2,而且他們有負載均衡的能力。接下來創建消費者,使用服務。

創建消費者,他的pom.xml以下:

<groupId>com.vincent</groupId>
    <artifactId>spring-cloud-eureka-consumer-A-1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.4.RELEASE</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    </dependencies>

創建ConsumerController.java

package com.vincent.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by vincent on 2019-6-19 19:09
 */
@RestController
public class ConsumerController {

    // 啓動的時候要注意,因爲咱們在controller中注入了RestTemplate,因此啓動的時候須要實例化該類的一個實例
    @Autowired
    private RestTemplateBuilder builder;

    @Autowired
    private RestTemplate restTemplate;

    // 使用RestTemplateBuilder來實例化RestTemplate對象,spring默認已經注入了RestTemplateBuilder實例
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return builder.build();
    }

    /**
     * Rest服務端使用RestTemplate發起http請求,而後獲得數據返回給前端
     * @param username
     * @return
     */
    @GetMapping(value = "/gotoUser/{username}")
    @ResponseBody
    public Map<String, Object> getUser(@PathVariable("username") String username) {
        Map<String, Object> data = new HashMap<>();
        /**
         * 地址是http://service-provider
         * 而不是http://127.0.0.1:8082/
         * 由於他向註冊中心註冊了服務,服務名稱service-provider-A,咱們訪問service-provider-A便可
         */
        data = restTemplate.getForObject("http://service-provider-A/user/" + username, Map.class);
        return data;
    }

}

啓動類App.java

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

consumer-A的application.properties內容以下:

# 註冊中心的註冊地址
eureka.client.service-url.defaultZone=http://127.0.0.1:8080/eureka/

# 服務名稱--調用的時候根據名稱來調用該服務的方法
spring.application.name=service-consumer-A
server.port=8083

能夠看到有兩個服務提供方,一個消費者。由於消費者服務沒有負載均衡,因此有警告,能夠忽略。

訪問消費者,瀏覽器輸入http://localhost:8083/gotoUser/vincent

 

能夠實現負載均衡,交替訪問provider-A-1和provider-A-2。

每一個微服務都是一個Eureka-Client,咱們把每一個app(SpringBootApplication)都向註冊中心註冊一個服務。 有時候,某個服務的工做量比較大的時候,咱們能夠多註冊幾個同名稱的微服務,從而讓他們交替工做,減輕單個服務的壓力。

相關文章
相關標籤/搜索