SpringCloud Alibaba 微服务架构(四)- 服务调用之OpenFeign方式

一、前言

Feign是一个声明式的web service客户端,它使得编写web service客户端更为容易。创建接口,为接口添加注解,即可使用Feign。Feign可以使用Feign注解或者JAX-RS注解,还支持热插拔的编码器和解码器。

Spring Cloud为Feign添加了Spring MVC的注解支持,并整合了Ribbon和Eureka来为使用Feign时提供负载均衡。使用@EnableFeignClients即可开启Feign。

简而言之:

  • Feign采用的是基于接口的注解
  • Feign默认整合了ribbon,具有负载均衡的能力
  • Feign默认整合了Hystrix,具有熔断的能力

二、初探Feign

微服务间的通讯是基于HTTP的,而Feign就是一个伪HTTP请求客户端,通过声明式的Feign客户端可以调用远程微服务,在实现远程微服务调用的过程中,多个实例存在的时候,Ribbon负载均衡器会默认的进行本地负载均衡,默认通过轮询机制进行微服务的调用,Feign默认则是集成了并且支持Ribbon负载均衡。
在这里插入图片描述
下面以订单服务(Order)调用商品服务(Product)为例,搭建环境使用Feign远程调用消费服务

三、父工程

  • 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>org.example</groupId>
    <artifactId>springcloud-ribbon-hystrix</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>springcloud-product</module>
        <module>springcloud-order</module>
    </modules>

    <properties>
        <project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding>
        <project.reporting.outputEncoding> UTF-8 </project.reporting.outputEncoding>
        <java.version> 1.8 </java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- SpringBoot的依赖配置 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Alibaba-Cloud -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

四、商品(Product)工程

  • 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">
    <parent>
        <artifactId>springcloud-ribbon-hystrix</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-product</artifactId>

    <properties>
        <project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding>
        <project.reporting.outputEncoding> UTF-8 </project.reporting.outputEncoding>
        <java.version> 1.8 </java.version>
    </properties>

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

        <!-- actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- Alibaba-nacos服务发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!-- nacos-client -->
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>1.2.0</version>
        </dependency>

        <!-- hystrix断路器 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

        <!-- openfeign客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>
  • application.yml
server:
  port: 8013

spring:
  application:
    name: nacos-product
  cloud:
    nacos:
      discovery:
        #开启服务注册与发现功能
        enabled: true
        #服务注册与发现地址
        server-addr: 130.252.102.241:8848
  • 商品服务接口ProviderController
package com.thinkingcao.product.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * @desc:   生产者-商品服务
 * @author: cao_wencao
 * @date: 2020-04-29 19:48
 */
@RestController
@Slf4j
public class ProviderController {
    @GetMapping(value = "/getProductInfo/{productId}")
    public String getProductInfo(@PathVariable("productId") String productId) {
        log.info("请求进来啦");
        return "Hello Nacos Discovery " + productId;
    }
}

  • 启动类ProductProviderApp
package com.thinkingcao.product;

import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;

/**
 * @desc:  商品服务-提供者
 * @author: cao_wencao
 * @date: 2020-04-29 17:48
 */
@SpringCloudApplication
public class ProductProviderApp {
    public static void main(String[] args) {
        SpringApplication.run(ProductProviderApp.class, args);
    }
}

五、订单(Order)工程

  • 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">
    <parent>
        <artifactId>springcloud-ribbon-hystrix</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-order</artifactId>

    <properties>
        <project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding>
        <project.reporting.outputEncoding> UTF-8 </project.reporting.outputEncoding>
        <java.version> 1.8 </java.version>
    </properties>

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

        <!-- actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- Alibaba-nacos服务发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>nacos-client</artifactId>
                    <groupId>com.alibaba.nacos</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- nacos-client -->
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>1.2.0</version>
        </dependency>

        <!-- hystrix断路器 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

        <!-- openfeign客户端 ,默认集成并开启了ribbon负载均衡-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>
</project>
  • application.yml
server:
  port: 8012

spring:
  application:
    name: nacos-order
  cloud:
    nacos:
      discovery:
        enabled: true
        server-addr: 130.252.102.241:8848
        register-enabled: true
  • 定义Feign客户端OrderFeign

