SpringCloud系列(26)--OpenFeign超时控制

前言:在上一章节中我们简单的介绍了如何使用OprnFeign去调用微服务,因为消费侧和服务侧是两个不同的微服务,这样可能会出现超时的现象,例如服务侧需要3秒处理任何才能返回结果,但消费侧可能2秒就断开连接了,这时就会因为时间差而出现连接超时的问题,而本节内容则是关于如果去对OpenFeign进行超时控制。

1、编写代码模拟连接超时
(1)编写providder-payment8001项目PaymentController类的代码
package com.ken.springcloud.controller;

import com.ken.springcloud.entities.CommonResult;
import com.ken.springcloud.entities.Payment;
import com.ken.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
public class PaymentController {

    @Resource
    private PaymentService paymentService;

    @Value("${server.port}")
    private String serverPort;

    @Resource
    private DiscoveryClient discoveryClient;

    @PostMapping("/payment/insert")
    public CommonResult insert(@RequestBody Payment payment) {
        int result = paymentService.insert(payment);
        log.info("插入结果{}",result);
        if(result > 0) {
            return new CommonResult(200,"插入数据库成功,提供服务的端口号为" + serverPort,result);
        }else {
            return new CommonResult(500,"插入数据库失败",result);
        }
    }

    @GetMapping("/payment/get/{id}")
    public CommonResult insert(@PathVariable("id") Long id) {
        Payment payment = paymentService.getPaymentById(id);
        log.info("查询结果{}",payment);
        if(payment != null) {
            return new CommonResult(200,"查询成功,提供服务的端口号为" + serverPort,payment);
        }else {
            return new CommonResult(500,"没有对应的数据,查询失败,查询id" + id,payment);
        }
    }

    @GetMapping("/payment/discovery")
    public Object discovery() {
        //获取eureka内的服务
        List<String> services = discoveryClient.getServices();
        for (String service : services) {
            log.info("***service:" + service);
        }
        //获取服务名为CLOUD-PAYMENT-SERVICE下的实例
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance instance : instances) {
            log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
        }
        return this.discoveryClient;
    }

    @GetMapping("/payment/lb")
    public String getPaymentLB() {
        //返回当前服务的端口号
        return serverPort;
    }

    @GetMapping("/payment/feign/timeout")
    public String paymentFeigntimeout() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //返回当前服务的端口号
        return serverPort;
    }

}
(2)编写cloud-consumer-feign-order80项目PaymentFeignService类的代码
package com.ken.springcloud.service;

import com.ken.springcloud.entities.CommonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
//这里@FeignClient里写的是指定要访问的微服务的名称,表示通过FeignClient去Eureka上面找名称为CLOUD-PAYMENT-SERVICE的微服务的接口
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {

    //指明要调用的CLOUD-PAYMENT-SERVICE的微服务的接口,这里调用的是PaymentController类里的/payment/get/{id}接口
    @GetMapping("/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id);

    @GetMapping("/payment/feign/timeout")
    public String paymentFeigntimeout();
}
(3)编写cloud-consumer-feign-order80项目OrderFeignController的代码
package com.ken.springcloud.controller;

import com.ken.springcloud.entities.CommonResult;
import com.ken.springcloud.entities.Payment;
import com.ken.springcloud.service.PaymentFeignService;
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;

import javax.annotation.Resource;

@Slf4j
@RestController
public class OrderFeignController {

    @Resource
    private PaymentFeignService paymentFeignService;

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
        return paymentFeignService.getPaymentById(id);
    }

    @GetMapping("/payment/feign/timeout")
    public String paymentFeigntimeout() {
        //客户端一般默认等待1秒钟
        return paymentFeignService.paymentFeigntimeout();
    }

}

2、测试payment接口是否正常工作

分别启动eureka-server7001、eureka-server7002,然后再启动provider-payment8001,最后再启动cloud-consumer-feign-order80,全部启动完毕后在浏览器的地址栏里输入http://localhost:8001/payment/feign/timeout 并且回车调用接口,最后可以看到接口调用成功并返回8001,这证明provider-payment8001服务工作正常

3、测试通过consumer服务远程调用payment服务

在浏览器地址栏里输入http://localhost/consumer/payment/feign/timeout 并且回车调用接口,这时会显示Read timed out executing GET http://CLOUD-PAYMENT-SERVICE/payment/feign/timeout的错误信息,这是因为Feign客户端默认只等待一秒钟,但是服务端处理需要超过1秒钟,导致Feign客户端不想等待了,直接返回报错,为了避免这样的情况,有时候我们需要设置Feign客户端的超时控制。

