当前位置: 首页 > news >正文

上游服务不可用了,下游服务如何应对?

上游服务不可用了,下游服务如何应对?

引言

  • 在系统中,上游服务和下游服务是两个关键概念。上游服务通常指的是提供某种功能或数据的服务端,它接收来自下游服务的请求,并根据请求进行处理和响应。下游服务通常指的是发起请求并依赖上游服务的客户端,它们通过发送请求向上游服务请求数据或执行某些操作。
  • 上游服务和下游服务之间的协作是系统中实现整体功能的关键。上游服务提供了核心的业务逻辑和数据,下游服务则依赖于上游服务来完成其特定任务。
  • 下游服务的稳定性和可用性直接依赖于上游服务的可靠性和性能。如果上游服务不可用或出现故障,同时下游服务没有采取任何应对措施,此时将可能出现以下问题:
  • 无法正常执行任务:下游服务可能无法执行其功能,因为它依赖于上游服务的数据或资源。这将导致下游服务无法正常工作。
  • 延迟和性能下降:如果下游服务不对上游服务的不可用进行适当处理,而是无限期等待或不断尝试请求,系统的响应时间会增加,导致性能下降。
  • 级联故障:如果下游服务继续发起大量的请求到不可用的上游服务,它可能会导致下游服务资源被全部占用,无法为其他请求提供服务。这可能导致级联故障,使整个系统不可用。
  • 因此,下游服务应该采取适当的应对措施来处理上游服务不可用的情况,以确保系统的稳定性和可用性。

情况分类

  • 对于上游服务的不可用,此时可以区分为短暂不可用和长时间不可用两种情况,从而采用不同的方式来进行处理。
  • 短暂不可用,是指上游服务在一段时间内暂时无法提供正常的服务,通常是由于网络波动或负载过高等原因导致的。这种情况下,上游服务可能会在很短的时间内自行恢复,并重新可用。短暂不可用通常持续时间较短,可以通过重试机制来处理。下游服务可以在请求失败后进行重试,直到上游服务恢复正常。
  • 长时间不可用,是指上游服务在较长的时间内无法提供正常的服务,无法自行恢复或恢复时间较长。这种情况可能是由于严重的故障、系统崩溃,或其他长期性问题导致的。在这种情况下,简单地进行无限制的重试可能会导致系统被该请求全部占用,甚至引发级联故障。
  • 短暂不可用和长时间不可用是上游服务不可用的两种常见情况,它们需要不同的应对策略。了解并区分这两种情况对于确保系统的稳定性和可用性至关重要。

短暂不可用

处理方式

  • 短暂的不可用可能只是临时性的,可能是网络拥塞或其他暂时性问题导致的。此时可以通过重试机制,下游服务可以尝试重新发送请求,增加请求成功的机会,避免由于系统的短暂不可用导致请求的失败。

代码示例

  • 重试机制在许多客户端库中已经成为标准功能。这些客户端库提供了一些配置选项,以控制重试行为。下面是一个使用gRPC的示例代码,展示了如何配置和使用重试机制,然后基于此避免由于系统的短暂不可用导致请求的失败。

  • 首先展示服务端代码,用于向外提供服务:

  • package mainimport ("context""log""net"pb "path/to/your/protobuf""google.golang.org/grpc"
    )type server struct {pb.UnimplementedYourServiceServer
    }func (s *server) YourRPCMethod(ctx context.Context, req *pb.Request) (*pb.Response, error) {// 处理请求逻辑return &pb.Response{Message: "Hello, world!"}, nil
    }func main() {listener, err := net.Listen("tcp", ":50051")if err != nil {log.Fatalf("Failed to listen: %v", err)}srv := grpc.NewServer()pb.RegisterYourServiceServer(srv, &server{})log.Println("Server started")if err := srv.Serve(listener); err != nil {log.Fatalf("Failed to serve: %v", err)}
    }
    
  • 接下来展示客户端代码,其在服务端出现错误时,会进行重试,避免由于服务的短暂不可用,导致请求的失败,保证系统的可用性:

  • package mainimport ("context""log""time"pb "path/to/your/protobuf" "google.golang.org/grpc"
    )func main() {conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())if err != nil {log.Fatalf("Failed to connect: %v", err)}defer conn.Close()client := pb.NewYourServiceClient(conn)// 设置重试次数和超时时间retryOptions := []grpc.CallOption{grpc.WithRetryMax(3),           // 最大重试次数grpc.WithTimeout(5 * time.Second), // 超时时间}// 发起 gRPC 请求(带重试和超时时间)ctx := context.Background()response, err := client.YourRPCMethod(ctx, &pb.Request{}, retryOptions...)if err != nil {log.Fatalf("Failed to make request: %v", err)}log.Println("Response:", response.Message)
    }
    
  • 在客户端代码中,我们通过 grpc.WithRetryMax 设置最大重试次数,通过 grpc.WithTimeout 设置超时时间。

  • 这样,当遇到服务端短暂不可用时,客户端将进行最多 3 次的重试,并在每次重试时设置 5 秒的超时时间。能够让上游服务在短暂不可用情况下,仍然能够最大限度得保证下游服务请求的成功。

