从零开始搭建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)都向注册中心注册一个服务。 有时候,某个服务的工做量比较大的时候,咱们能够多注册几个同名称的微服务,从而让他们交替工做,减轻单个服务的压力。

相关文章
相关标签/搜索