前言

上一篇文章我们介绍了 Eureka 服务注册中心 的搭建,这篇文章介绍一下如何使用 Eureka服务注册中心,搭建一个简单的 服务端注册服务,由 客户端 通过 Ribbon 负载均衡 地去调用服务案例。

正文

1. 创建服务提供者

创建一个 service-hi 的 Module,创建完成后的 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>1.5.3.RELEASE</version>

        <relativePath/> <!-- lookup parent from repository -->

    </parent>

    <groupId>io.ostenant.github.springcloud</groupId>

    <artifactId>service-hi</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <name>service-hi</name>

    <description>Demo project for Spring Boot</description>


    <properties>

        <java.version>1.8</java.version>

        <spring-cloud.version>Dalston.SR1</spring-cloud.version>

    </properties>


    <dependencies>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-eureka</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-cloud-starter-web</artifactId>

        </dependency>


        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

            <scope>test</scope>

        </dependency>

    </dependencies>


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

        <plugins>

            <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

            </plugin>

        </plugins>

    </build>

</project>

通过 注解 @EnableEurekaClient 表明自己是一个 EurekaClient。

@SpringBootApplication

@EnableEurekaClient

@RestController

public class ServiceHiApplication {

    public static void main(String[] args) {

        SpringApplication.run(ServiceHiApplication.class, args);

    }

}

创建一个控制器 HelloController,对外提供一个 /hi 的 HTTP 的服务。在响应数据中返回当前 服务实例 的 端口号。

@RestController

public class HelloController {


    @Value("${server.port}")

    private String port;


    @RequestMapping("/hi")

    public String hi(@RequestParam String name) {

        return "Hi " + name + ", I am from port: "  + port;

    }

}

在 配置文件 中注明的 服务注册中心 的地址, application.yml 配置文件如下:

spring:

  active:

    profiles: service-hi1 # service-hi2



---


spring:

  profiles: service-hi1

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8761/eureka/

server:

  port: 8763

spring:

  application:

    name: service-hi



---


spring:

  profiles: service-hi2

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8761/eureka/

server:

  port: 8764

spring:

  application:

    name: service-hi

分别以 spring.profiles.active=hi1 和 spring.profiles.active=hi2 作为 SpringBoot 的 启动命令参数,在 端口号 8763 和 8764 启动 2个 服务提供者 实例。

2. 创建服务消费者

重新新建 service-ribbon 的 Module,在它的 pom.xml 文件分别引入 起步依赖 spring-cloud-starter-eureka、 spring-cloud-starter-ribbon、 spring-boot-starter-web,代码如下:

<?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>1.5.3.RELEASE</version>

        <relativePath/> <!-- lookup parent from repository -->

    </parent>

    <groupId>io.ostenant.github.springcloud</groupId>

    <artifactId>service-ribbon</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <name>service-ribbon</name>

    <description>Demo project for Spring Boot</description>


    <properties>

        <java.version>1.8</java.version>

        <spring-cloud.version>Dalston.SR1</spring-cloud.version>

    </properties>


    <dependencies>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-eureka</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-ribbon</artifactId>

        </dependency>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>


        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

            <scope>test</scope>

        </dependency>

    </dependencies>


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

        <plugins>

            <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

            </plugin>

        </plugins>

    </build>

</project>

在项目的 配置文件 指定服务的 服务注册中心 的地址,应用名称 为 service-ribbon,端口号 为 8762。完整配置文件 application.yml 如下:

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8761/eureka/

server:

  port: 8762

spring:

  application:

    name: service-ribbon

在应用 启动类 上,通过 @EnableDiscoveryClient 向 服务中心 注册自身信息,向 SpringBoot 容器注册一个 RestTemplate 对象,并通过 @LoadBalanced 注解表明这个 RestRemplate 开启 客户端负载均衡 的功能。

@SpringBootApplication

@EnableDiscoveryClient

public class ServiceRibbonApplication {

    public static void main(String[] args) {

        SpringApplication.run(ServiceRibbonApplication.class, args);

    }


    @Bean

    @LoadBalanced

    public RestTemplate restTemplate() {

        return new RestTemplate();

    }

}

写一个 测试接口,注入上面的 RestTemplate 对象来消费 service-hi 服务的 /hi 接口。在 RestTemplate 的 URL 中,我们将具体 服务生产者 的 主机名称 和 端口号 替换为它的 服务名称。

@RestController

public class HelloController {


    @Autowired

    private RestTemplate restTemplate;


    @RequestMapping(value = "/hi")

    public String requestForHi(@RequestParam String name){

        return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);

    }

}

在浏览器上多次访问 http://localhost:8762/hi?name=ribbon,浏览器交替显示:

Hi ribbon, I am from port: 8763

Hi ribbon, I am from port: 8764

在具体的调用过程中, Ribbon 提供的 @LoadBalanced 注解会从 EurekaServer 上查询 服务列表,根据 服务名称 找到 SERVICE-HI 的 服务实例。如果有多个 SERVICE-HI 实例, Ribbon 会根据 客户端负载均衡 算法筛选其中一台,并把 URL 中的 SERVICE-HI 替换为具体实例的 主机名称 和 端口号。

参考

  • 方志朋《深入理解Spring Cloud与微服务构建》
    

欢迎关注技术公众号: 零壹技术栈

本帐号将持续分享后端技术干货,包括虚拟机基础,多线程编程,高性能框架,异步、缓存和消息中间件,分布式和微服务,架构学习和进阶等学习资料和文章。