最佳实践

  • 但是并非当请求失败时,便不断进行重试,直到请求成功,需要设置适当的重试策略和超时机制。避免由于大量的重试导致下游服务压力变大,从而导致服务从短暂不可用转变成了长时间不可用。
  • 首先确定最大重试次数,根据系统需求和上游服务的特性,确定最大重试次数。避免无限制地进行重试,因为过多的重试可能会给上游服务造成过大的负担。通常,3-5次重试是一个常见的值,但具体数字应根据实际情况进行调整。
  • 其次设置合理的超时时间,为了避免下游服务长时间等待不可用的上游服务,设置合理的请求超时时间是很重要的。超时时间应根据上游服务的预期响应时间和网络延迟进行调整。一般来说,超时时间应该在几秒钟的范围内,以确保及时地放弃不可用的请求并进行后续处理。

长时间不可用

会导致的问题

  • 长时间不可用的情况可能导致严重的问题,其中包括系统资源被全部占用和级联故障的风险。
  • 首先是上游服务可能直接崩溃。当上游服务面临大量请求失败时,如果下游服务仍然持续地发起请求并无脑重试,此时随着请求数的增加,系统的资源(例如线程、内存、连接等)将被耗尽,导致系统无法处理其他的请求。结果是整个系统变得不可响应,甚至崩溃。
  • 其次是级联故障的风险。长时间不可用的上游服务可能引发级联故障。在分布式系统中,不同的服务通常相互依赖和交互,上游服务的不可用性可能会影响到下游服务。如果下游服务在遇到上游服务不可用时不具备合适的应对机制,它们可能会继续尝试发送请求,造成资源浪费和堆积。这样的情况可能导致下游服务也不可用,甚至影响到更多的依赖系统,最终导致整个系统的级联故障。
  • 所以,我们在设计系统时,下游服务在一些关键节点应该采取适当的应对措施来处理上游服务不可用的情况,以确保系统的稳定性和可用性。

处理方式

  • 当上游服务长时间不可用时,下游服务需要采取一些措施来处理这个问题,以避免系统资源被全部占用和防止级联故障的发生。有两种常见的处理方式:引入熔断器和数据降级。
  • 首先可以引入熔断器:熔断器是一种用于监控上游服务可用性并在需要时进行熔断的机制。当上游服务长时间不可用时,熔断器会直接熔断下游服务对上游服务的请求,而不是无脑地继续发送请求。这样可以避免下游服务持续占用系统资源,并且防止级联故障的发生。
  • 熔断器通常有三个状态:关闭状态、打开状态和半开状态。在关闭状态下,请求会正常通过;当错误率达到一定阈值时,熔断器会打开,所有请求都会被熔断;在一段时间后,熔断器会进入半开状态,允许部分请求通过,以检查上游服务是否已经恢复正常。通过熔断器的状态转换,下游服务可以更好地适应上游服务的不可用情况。
  • 其次是进行数据缓存与降级,如果上游服务提供的数据不是实时性要求很高,下游服务可以考虑在上游服务可用时缓存一部分数据。当上游服务不可用时,下游服务可以使用已经缓存的数据作为降级策略,确保系统的正常运行。这样可以减少对上游服务的依赖,避免系统资源被全部占用。
  • 两种常见的方式,可以帮助下游服务在上游服务长时间不可用的情况下保持稳定性,并避免系统资源被全部占用和级联故障的发生。