OrderFeign 中引入了Hystrix熔断器组件起到服务的保护降级作用,@FeignClient注解当中使用断路器支持的有两种方式fallback 和fallbackFactory

关于Feign Hystrix Fallbacks:
第一种:Hystrix支持回退的概念:当它们的电路断开或出现错误时,将执行默认代码路径。要为给定@FeignClient集启用后备,该fallback属性应为实现后备的类名称。您还需要将实现声明为Spring bean

package com.thinkingcao.order.feign;

import com.thinkingcao.order.feign.callback.OrderFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @desc:   订单调用商品服务
 * @author: cao_wencao
 * @date: 2020-04-29 20:19
 */
@FeignClient(name = "nacos-product",fallback = HystrixClientFallback.class)
public interface OrderFeign {

    @GetMapping(value = "/getProductInfo/{productId}")
    public String getProductInfo(@PathVariable("productId") String productId);

    static class HystrixClientFallback implements OrderFeign {
        @Override
        public String getProductInfo(String productId) {
            return "fallback; reason was:  服务忙,稍后重试" ;
        }
    }
}

第二种: 如果需要访问引起后备触发器的原因,则可以使用fallbackFactory inside的属性@FeignClient。说白了就是如果你想知道服务调用为什么失败了,可以使用下面这种断路器方式。

package com.thinkingcao.order.feign;

import com.thinkingcao.order.feign.callback.OrderFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @desc:   订单调用商品服务
 * @author: cao_wencao
 * @date: 2020-04-29 20:19
 */
@FeignClient(name = "nacos-product",fallbackFactory = OrderFeignFallbackFactory.class)
public interface OrderFeign {

    @GetMapping(value = "/getProductInfo/{productId}")
    public String getProductInfo(@PathVariable("productId") String productId);

    @Component
    @Slf4j
    static class OrderFeignFallbackFactory implements FallbackFactory<OrderFeign> {
      @Override
      public OrderFeign create(Throwable throwable) {
         log.error("调用异常:"+ throwable.toString());
         return new OrderFeign() {
            @Override
            public String getProductInfo(String string) {
                return "开启断路-fallback; reason was: "+ throwable;
            }
        };
      }
}

参考自官网: https://cloud.spring.io/spring-cloud-static/spring-cloud-openfeign/2.2.2.RELEASE/reference/html/#spring-cloud-feign-overriding-defaults

在这里插入图片描述

  • 服务消费OrderController
package com.thinkingcao.order.controller;

import com.thinkingcao.order.feign.OrderFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * @desc:  消费者-订单服务
 * @author: cao_wencao
 * @date: 2020-04-29 19:50
 */
@RestController
@Slf4j
public class OrderController {
    @Autowired(required = false)
    private OrderFeign orderFeign;

    @GetMapping("/getProduct/{productId}")
    public String getProduct(@PathVariable("productId") String id){
        String response = orderFeign.getProductInfo(id);
        log.info("调用服务结束: "+ response);
        return response;
    }
}
  • 启动类OrderConsumerApp

1.@SpringCloudApplication: 组合注解:

  • @SpringBootApplication(启动SPringBoot程序)
  • @EnableDiscoveryClient(开启服务注册与发现)
  • @EnableCircuitBreaker(开启断路器)

2.@EnableFeignClients: 开启Feign客户端

package com.thinkingcao.order;

import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @desc:  订单服务-消费者
 * @author: cao_wencao
 * @date: 2020-04-29 17:50
 */
@SpringCloudApplication
@EnableFeignClients
public class OrderConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(OrderConsumerApp.class, args);
    }
}

五、测试

地址: http://130.252.102.241:8012/getProduct/1010110

访问结果: Hello Nacos Discovery 1010110
在这里插入图片描述

六、源码

https://github.com/Thinkingcao/SpringCloudLearning/tree/master/springcloud-ribbon-hystrix

七、Spring Cloud Alibaba教程

1. 下一篇: Spring Cloud Alibaba教程五》- 使用Nacos实现分布式配置中心

2. Nacos官方文档: https://nacos.io/zh-cn/docs/what-is-nacos.html

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thinkingcao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值