Feign概述

远程调用:声明式客户端

只需要声明一个抽象接口,将可以通过接口做远程调用,不需要再使用RestTemplate来调用。

调用流程:
image.png

第一步:创建springboot项目sp09-feign
image.png
第二步:添加相关依赖和sp01-commons依赖
image.png
添加sp01-commons依赖:

<dependency>
   <groupId>cn.tedu</groupId>
   <artifactId>sp01-commons</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>

第三步:配置yml文件

spring:
  application:
    name: feign
server:
  port: 3001
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka
#调整ribbon的重试参数
ribbon:
  MaxAutoRetries: 1
# 只针对item-service这一个服务有效,
# 对其他服务不应用这个配置
item-service:
  ribbon:
    MaxAutoRetries: 2

第四步:主程序添加@EnableFeignClients注解

package cn.tedu.sp09;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@SpringBootApplication
public class Sp09FeignApplication {
   public static void main(String[] args) {
      SpringApplication.run(Sp09FeignApplication.class, args);
   }
}

第五步:创建ItemClient、UserClient、OrderClient接口

//根据服务id,从注册表得到主机地址
@FeignClient(name = "item-service")
public interface ItemClient {
    @GetMapping("/{orderId}")
    JsonResult<List<Item>> getItems(@PathVariable String orderId);
    @PostMapping("/decreaseNumber")
    JsonResult<?> decreaseNumber(@RequestBody List<Item> irems);//从请求协议体中获取数据
}
//根据服务id,从注册表得到主机地址
@FeignClient(name = "user-service")
public interface UserClient {
    @GetMapping("/{userId}")
    JsonResult<User> getUser(@PathVariable Integer userId);
//                /8/score?score=1000
 @GetMapping("/{userId}/score")
    JsonResult<?> addScore(@PathVariable Integer userId,
                           @RequestParam Integer score);
}
@FeignClient(name = "order-service")
public interface OrderClient {
    @GetMapping("/{orderId}")
    JsonResult<Order> getOrder(@PathVariable String orderId);
    @GetMapping("/")
    JsonResult<?> addOrder();
}

第六步:创建FeignController

类似于springmvc的controller配置结构。

package cn.tedu.sp09.controller;
import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.sp01.pojo.User;
import cn.tedu.sp09.feign.ItemClient;
import cn.tedu.sp09.feign.OrderClient;
import cn.tedu.sp09.feign.UserClient;
import cn.tedu.web.util.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@Slf4j
public class FeignController {
    @Autowired
 private ItemClient itemClient;
    @Autowired
 private OrderClient orderClient;
    @Autowired
 private UserClient userClient;
    @GetMapping("/item-service/{orderId}")
    public JsonResult<List<Item>> getItems(@PathVariable String orderId){
        return itemClient.getItems(orderId);
    }
    @PostMapping("/item-service/decreaseNumber")
    public JsonResult<?> decreaseNumber(@RequestBody List<Item> items){
        return itemClient.decreaseNumber(items);
    }
    @GetMapping("/user-service/{userId}")
    public JsonResult<User> getUser(@PathVariable Integer userId){
        return userClient.getUser(userId);
    }
    @GetMapping("/user-service/{userId}/score")
    public JsonResult<?> addScore(@PathVariable Integer userId,Integer score){
        return userClient.addScore(userId, score);
    }
    @GetMapping("/order-service/{orderId}")
    public JsonResult<Order> getOrder(@PathVariable String orderId){
        return orderClient.getOrder(orderId);
    }
    @GetMapping("/order-service/")
    public JsonResult<?>  addOrder(){
        return orderClient.addOrder();
    }
}

第七步:启动服务,进行测试
http://localhost:3001/item-service/35

Feign集成Ribbon

feign已默认开启ribbon负载均衡重试机制。
可在yml中配置ribbon的超时和重试时间。

#全局配置
ribbon:
  ConnectTimeout: 1000
  ReadTimeout: 1000
  
#单体服务器配置
item-service:
  ribbon:
    MaxAutoRetries: 1
    MaxAutoRetriesNextServer: 2
    ConnectTimeout: 1000
    ReadTimeout: 500

Feign集成Hystrix

Feign默认不启用Hystrix,不推荐启用Hystrix。

第一步:sp09中pom添加Hystrix起步依赖

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

第二步:yml中启用hystrix

# 启用hystrix
feign:
  hystrix:
    enabled: true

第三步:主程序上添加@EnableCircuitBreaker注解,启用hystrix断路器。

package cn.tedu.sp09;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableCircuitBreaker
@EnableFeignClients
@SpringBootApplication
public class Sp09FeignApplication {
   public static void main(String[] args) {
      SpringApplication.run(Sp09FeignApplication.class, args);
   }
}

添加降级

调用超时或失败则访问降级类进行输出返回。
image.png

第一步:ItemClient、UserClient、OrderClient接口中注解内添加降级类

//根据服务id,从注册表得到主机地址
@FeignClient(name = "item-service",fallback=ItemClientFB.class)
public interface ItemClient {
    @GetMapping("/{orderId}")
    JsonResult<List<Item>> getItems(@PathVariable String orderId);
    @PostMapping("/decreaseNumber")
    JsonResult<?> decreaseNumber(@RequestBody List<Item> irems);//从请求协议体中获取数据
}
@FeignClient(name = "order-service",fallback=OrderClientFB.class)
@FeignClient(name = "user-service",fallback=UserClientFB.class)

第二步:创建ItemClient、UserClient、OrderClient接口的降级实现类ItemClientFB、UserClientFB、OrderClientFB。
添加@Component注解将降级类交给spring管理,并重写接口类的方法,设置降级输出。

package cn.tedu.sp09.feign;
import cn.tedu.sp01.pojo.Item;
import cn.tedu.web.util.JsonResult;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ItemClientFB implements ItemClient{
    @Override
 public JsonResult<List<Item>> getItems(String orderId) {
        return JsonResult.err().msg("无法获取订单商品列表");
    }
    @Override
 public JsonResult<?> decreaseNumber(List<Item> irems) {
        return JsonResult.err().msg("无法修改商品库存");
    }
}
package cn.tedu.sp09.feign;
import cn.tedu.sp01.pojo.User;
import cn.tedu.web.util.JsonResult;
import org.springframework.stereotype.Component;
@Component
public class UserClientFB implements UserClient{
    @Override
 public JsonResult<User> getUser(Integer userId) {
        return JsonResult.err().msg("无法获取用户信息");
    }
    @Override
 public JsonResult<?> addScore(Integer userId, Integer score) {
        return JsonResult.err().msg("无法增加用户积分");
    }
}
package cn.tedu.sp09.feign;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.web.util.JsonResult;
import org.springframework.stereotype.Component;
@Component
public class OrderClientFB implements OrderClient{
    @Override
 public JsonResult<Order> getOrder(String orderId) {
        return JsonResult.err().msg("无法获取商品订单");
    }
    @Override
 public JsonResult<?> addOrder() {
        return JsonResult.err().msg("无法保存订单");
    }
}

第三步:启用服务器进行测试
当访问服务出错时,访问降级类进行输入。
http://localhost:3001/item-service/35
image.png

添加熔断

降级配置完成,熔断自动开启。

添加监控

第一步:添加actuator依赖

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

第二步:在yml中设置暴露端点配置

# 暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream

第三步:访问监控测试
http://localhost:3001/actuator/
image.png


木安
13 声望6 粉丝