代码示例

  • 下面展示一个示例代码,展示下游服务向上游服务发送请求,并实现熔断机制和缓存降级操作,从而在上游服务不可用时,保证下游服务的稳定性:

  • package mainimport ("fmt""sync""time""github.com/sony/gobreaker"
    )var (circuitBreaker *gobreaker.CircuitBreakercache          map[string]stringcacheMutex     sync.RWMutex
    )func main() {// 初始化熔断器circuitBreaker = gobreaker.NewCircuitBreaker(gobreaker.Settings{Name:        "MyCircuitBreaker",MaxRequests: 3,                  // 最大请求数Interval:    5 * time.Second,    // 统计时间窗口Timeout:     1 * time.Second,    // 超时时间ReadyToTrip: customTripFunc,     // 自定义熔断判断函数})// 初始化缓存cache = make(map[string]string)// 模拟下游服务发送请求for i := 0; i < 10; i++ {response, err := makeRequest("https://baidu.com")if err != nil {fmt.Println("Request failed:", err)} else {fmt.Println("Response:", response)}time.Sleep(1 * time.Second) // 间隔一段时间再次发送请求}
    }// 发送请求的函数
    func makeRequest(url string) (string, error) {// 使用熔断器包装请求函数response, err := circuitBreaker.Execute(func() (interface{}, error) {// 假设向上游服务发送 HTTP 请求// ...// 返回响应数据或错误return "Response from  service", nil})if err != nil {// 请求失败,使用缓存降级cacheMutex.RLock()cachedResponse, ok := cache[url]cacheMutex.RUnlock()if ok {return cachedResponse, nil}return "", err}// 请求成功,更新缓存cacheMutex.Lock()cache[url] = response.(string)cacheMutex.Unlock()return response.(string), nil
    }// 自定义熔断判断函数,根据实际情况进行判断
    func customTripFunc(counts gobreaker.Counts) bool {// 根据失败次数或其他指标来判断是否触发熔断return counts.ConsecutiveFailures > 3
    }
    
  • 上述代码示例中,使用了gobreaker开源项目实现了熔断机制,并使用本地缓存实现了缓存降级操作。

  • 在发送请求的函数makeRequest中,使用熔断器包装请求函数,在请求函数内部实际发送请求给上游服务。如果请求成功,则更新缓存,并返回响应。

  • 如果请求失败,则再次尝试从缓存中获取数据,如果缓存中存在,则返回缓存的响应。如果缓存中也不存在数据,则返回错误。

  • 这样,下游服务可以在上游服务不可用的情况下,通过缓存提供一定的降级功能,避免对上游服务进行频繁无效的请求。而熔断机制则可以在下游服务可用性不高时,直接熔断请求,减少对上游服务的负载,提高整体系统的稳定性。

总结

  • 本文主要介绍了上游服务不可用时,下游服务的应对措施。主要分为短暂不可用和长时间不可用两种情况。
  • 短暂不可用通常由网络波动或其他暂时性问题导致。在这种情况下,可以采用重试机制来成功请求上游服务,确保资源的可用性。重试机制是一种简单而有效的方法,通过多次重试请求,以应对短暂的不可用情况,避免下游服务受到影响。
  • 长时间不可用可能导致严重的问题,如上游服务崩溃或级联故障。为了应对这种情况,可以引入熔断器保护机制来确保下游服务的稳定性。熔断器能够快速切断对不可用的上游服务的请求,避免系统资源被全部占用。此外,根据具体服务的特性,可以考虑使用缓存降级来处理长时间不可用的情况。通过缓存上游服务的响应数据,即使上游服务不可用,下游服务仍可以从缓存中获取数据,保持服务的可用性。
  • 综上所述,重试机制和熔断器是应对上游服务不可用的关键措施。重试机制适用于短暂不可用情况,而熔断器则用于长时间不可用的情况下保护下游服务。此外,根据具体情况,采用缓存降级等策略可以进一步提升服务的稳定性和可用性。

