转载:原文

总结:

1.pom添加依赖

2.application中填写正确的eureka配置

3.启动项中增加注解

@EnableFeignClients

4.填写正确的调用接口

通过原文使用Feign可能会遇到的问题

Eureka中配置的地址不对,导致消费者调用提供者方法时候,出现链接超时, 这边需要改一下提供者的Eureka的接口配置

正文如下

一、Feign介绍

Feign是一个声明式的伪Http客户端,通过Feign可以实现服务间的相互调用,比如服务A调用服务B暴露的一些接口;同时Feign整合了Ribbon,所以Feign也可以实现服务的负载均衡调用。想要使用Feign也比较简单,定义一个通过注解@FeignClient()指定需要调用的服务的接口,启动类加上@EnableFeignClients开启Feign功能即可。

二、准备工作:

本文同样有三个工程,分别是:

eureka-server: 服务注册中心,端口1111;

feign-service-a: Feign客户端,端口2222;

feign-service-b: 服务提供者,端口3333和4444,需要启动多个实例;

本文主要演示如何在feign-service-a通过feign远程调用feign-service-b中暴露的接口。

三、新建feign-service-b工程

首先引入依赖:

<?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.springcloud.wsh</groupId>
    <artifactId>springcloud_feign_service_b</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>springcloud_feign_service_b</name>
    <description>Feign 服务B</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Camden.SR6</spring-cloud.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</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>

四、新建feign-service-a的配置文件application.yml

server:
#  port: 3333
  port: 4444
spring:
  application:
    name: eureka-feign-service-b
eureka:
  client:
    service-url:
      defaultZone: http://localhost:1111/eureka/

同时启动类加上@EnableDiscoverClient,使其注册到Eureka中

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

五、新建FeignServiceBController.java

该类主要暴露接口给其他服务调用

/**
 * @Title: FeignServiceBController
 * @ProjectName springcloud_feign
 * @Description: 服务BController
 * @Author WeiShiHuai
 * @Date 2018/9/10 15:07
 */
@RestController
public class FeignServiceBController {
 
    private static Logger logger = LoggerFactory.getLogger(FeignServiceBController.class);
 
    @Autowired
    private DiscoveryClient discoveryClient;
 
    @RequestMapping("/getInfo")
    public String getInfo(@RequestParam("name") String name) {
        ServiceInstance serviceInstance = discoveryClient.getLocalServiceInstance();
        String host = serviceInstance.getHost();
        Integer port = serviceInstance.getPort();
        String info = "hello, name = " + name + ", host = " + host + ", port = " + port;
        logger.info(info);
        return info;
    }
 
}

至此,feign-service-b功能已经搭建成功。启动eureka-server以及启动两个feign-service-b实例,用于测试服务的负载均衡调用。

访问http://localhost:1111/可以看到已经成功启动两个feign-service-b实例,端口号分别是3333和4444:

六、新建feign-service-a工程

首先引入pom依赖,注意需要引入Feign的依赖。

<?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.springcloud.wsh</groupId>
    <artifactId>springcloud_feign_service_a</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>springcloud_feign_service_a</name>
    <description>Feign服务A</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Camden.SR6</spring-cloud.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</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>
 

七、新建feign-service-a的配置文件

server:
  port: 2222
spring:
  application:
    #应用名称,Feign通过@FeignClient指定服务名称进行调用
    name: eureka-feign-service-a
eureka:
  client:
    service-url:
      defaultZone: http://localhost:1111/eureka/

八、启动类加上注解@FeignClients以及@EnableDiscoverClient

@FeignClients:主要开启Feign的声明式服务调用功能

@EnableDiscoverClient: 主要注册成为Eureka的一个客户端

/**
 * @Description: Feign远程服务调用(这里模拟A服务通过远程服务调用B服务的接口)
 * @Author: WeiShiHuai
 * @Date: 2018/9/10 15:01
 * Feign是一个声明式的Web Service客户端,使用Feign来创建一个接口并用@FeignClient注解来配置它既可。
 * Spring Cloud为Feign增加了对Spring MVC注解的支持,还整合了Ribbon和Eureka来提供均衡负载的HTTP客户端实现。
 * 通过Feign远程服务调用,方便了各个服务之间的接口调用,就像调用本地方法一样。
 */
@SpringBootApplication
@EnableDiscoveryClient
//@EnableFeignClients注解用于开启Feign远程服务调用功能
@EnableFeignClients
public class SpringcloudFeignServiceAApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(SpringcloudFeignServiceAApplication.class, args);
    }
}

九、新建FeignClient

FeignClient必须是一个接口,类需要加上@FeignClient指定需要调用的服务名称,这个对应application-name,同时可以指定fallback回调方法,这个在feign调用失败的时候执行。

