本节示例代码在: https://github.com/laolunsi/spring-boot-stack


一、概述

在上一节中,我们利用eureka成功注册了一个client服务,那么疑问来了,我们创建微服务的最终作用还是要去调用它。在SpringCloud下,我们怎么去调用创建的微服务呢?

先看没有微服务的情况,程序A调用程序B:
file

而在微服务架构中,服务调用是这样的:
file

在本篇文章中,我们就来建立这样一个SpringCloud下的服务调用系统。

SpringCloud中常用的服务调用方式有两种:Ribbon和Feign,而Feign是基于Ribbon封装的。这一篇,我们先基于更简单易用的Feign来实现。

官网地址:https://spring.io/projects/spring-cloud-openfeign

Declarative REST Client: Feign creates a dynamic implementation of an interface decorated with JAX-RS or Spring MVC annotations

思路:需要以下三种角色:服务注册中心、服务提供者、服务消费者。

服务注册中心基于之前的eureka构建,服务提供者添加测试接口,而服务调用者需要引入feign的依赖和配置,然后以声明式的方式来调用服务提供者的接口。

注1:这里的服务可以简单理解为Web接口的集合。

注2:本例中的服务注册中心参考上一节建立一个即可,端口号设为8100。SpringBoot使用2.0.x,SpringCloud使用Finchley.RELEASE版本。


二、创建服务提供者

注册一个service-producer服务,端口号8101

添加如下依赖(主要就是eureka-client):

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!-- 引入netlfix-eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </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>

配置文件:

server:
  port: 8101
spring:
  application:
    name: service-provider
eureka:
  client:
    service-url:
      defaultZone: 'http://peer1:8100/eureka'

在Application类上加上@EnableDiscoveryClient注解,也可以使用@EnableEurekaClient

编写一个接口:

package com.example.serviceprovider;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(value = "hello")
public class HelloAction {

    @GetMapping(value = "{name}")
    public String hello(@PathVariable("name") String name) {
        return "hello, " + name + ", this is service provider's response.";
    }
}

三、创建服务消费者

注册一个service-consumer服务,端口号8102

引入eureka-client和feign依赖:

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>

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

        <!-- 引入eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!-- 引入openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </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>

配置文件:

server:
  port: 8102
spring:
  application:
    name: service-consumer
eureka:
  client:
    service-url:
      defaultZone: 'http://peer1:8100/eureka' # eureka服务地址

Application类添加两个注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class ServiceConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceConsumerApplication.class, args);
    }

}

@EnableFeignClients注解使得服务消费者开启了Feign。

下面编写一个@FeignClient对应的接口,如下:

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

// 这里的name对应的就是要调用的服务的名称
@FeignClient(name = "service-provider")
public interface HelloRemote {

    @GetMapping(value = "hello/{name}")
    public String hello(@PathVariable("name") String name);
}

如上,使用了@FeignClient(name = "service-provider")标明对应要调用的服务,name就是服务的名称。

下面的方法与服务提供者(service provider)中编写的接口名称、参数等均相同。

然后在服务消费者里编写一个新的接口,通过调用它来进一步调用服务提供者:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "consumer")
public class TestAction {

    @Autowired
    private HelloRemote helloRemote;

    @GetMapping(value = "test")
    public String consume(String name) {
        String res = helloRemote.hello(name);
        String str = "服务消费者调用服务提供者,提供参数name=" + name + ",获取返回值:" +  res;
        System.out.println(str);
        return str;
    }
}

四、启动与测试

分别启动eureka-server, service-provider, service-consumer,打开浏览器,输入http://localhost:8100,看到如下页面:
file

两个服务都注册成功了。

下面我们测试一下,首先测试一下service-producer提供的接口是否正常:
file

最后我们利用service-consumer的接口来测试服务互相调用是否正常:
file

至此,我们利用Eureka做服务注册与发现,Feign进行服务调用的示例项目已完成。


参考资料

  1. 纯洁的微笑-SpringCloud专栏3-服务提供与调用:http://www.ityouknow.com/springcloud/2017/05/12/eureka-provider-constomer.html
  2. 方志朋-SpringCloud系列3-服务消费者(Feign):https://blog.csdn.net/forezp/article/details/69808079
Last modification:December 25th, 2019 at 11:09 pm
请作者喝杯肥宅快乐水吧!