-----------------------------------------------------------------------------------

offer突击训练营简介:

1:针对不知道怎么面试,面试没有信心的小伙伴,我们会给你一个offer保障。

2:我们会监督你15-20天内把面试体系技术点掌握至少7成,这样足够你去找到满意的工作了。

3:我们是面向面试学习指导,不会带你们去写代码,会把项目真实开发的迭代过程和技术细节如何实现业务功能都详细教清楚,你能在面试中流畅表达清楚就行了,项目经验你不用担心(技术老师提供的真实项目经验肯定拿的出手),自己学和别人带着系统学,效率完全不一样。

详情请点击这里:offer突击训练营,给你一个offer的保障,求职跳槽的看过来!

相关文章:

上游服务不可用了,下游服务如何应对?

上游服务不可用了&#xff0c;下游服务如何应对&#xff1f; 引言 在系统中&#xff0c;上游服务和下游服务是两个关键概念。上游服务通常指的是提供某种功能或数据的服务端&#xff0c;它接收来自下游服务的请求&#xff0c;并根据请求进行处理和响应。下游服务通常指的是发…...

WebGL笔记:矩阵的变换之平移的实现

矩阵的变换 变换 变换有三种状态&#xff1a;平移、旋转、缩放。当我们变换一个图形时&#xff0c;实际上就是在移动这个图形的所有顶点。解释 webgl 要绘图的话&#xff0c;它是先定顶点的&#xff0c;就比如说我要画个三角形&#xff0c;那它会先把这三角形的三个顶点定出来…...

XTU-OJ 1187-Candy

WCB某天买了非常多的糖果并把它们分成N份&#xff0c;依次分别有1&#xff0c;2&#xff0c;3…,N个糖果。他想拿出其中的3份分给他的室友&#xff0c; 为了不让室友们闹意见&#xff0c;必须让这三份的糖果总数恰好能被三人均分。请问他一共有多少种不同的组合方案数&#xff…...

基于 nodejs+vue城市轨道交通线路查询系统mysql

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…...

电商时代,VR全景如何解决实体店难做没流量?

近日&#xff0c;电商和实体经济的对立成为了热门话题&#xff0c;尽管电商的兴起确实对线下实体店造成了一定的冲击&#xff0c;但实体店也不是没有办法挽救。VR全景助力线下实体店打造线上店铺&#xff0c;打通流量全域布局&#xff0c;还能实现打开产品、查看产品内部细节等…...

操作系统-浅谈CPU与内存

目录 计算机的基本组成CPU内存虚拟内存内存分段内存分页 CPU与内存的交互过程高速缓存cache 所有图片均来自&#xff1a;小林coding 计算机的基本组成 计算机由软件和硬件组成 硬件由CPU(中央处理器&#xff09;存储器(内存外存&#xff09;外部设备组成。 软件由应用软件和系…...

K8s 部署 CNI 网络组件+k8s 多master集群部署+负载均衡

------------------------------ 部署 CNI 网络组件 ------------------------------ ---------- 部署 flannel ---------- K8S 中 Pod 网络通信&#xff1a; ●Pod 内容器与容器之间的通信 在同一个 Pod 内的容器&#xff08;Pod 内的容器是不会跨宿主机的&#xff09;共享同一…...

若依微服务上传图片文件代理配置

在使用若依微服务文件上传时候,文件上传成功会上传到D:/ruoyi/uploadPath目录下。默认使用9300端口进行访问图片文件,现在我想把它代理到80端口应该怎么做呢? 配置前:http://localhost:9300/statics/2023/09/24/test.jpg 配置后:http://localhost/statics/2023/09/24/test…...

物联网与 Linux 的相爱相生

Linux 无疑将在物联网中扮演一个关键角色&#xff0c;但是其光彩将与其它的一些分享。 随着 Canonical 重新关注于赢利和新技术&#xff0c;我们中的一些人发现我们正在思考 Linux 未来将走向何方&#xff0c;IoT&#xff08;物联网&#xff09;是否是 Linux 的未来&#xff1…...

python自动化测试(一):操作浏览器