/**
 * @Title: ServiceBFeignClient
 * @ProjectName springcloud_feign
 * @Description: FeignClient
 * @Author WeiShiHuai
 * @Date 2018/9/10 15:15
 * 1. FeignClient必须是一个接口interface
 * 2. 必须加上@FeignClient指定需要调用哪个服务的接口
 * 3. Feign默认集成了Ribbon,所以通过Feign也可以实现服务的负载均衡调用(轮询方式)。
 *
 * Feign的实现的过程大致如下:
    a. 首先通过@EnableFeignClients注解开启FeignClient
    b. 根据Feign的规则实现接口,并加@FeignClient注解
    c. 程序启动后,会进行包扫描,扫描所有的@ FeignClient的注解的类,并将这些信息注入到ioc容器中。
    d. 当接口的方法被调用,通过jdk的代理,来生成具体的RequestTemplate
    e. RequestTemplate在生成Request
    f. Request交给Client去处理,其中Client可以是HttpUrlConnection、HttpClient也可以是Okhttp
    g. 最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡
 *
 */
 //@FeignClient注解通过value指定调用的服务名称,对应application.yml的application-name,如本例为eureka-feign-service-b
//通过fallback指定远程服务调用失败的回调方法,也叫服务降级处理,回调类必须实现使用@FeignClient标识的接口(implements ServiceBFeignClient)
//使用@FeignClient("eureka-feign-service-b")注解来绑定该接口对应feign-service-b服务
@FeignClient(value = "eureka-feign-service-b", fallback = ServiceBFeignClientFallback.class)
public interface ServiceBFeignClient {
 
    /**
     * 编写Feign接口简便的方法:把具体需要远程调用的服务(如服务B)中的方法复制过来,去掉实现即可。
     *
     * @param name
     * @return
     */
    @RequestMapping("/getInfo")
    String getInfo(@RequestParam("name") String name);
 
}

同时,新建ServiceBFeignClientFallback.java指定Feign失败回调方法

/**
 * @Title: ServiceBFeignClientFallback
 * @ProjectName springcloud_feign
 * @Description: FeignClient失败回调方法
 * @Author WeiShiHuai
 * @Date 2018/9/10 15:22
 * FeignClient失败回调方法必须实现使用@FeignClient标识的接口(implements ServiceBFeignClient),实现其中的方法
 */
@Component
public class ServiceBFeignClientFallback implements ServiceBFeignClient {
 
    /**
     * 当服务B由于某种原因使得服务调用不成功时会执行该回调方法
     *
     * @param name
     * @return
     */
    @Override
    public String getInfo(String name) {
        return "sorry " + name + ", feign client error";
    }
 
}

十、新建FeignController.java

通过注入上面定义的ServiceBFeignClient,实现服务间的调用

/**
 * @Title: FeignController
 * @ProjectName springcloud_feign
 * @Description: 测试Feign
 * @Author WeiShiHuai
 * @Date 2018/9/10 15:28
 * 注入FeignClient,调用feignClient的方法实现远程方法调用
 */
@RestController
public class FeignController {
 
    private static Logger logger = LoggerFactory.getLogger(FeignController.class);
 
    @Autowired
    private ServiceBFeignClient serviceBFeignClient;
 
    /**
     * 使用http://localhost:2222/getInfo访问,实际上A服务会通过FeignClient调用服务B提供的getInfo接口
     *
     * @param name
     * @return
     */
    @GetMapping("/getInfo")
    public String getInfo(@RequestParam("name") String name) {
        String info = serviceBFeignClient.getInfo(name);
        logger.info(info);
        return info;
    }
 
}

十一、测试

启动feign-service-a工程,访问http://localhost:1111/,可以看到成功注册到Eureka:

此时访问http://localhost:2222/getInfo?name=weixiaohuai,可以看到我们已经通过Feign实现了在feign-service-a调用feign-service-b的接口

由于我们对feign-service-b启动了两个实例,通过刷新浏览器以及后台打印的日志可以看到Feign通过轮询的方式访问端口为3333或者4444的接口

下面,我们测试一下Feign的服务降级功能,也就是Feign调用失败后的回调方法,下面我们关掉feign-service-b的两个实例,接着访问http://localhost:2222/getInfo?name=weixiaohuai,如下图

可以看到,当feign调用失败后,服务调用并没有死掉,而是执行了失败回调方法。

十二、总结

Feign的实现的过程大致如下:

首先通过@EnableFeignCleints注解开启FeignCleint

根据Feign的规则实现接口,并加@FeignCleint注解

程序启动后,会进行包扫描,扫描所有的@ FeignCleint的注解的类,并将这些信息注入到ioc容器中。

当接口的方法被调用,通过jdk的代理,来生成具体的RequesTemplate

RequesTemplate在生成Request

Request交给Client去处理,其中Client可以是HttpUrlConnection、HttpClient也可以是Okhttp

最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡

通过Feign以接口和注解配置的方式,轻松实现了对feign-service-b服务的绑定,这样我们就可以在本地应用中像本地服务一下的调用它,并且做到了客户端均衡负载。