效果图:

4、设置Feign客户端的超时时间

修改cloud-consumer-feign-order80项目的application.yml文件(因为OpenFeign集成了Ribbon,所以OpenFeign的超时控制也由最底层的Ribbon来进行限制,所以这里是对Ribbon进行配置)

集成示意图:

application.yml文件

server:
  port: 80
eureka:
  client:
    #表示是否将自己注册进Eureka Server里,默认为true
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
  #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  ReadTimeout: 5000
  #指的是建立连接后从服务器读取到可用资源所用的时间
  ConnectTimeout: 5000

5、重新测试通过consumer服务远程调用payment服务

重新启动consumer服务,然后重新用浏览器调用http://localhost/consumer/payment/feign/timeout 接口,发现现在并不会再次发生微服务间调用出现连接超时的情况

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/647107.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Django 里的静态资源调用

静态资源&#xff1a;图片&#xff0c;CSS, JavaScript 一共有两种方法 第一种方法 在项目的文件夹里创建名为 static 文件夹 在该文件夹里&#xff0c;添加静态资源 在 settings.py 里添加路径 import os# Static files (CSS, JavaScript, Images) # https://docs.djan…

基于Arduino IDE的ESP32开发环境搭建

文章目录 一. Arduino IDE安装二. Arduino IDE安装ESP开发包 一. Arduino IDE安装 Arduino官网下载IDE软件 解压下载好的安装包&#xff0c;以管理员身份运行Arduino IDE软件 IDE第一次启动会安装各种驱动&#xff0c;直接点击确定就行 二. Arduino IDE安装ESP开发包 将…

只需一行代码提高3DGS重建质量!随机初始化新SOTA

论文标题&#xff1a; Relaxing Accurate Initialization Constraint for 3D Gaussian Splatting 论文作者&#xff1a; Jaewoo Jung, Jisang Han, Honggyu An, Jiwon Kang, Seonghoon Park and Seungryong Kim 导读&#xff1a; 3DGS在新视角合成和三维重建方面展现了令人印…

SSH 远程登录系统和远程拷贝

文章目录 目录 文章目录 前言 一.SSH的基本用法 SSH基本用法&#xff1a; SSH无密码登录 二.SSH安全设置 三.SSH限制用户 前言 很多时候服务器并没有服务器&#xff0c;我们也不能每次都通过控制台去管理服务器&#xff0c;这时候就需要远程登录&#xff0c;相比于Telnet&a…

C语言指针相关知识(第五篇章)(非常详细版)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、sizeof和strlen对比二、数组之间的比较&#xff08;依据strlen和sizeof来呈现&#xff09;&#xff08;一&#xff09;、一维整型数组&#xff08;二&#…

Arthas-快速使用

一、 arthas(阿尔萨斯)的基本介绍 开发人员可以尝试在测试环境或者预发环境中复现生产环境中的问题。但是&#xff0c;某些问题无法在不同的环境中轻松复现&#xff0c;甚至在重新启动后就消失了&#xff0c;如果您正在考虑在代码中添加一些日志以帮助解决问题&#xff0c;您将…

07、SpringBoot 源码分析 - SpringApplication启动流程七

SpringBoot 源码分析 - SpringApplication启动流程七 初始化基本流程SpringApplication的prepareContext准备上下文postProcessApplicationContext处理applyInitializers初始化器初始化load SpringApplication的refreshContext刷新上下文refreshServletWebServerApplicationCon…

力扣538. 把二叉搜索树转换为累加树

Problem: 538. 把二叉搜索树转换为累加树 文章目录 题目描述思路复杂度Code 题目描述 思路 利用二叉搜索树中序遍历的特性&#xff0c;**降序遍历&#xff08;此处是想表达先遍历其右子树再遍历其左子树这样遍历的过程中每个节点值得大小排序是降序得&#xff09;**其节点&…

Mybatis-全局配置文件多数据库支持

这里我们来做一个对比试验&#xff0c;将上门课中使用hibernate做的权限控制项目&#xff0c;从mysql数据库转移到orcale数据库&#xff0c;然后我们在让现在的mybatis入门demo也从使用mysql数据库改orcale&#xff0c;对比一下两者之间的区别&#xff1a; <dependency>…