通过Python的代码去操作浏览器的操作 目录 目录 1、导入自动化模块 2、定义打开的浏览器驱动、声明一个url变量保存打开的地址 3、使用函数&#xff1a;driver.get(url)打开浏览器的指定页面 4、最大化浏览器窗口&#xff1a;driver.maximize_window() 5、添加全局的等待…...

NReco.LambdaParser使用案例

使用案例集合&#xff1a; private async void RuleEngine_Click(object sender, EventArgs e){#region 获取变量string expression this.Rule.Text.Trim();string pattern "\$(.*?)\$";MatchCollection matches Regex.Matches(expression, pattern);foreach (Ma…...

苹果IOS安装IPA, plist形式 Safari 浏览器点击安装

快速链接 苹果开发者账号链接 网址: https://developer.apple.com/account 苹果应用上架链接 网址: https://appstoreconnect.apple.com/ 应用证书文件及打包 参考教程: 最新uniapp打包IOS详细步骤&#xff08;2022&#xff09; 证书在线制作工具 网址: https://app.121xuexi.…...

Django 注册及创建订单商品

注册功能的实现 user/views from rest_framework.generics import GenericAPIView from rest_framework.views import APIViewfrom apps.user.models import User from apps.user.serializers import UserSerializer from utils import ResponseMessage from utils.jwt_auth …...

15、Python -- 阶段总结:变量与流程控制

目录 变量变量没有类型&#xff0c;数据有类型 表达式程序流程 变量 变量&#xff1a;编程的本质就是处理数据&#xff0c;数据需要用变量保存 Python语言的特征&#xff1a; 所有变量无需声明&#xff0c;即可使用 变量没有类型 变量没有类型&#xff0c;数据有类型 已学过…...

信息检索与数据挖掘 | 【实验】排名检索模型

文章目录 &#x1f4da;实验内容&#x1f4da;相关概念&#x1f4da;实验步骤&#x1f407;分词预处理&#x1f407;构建倒排索引表&#x1f407;计算query和各个文档的相似度&#x1f407;queries预处理及检索函数&#x1f525;对输入的文本进行词法分析和标准化处理&#x1f…...

玩转AIGC:打造令人印象深刻的AI对话Prompt

玩转AIGC&#xff1a;打造令人印象深刻的AI对话Prompt 《玩转AIGC&#xff1a;打造令人印象深刻的AI对话Prompt》摘要引言正文良好的Prompt&#xff1a;引发AI深度交流的法宝 ✨探讨不同的提问方式1. 常规提问2. 创意提问 对话交流的艺术&#xff1a;倾听与引导的巧妙平衡 ⚖️…...

uniapp vue国际化 i18n

一、安装 vue-i18n npm i vue-i18n 二、新建i18n目录 1、en.json 内容 {"loginPage":{"namePh":"Please enter your login account","passwordPh":"Please enter password"} } 2、zh-CN.json 内容 {"loginPage&qu…...

Docker 启动远程服务访问不了

今天一下午在弄这个 1、防火墙是否关了 firewall-cmd --state2、ip转发开没开 sysctl net.ipv4.ip_forward3、service iptables是不是打开并拦截了 4、检查docker启动的端口号是否一致&#xff0c;或者启动时对不对 5、检查docker的服务是否起来了&#xff0c;比如你的端口号…...

[ACTF2020 新生赛]Exec

【解题过程】 1.打开链接 得到一个能ping 的网站&#xff0c;可以推测这个可以在终端运行的网站。 2.解题思路 在执行的时候我们可以想到命令执行的“&#xff1b;”分号的作用&#xff1a;命令用分号分隔开来&#xff0c;表示它们是两个独立的命令&#xff0c;需要依次执行。…...

Git(三).git 文件夹详解

目录 一、初始化新仓库二、.git 目录2.1 hooks 文件夹2.2 info 文件夹2.3 logs 文件夹2.4 objects 文件夹【重要】2.5 refs 文件夹【重要】2.6 COMMIT_EDITMSG2.7 config2.8 description2.9 FETCH_HEAD2.10 HEAD【重要】2.11 index【重要】2.12 ORIG_HEAD2.13 packed-refs 官网…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...