Spring Cloud Feign声明式服务调用(转载)+遇到的问题的更多相关文章

  1. Spring Cloud Feign 声明式服务调用

    目录 一.Feign是什么? 二.Feign的快速搭建 三.Feign的几种姿态 参数绑定 继承特性 四.其他配置 Ribbon 配置 Hystrix 配置 一.Feign是什么? ​ 通过对前面Sp ...

  2. 笔记:Spring Cloud Feign 声明式服务调用

    在实际开发中,对于服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以我们通常会针对各个微服务自行封装一些客户端类来包装这些依赖服务的调用,Spring Cloud Feign 在此基础上做了进 ...

  3. Spring Cloud 2-Feign 声明式服务调用(三)

    Spring Cloud Feign  1. pom.xml 2. application.yml 3. Application.java 4. Client.java 简化RestTemplate调 ...

  4. spring cloud 系列第4篇 —— feign 声明式服务调用 (F版本)

    源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.feign 简介 在上一个用例中,我们使用ribbon+restTem ...

  5. Feign声明式服务调用

    Feign是一种声明式.模板化的HTTP客户端(仅在Application Client中使用).声明式调用是指,就像调用本地方法一样调用远程方法,无需感知操作远程http请求. Spring Clo ...

  6. SpringCloud微服务实战二:Spring Cloud Ribbon 负载均衡 + Spring Cloud Feign 声明式调用

    1.Spring Cloud Ribbon的作用 Ribbon是Netflix开发的一个负载均衡组件,它在服务体系中起着重要作用,Pivotal将其整合成为Spring Cloud Ribbon,与其 ...

  7. Spring Cloud07: Feign 声明式接口调用

    一.什么是Feign Feign也是去实现负载均衡,但是它的使用要比Ribbon更加简化,它实际上是基于Ribbon进行了封装,让我们可以通过调用接口的方式实现负载均衡.Feign和Ribbon都是由 ...

  8. SpringCloud实战-Feign声明式服务调用

    在前面的文章中可以发现当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率 ...

  9. Spring Cloud Feign 优雅的服务调用

    Fegin 是由NetFlix开发的声明式.模板化HTTP客户端,可用于SpringCloud 的服务调用.提供了一套更优雅.便捷的HTTP调用API,并且SpringCloud整合了Fegin.Eu ...

随机推荐

  1. 10 select、poll以及epoll

    IO复用:为了解释这个名词,首先来理解下复用这个概念,复用也就是共用的意思,这样理解还是有些抽象,为此,咱们来理解下复用在通信领域的使用, 在通信领域中为了充分利用网络连接的物理介质,往往在同一条网络 ...

  2. python之file 方法

    file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数: 1    file.close() close() 方法用于关闭一个已打开的文件.关闭后的文件不能再进行读写操作, 否 ...

  3. php--常见算法2

    <?php function zhi($number){ $f1=1; $f2=1; for($i=3;$i<=$number;$i++){ //前一个的前一个值+前一个值 $f3=$f1 ...

  4. U盘加载速度慢的解决方法

    在日常的生活和工作中,我们经常用U盘存储一些文件和程序.然而,一些朋友发现U盘有时候在使用过程中的识别加载速度非常缓慢.是U盘出故障了吗?其实不尽然,下面就为大家分享一下如何快速解决U盘加载缓慢的方法 ...

  5. 十四,K8s集群网络flannel及canal策略

    目录 k8s网络CNI之flannel k8s网络通信模型 常见CNI插件(Container,Network,Interface) 插件通信一般的解决方案 网络插件的应用 Flannel插件 fla ...

  6. RHEL7中配置本地YUM软件源

     1.创建目录,挂载光盘 [root@localhost ~]# mkdir /mnt/iso [root@localhost ~]# mount /dev/sr0  /mnt/iso mount: ...

  7. 寒武纪C++日常实习生面经(其他人面试题)

    1.C++继承方式? 答:public,protected,private三种继承方式和虚继承一共四种. 派生类可以继承定义在基类中的成员,但是派生类的成员函数不一定有权访问从基类继承而来的成员. 派 ...

  8. 修改虚拟机CentOS系统ip地址和主机名

    按照教程安装了虚拟机但是未配置静态IP,所以导致IP地址经常变化,CRT,mysql等连接时经常出现问题. 所以修改虚拟机内CentOS系统的IP为静态IP. 一.查看当前网关 虚拟机-->[编 ...

  9. linux基础—课堂随笔09_数组

    数组:(6.14 第一节) 取分区利用率,大于百分之八十则发出警报 取分区第一列 取分区使用率: 脚本: 检查脚本语法: ——end 数组切片: 1.跳过前两个取后面 2.跳过前两个取三个 生成10个 ...

  10. Delphi用QJSON解析JSON格式的数据 【转】

    本来用superobject来解析JSON已经够用了,可惜这个东东不能在移动端使用,于是找到QJSON来处理. 这是一个国内高手写开源免费的东西,赞一个. 假入数据如下: {"message ...