【Spring Cloud】10_Spring Cloud的声明式服务调用 Feign

Feign 的远程调用

在这里插入图片描述

在这里插入图片描述

之前的系统结构是浏览器直接访问后台服务
在这里插入图片描述

后面我们通过一个Demo项目演示 Spring Cloud 远程调用

在这里插入图片描述

实战案列

添加 Feign,用Feign的声明式客户端接口做远程调用

  1. pom.xml 添加 Feign 依赖

  2. 启动类添加注解: @EnableFeignClients

  3. 定义两个客户端接口:ItemClient 、 UserClient

  4. 修改 OrderServiceImpl 完成远程的调用

通过 Sp04Order 订单服务调用 Sp02Item 商品和 Sp03User 用户服务。

pom.xml

sp04-orderservice 模块中添加 Feign 依赖

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

主程序

启动类添加注解: @EnableFeignClients

@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class Sp04OrderserviceApplication {

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

}

定义两个客户端接口

在这里插入图片描述

配置三条规则:

  • 调用哪个服务
  • 调用哪个路径
  • 向路径提交什么参数

ItemClient

package cn.tedu.sp04.feign;

import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.util.JsonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

@FeignClient(name = "item-service")
public interface ItemClient {

    @GetMapping("/{orderId}")
    JsonResult<List<Item>> getItems(@PathVariable String orderId);

    @PostMapping("/decreaseNumber")
    JsonResult<?> decreaseNumber(@RequestBody List<Item> items);
}

UserClient

package cn.tedu.sp04.feign;

import cn.tedu.sp01.pojo.User;
import cn.tedu.sp01.util.JsonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "user-service")
public interface UserClient {
    @GetMapping("/{userId}")
    JsonResult<User> getUser(@PathVariable Integer userId);

    @GetMapping("/{userId}/score")//  /8/score?score=1000
    JsonResult<?> addScore(
            @PathVariable Integer userId,
            @RequestParam("score") Integer score);
}

OrderServiceImpl

修改 OrderServiceImpl 完成远程的调用

package cn.tedu.sp04.serivce;

import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.sp01.pojo.User;
import cn.tedu.sp01.service.OrderService;
import cn.tedu.sp01.util.JsonResult;
import cn.tedu.sp04.feign.ItemClient;
import cn.tedu.sp04.feign.UserClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author deven
 * @version 1.0
 * @description: TODO
 * @date 2021/10/18 15:51
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    
    @Autowired
    private ItemClient itemClient;
    @Autowired
    private UserClient userClient;

    /**
     * @description: 获取订单信息
     * 同时远程调用 itemClient 服务,获取商品列表
     * 远程调用 userClient 服务,获取用户数据
     * @author deven
     * @date 2021/10/19 20:47
     * @version 1.0
     */
    @Override
    public Order getOrder(String orderId) {
        log.info("获取订单,orderId="+orderId);
        // 远程调用商品,获取商品列表
        JsonResult<List<Item>> items = itemClient.getItems(orderId);
        // 远程调用用户,获取用户数据
        JsonResult<User> user = userClient.getUser(8);// 真实项目中要获取已登录用户的id
        Order order = new Order();
        order.setId(orderId);
        order.setUser(user.getData());
        order.setItems(items.getData());
        return order;
    }

    /**
     * @description: 添加订单信息
     * 下单成功会远程调用 itemClient 服务实现减少商品库存,
     * 远程调用 uerClient 服务增加用户订单
     * @author deven
     * @date 2021/10/19 13:17
     * @version 1.0
     */
    @Override
    public void addOrder(Order order) {
        log.info("添加订单:"+order);
        // 远程调用商品,减少库存
        itemClient.decreaseNumber(order.getItems());
        // 远程调用用户,增加积分
        userClient.addScore(order.getUser().getId(), 1000);
    }
}

访问测试

访问测试,Feign 会把请求分发到 8001 和 8002 两个服务端口上

http://localhost:8201/34

在这里插入图片描述
第一次访问,sp02item-8001 响应
在这里插入图片描述
第二次访问,sp02item-8002 响应

在这里插入图片描述

Feign 的负载均衡

实战案列

Feign 的调用重试

远程调用失败,可以自动发起重试调用

  • 异常

  • 服务器宕机

  • 后台服务阻塞超时
    重试参数:

  • MaxAutoRetries - 单台服务器的重试次数,模式0

  • MaxAutoRetriesNextServer - 更换服务器的次数,默认1

  • ReadTimeout - 等待响应的超时时间,默认1000

  • OkToRetryOnAllOperations - 是否对所有类型请求都重试,默认只对GET请求重试

  • ConnectTimeout - 与后台服务器建立连接的等待超时时间,默认1000

实战案列

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值