【C++】二分查找:在排序数组中查找元素的第一个和最后一个位置

1.题目 难点&#xff1a;要求时间复杂度度为O(logn)。 2.算法思路 需要找到左边界和右边界就可以解决问题。 题目中的数组具有“二段性”&#xff0c;所以可以通过二分查找的思想进行解题。 代码&#xff1a; class Solution { public:vector<int> searchRange(vect…

【排序算法】选择排序以及需要注意的问题

选择排序的基本思想&#xff1a;每一次从待排序的数据元素中选出最小&#xff08;或最大&#xff09;的一个元素&#xff0c;存放在序列的起始位置&#xff0c;直到全部待排序的数据元素排完 。 第一种实现方法&#xff1a; void SelectSort(int* arr, int n) {for (int j 0…

阿里云百炼大模型使用

阿里云百炼大模型使用 由于阿里云百炼大模型有个新用户福利&#xff0c;有免费的4000000 tokens&#xff0c;我开通了相应的服务试试水。 使用 这里使用Android开发了一个简单的demo。 安装SDK implementation group: com.alibaba, name: dashscope-sdk-java, version: 2.…

DAMA数据管理知识体系必背18张框图

近期对数据管理知识体系中比较重要的框图进行了梳理总结,总共有18张框图,供大家参考。主要涉及数据管理、数据治理阶段模式、数据安全需求、主数据管理关键步骤,主数据架构、DW架构、数据科学的7个阶段、数据仓库建设活动、信息收敛三角、大数据分析架构图、数据管理成熟度等…

精品丨快速申请免费https证书

https域名证书对提高网站排名有一定的好处&#xff0c;所以当今很多企业为了给网站一个好的安全防护&#xff0c;就会去申请该证书。如今很多企业虽然重视网站的安全防护&#xff0c;但是也重视成本&#xff0c;所以为了节约成本会考虑申请免费的https证书。 第一个好处 企业不…

如何在 DigitalOcean Droplet 云主机上创建 Ubuntu 服务器

在本文中&#xff0c;你将通过 DigitalOcean 的管理面板创建一个 Ubuntu 服务器&#xff0c;并将其配置为使用你的 SSH 密钥。设置好服务器后&#xff0c;你可以在其上部署应用程序和网站。 本教程是DigitalOcean云课程简介的一部分&#xff0c;它指导用户完成将应用程序安全地…

SpringBoot+Vue开发记录(七)-- 跨域文件与Restful风格

本篇文章的主要内容是关于项目的跨域配置和给项目添加restful风格接口。 重点是文件粘贴 文章目录 一、 跨域二、Restful风格1. 什么是restful风格&#xff1f;2. 项目文件结构3. 新建文件4. 在Controller中进行修改 一、 跨域 跨域问题暂时也就那样&#xff0c;解决方法就是…

Unity入门理论+实践篇之Luna

创建世界的主角 父子物体 首先创建一个cube物体 可以观察到其在2D视角下的坐标为&#xff08;0&#xff0c;0&#xff09; 此时将cube物体拖拽到ldle_0下&#xff0c;如图所示&#xff0c;并将其坐标值改为&#xff08;2&#xff0c;2&#xff09; 此时再将ldle_0物体的坐标…

huggingface 笔记:查看GPU占用情况

0 准备部分 0.1 创建虚拟数据 import numpy as npfrom datasets import Datasetseq_len, dataset_size 512, 512 dummy_data {"input_ids": np.random.randint(100, 30000, (dataset_size, seq_len)),"labels": np.random.randint(0, 1, (dataset_size…

Markdown魔法手册:解锁高效写作的新技能

边使用边更新0.0... 文章目录 一、如何在Markdown中插入表情&#xff1f;二、文字样式设置1.文本颜色设置2.文本字号设置3.文本字体设置4. 实战演练5.黄色高亮 一、如何在Markdown中插入表情&#xff1f; 在Markdown中插入表情&#xff08;emoji&#xff09;的方法取决于你使用…

02.并发编程基础概念

在正式学习 Java 的并发编程之前&#xff0c;我们需要熟悉和学习几个并发编程的基础概念。 1 进程和线程 1.1 进程 我们常说的是应用程序&#xff0c;也就是 app&#xff0c;由指令和数据组成。但是当我们不运行一个具体的 app 时&#xff0c;这些应用程序就是放在磁盘(也包括…