什么是Eureka,什么是服务注册与发现?

Spring Boot作为目前最火爆的web框架。那么spring boot与Eureka又有什么关联呢?

Eureka是Netflix开源的一个RESTful服务,主要用于服务的注册发现。
Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。
Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。
Netflix在其生产环境中使用的是另外的客户端,它提供基于流量、资源利用率以及出错状态的加权负载均衡。
SpringCloud Eureka是SpringCloud Netflix服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能。

从零开始搭建Eureka。

我们在创建新的项目时,如果选择了相关SpringCloud的依赖,则会自动在pom.xml配置文件内添加SpringCloud最新稳定版本依赖配置。
spring-cloud-dependencies这个依赖是SpringCloud内所需要依赖的版本维护,在maven项目内如果被<dependencyManagement>内修饰的<dependency>,子项目或者本项目在使用时可以不用设置版本号,默认使用<dependencyManagement>下<dependency>内设置的版本信息。
正因如此,这也是为什么我们添加了spring-cloud-dependencies依赖后,在使用相关SpringCloud插件时可以不用添加version标签设置导入指定版本的依赖。

Eureka-server项目,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-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?

仅仅需要在启动类上开启一个注解@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,内容如下:

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/

1111b5cbaf2cb5fbc681c237fe8f395c1df.jpg

可以看到可视化界面,但是我们发现这里并没有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/

ffdd6b2cbcf69becf304de753af849a4791.jpg

可以看到SERVICE-PROVIDER-A-1已经成功加入进去了。

有标红的,因为注册的服务都是高可用的,这里只检测到一个服务,产生的预警,不影响使用,等下我们启动多个实例就不会了。

测试客户端方法是否可用:

4105c9de78ac2579a477419f8f48df1e768.jpg

说明客户端正常。

再建立一个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后台:

9b0b9d5183750d7ecf4c478f4d7f57c833c.jpg

发现红色的警告没有了,因为我们有了两个同样的服务,提供了高可用服务,还可以负载均衡。

这两个服务可以分别访问以下:

9be8030a6c49d99c256794ad4d7b3d40123.jpg

5a24c8cc0d7697ae739fe6cfddcbbb489cf.jpg

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

8d9560c13a366a516817c95c90c8374f096.jpg

可以看到有两个服务提供方,一个消费者。因为消费者服务没有负载均衡,所以有警告,可以忽略。

访问消费者,浏览器输入http://localhost:8083/gotoUser/vincent

d90213b91fbe5cbe6608c0d22f0e013ca5c.jpg

f9c58f8d2d624ba6548c4feb07a8892318e.jpg

 

可以实现负载均衡,交替访问provider-A-1和provider-A-2。

d19f5d3950d5e07777aca3790915b245363.jpg

每个微服务都是一个Eureka-Client,我们把每个app(SpringBootApplication)都向注册中心注册一个服务。
有时候,某个服务的工作量比较大的时候,我们可以多注册几个同名称的微服务,从而让他们交替工作,减轻单个服务的压力。

转载于:https://my.oschina.net/duanvincent/blog/3063507

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