go的实践

文章目录

  • 用goroutine来替代mq做异步的应用
    • 心跳
    • contenx的超时设置
    • 定时器
    • break label
    • 核心代码

用goroutine来替代mq做异步的应用

方法在创建ai任务接口中用协程的方式异步调用go s.handleResultPolling(ctx, algorithm, taskId, iAiHandle),来更新ai任务的状态

心跳

心跳机制是一种用于检测连接或任务是否仍处于活动状态的方法。在分布式系统或网络通信中,心跳机制可以用来监视节点和服务的可用性、性能和故障。心跳通常是通过定期发送小的数据包或信号来实现的,然后接收方会对这些信号进行响应,以表示它们仍然在线并正常运行。
在这段代码中,心跳机制用于监控AI任务的进行情况。每隔2秒,会将当前时间戳写入Redis缓存,作为心跳信号。这样,外部监控系统可以检查Redis缓存中的心跳信号来判断任务是否仍在进行。如果在一定时间内没有收到新的心跳信号,那么可以认为任务已经中止或出现故障。

contenx的超时设置

context没有默认的超时时间,如果要设置超时时间的话,记得调用

ctxTimeout, timeoutCancel := context.WithTimeout(ctx, time.Hour)
defer timeoutCancel() // 操作完成时立即释放资源

定时器

在这段代码中,time.NewTicker(time.Millisecond)创建的定时器最初每隔1毫秒触发一次,ticker.Reset(time.Second * 2)的作用是重置定时器(ticker)的时间间隔为2s,这样能每2s从通道中取到信息case <-ticker.C:

break label

breakFor是一个标签,它用于在嵌套循环或选择语句中提供更精确的控制。在这个例子中,breakFor标签用于跳出外层的for循环。 在Go语言中,break语句默认只跳出当前层次的循环或选择语句。在这个例子中,当ctxTimeout.Done()通道接收到一个值或者满足其他条件时,我们希望跳出整个for循环,而不仅仅是select语句。通过在for循环前添加breakFor标签,并在break`语句中指定该标签,我们可以实现这个功能。

核心代码

// handleCreateAsync 启动协程处理结果
func (s *aiHandle) handleCreateAsync(ctx context.Context, algorithm string, taskId string, data interface{}, iAiHandle IAiHandle) {
	// 上报神策
	properties := map[string]interface{}{
		"uid": util.GetCtx(ctx).User.WsId,
		"alg": algorithm,
	}
	sensorsdata.Track(gtrace.GetTraceID(ctx), "SeAlgCreate", properties, util.GetCtx(ctx).User.WsId != "", "")

	// 创建任务
	s.createDbSave(ctx, taskId, algorithm, data)

	// 任务数量+1
	s.handleCreateActive(ctx, algorithm, true)

	// 异步处理结果
	go s.handleResultPolling(ctx, algorithm, taskId, iAiHandle)
}
// handleCreateAsync 启动协程处理结果
func (s *aiHandle) handleCreateAsync(ctx context.Context, algorithm string, taskId string, data interface{}, iAiHandle IAiHandle) {
   // 上报神策
   properties := map[string]interface{}{
      "uid": util.GetCtx(ctx).User.WsId,
      "alg": algorithm,
   }
   sensorsdata.Track(gtrace.GetTraceID(ctx), "SeAlgCreate", properties, util.GetCtx(ctx).User.WsId != "", "")

   // 创建任务
   s.createDbSave(ctx, taskId, algorithm, data)

   // 任务数量+1
   s.handleCreateActive(ctx, algorithm, true)

   // 异步处理结果
   go s.handleResultPolling(ctx, algorithm, taskId, iAiHandle)
}

// handleResultPolling 轮询结果
func (s *aiHandle) handleResultPolling(ctx context.Context, algorithm, taskId string, iAiHandle IAiHandle) {
   // 60分钟超时
   // 1. 首先,设置一个60分钟的超时上下文,确保处理不会无限期地进行下去。
   ctxTimeout, timeoutCancel := context.WithTimeout(ctx, time.Hour)
   defer timeoutCancel() // 超时前调用这个,用来释放资源;不调用这个方法的话,会在超时时间释放资源

   // 2. 创建一个心跳goroutine,每隔2秒更新一次心跳缓存。这样可以在外部监控任务的进行情况。
   // 启动心跳,2秒一次
   go func(ctx context.Context, taskId string) {
      ticker := time.NewTicker(time.Millisecond)
      defer ticker.Stop()

      heartbeatKey := aiCache.GetAiTaskHeartBeat(taskId)
      for {
         select {
         case <-ctx.Done():
            return
         case <-ticker.C:
            ticker.Reset(time.Second * 2)
            if cache.RedisExists(ctx, heartbeatKey) == false {
               _ = cache.RedisSet(ctx, heartbeatKey, time.Now().Unix(), time.Hour*24)
            }
            _ = cache.RedisIncBy(ctx, heartbeatKey, 2)
         }
      }
   }(ctxTimeout, taskId)

   // 3. 初始化任务结果的状态和数据变量。
   // 任务结果
   taskEnd := false
   taskStatus := consts.TaskStatusProcessing
   taskMsg := ""
   var taskData any

   // 4. 设置一个定时器,每隔3秒执行一次轮询查询结果。
   // 每3秒重试一次
   step := time.NewTimer(time.Millisecond)
   defer step.Stop()

   // 查询失败时,重试5次
   retry := 1

   //5. 使用`breakFor`标签和`select`语句进行轮询操作,当超时或查询到结果时跳出循环。
   //- 调用`iAiHandle.ResultHandle`方法查询任务结果。
   //- 如果查询失败,重试5次。
   //- 如果任务状态不是处理中或等待中,则更新任务状态和数据,设置`taskEnd`为`true`,跳出循环。

   // 轮询结果
breakFor:
   for {
      select {
      case <-ctxTimeout.Done():
         break breakFor
      case <-step.C:
         step.Reset(time.Second * 3)
         // 查结果
         taskResult, err := iAiHandle.ResultHandle(ctx, &v1.ResultReq{
            Algorithm: algorithm,
            TaskId:    taskId,
         })
         taskData = taskResult
         if err != nil {
            if retry > 5 {
               taskStatus = consts.TaskStatusServerFail
               taskMsg = "handle result err retry than 5 times"
               break breakFor
            }
            retry++
         } else {
            // 状态不一致则返回
            if taskResult != nil && taskResult.Status != consts.TaskStatusProcessing && taskResult.Status != consts.TaskStatusWaiting {
               taskStatus = taskResult.Status
               taskMsg = taskResult.Reason
               taskEnd = true
               break breakFor
            }
         }
      }
   }

   // 程序处理超时
   if taskEnd == false {
      taskStatus = consts.TaskStatusServerOutTime
      taskMsg = "handle result than 60 minutes"
   }
   // 7. 更新任务计数器。
   // 任务数量-1
   s.handleCreateActive(ctx, algorithm, false)

   // 8. 保存任务结果到数据库。
   // 更数任务
   s.resultDbSave(ctx, taskId, taskStatus, taskMsg, taskData)

}

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

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

相关文章

OKCC搭建配置什么样的服务器合适

OKCC呼叫中心系统是一种采用软硬件结合的架构方式、及分布式的IP技术&#xff0c;从多角度为企业提供整合的一体化解决方案。因此&#xff0c;搭建OKCC呼叫中心系统所使用的服务器应该满足以下几点要求&#xff1a; 稳定性&#xff1a;服务器需要具有较高的稳定性和可靠性&…

MinIO + Prometheus + Grafana docker部署

文章目录 说明MinIO简介MinIO 容器化部署Prometheus服务地址配置方法一&#xff1a;先部署后修改方法二&#xff1a;部署时修改compose文件&#xff08;未验证&#xff09; MinIO Access Key配置Prometheus 容器化部署MinIO 生成抓取配置修改Prometheus配置文件Grafana 容器化部…

iframe和 blob实现JS,CSS,HTML直接当前页预览

先贴效果图&#xff1a; <template><div><div class"aaa"></div><div class"btn-run" click"tres">运行</div></div></template><script>import { mapState } from vuex;export default …

在线编辑器 CodeMirror

如何优雅的在网页显示代码 如果开发在线编辑器 引入资源&#xff1a; <link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.60.0/codemirror.min.css"><script src"https://cdnjs.cloudflare.com/ajax/libs/c…

【网安小白成长之路】8.sql注入操作1

&#x1f42e;博主syst1m 带你 acquire knowledge&#xff01; ✨博客首页——syst1m的博客&#x1f498; &#x1f51e; 《网安小白成长之路(我要变成大佬&#x1f60e;&#xff01;&#xff01;)》真实小白学习历程&#xff0c;手把手带你一起从入门到入狱&#x1f6ad; &…

店前台安装水离子雾化壁炉前和装后对比

当酒店前台装上水离子雾化壁炉后&#xff0c;整体氛围和客户体验都会发生显著的变化&#xff1a; 装前&#xff1a; 普通的前台氛围&#xff1a;前台可能显得比较普通和传统&#xff0c;可能缺乏独特的装饰元素或视觉焦点。 视觉上缺乏吸引力&#xff1a;前台空间可能比较朴…

现代商业中首席人工智能官(CAIO)的角色与影响

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

万字总结!Docker简介及底层关键技术剖析

本文首发在个人博客上&#xff1a;万字总结&#xff01;Docker简介及底层关键技术剖析 Docker 简介 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从 Apache2.0 协议开源。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#x…

PVE grub resue错误修复 lvmid BUG

服务器断电后启动不起来&#xff0c;显示grub resue 找了半天没有找到修复方法。看官方文档有一处Recovering from grub “disk not found” error when booting from LVM 极为类似。https://pve.proxmox.com/wiki/Recover_From_Grub_Failure 下面是处理过程。 使用PVE 6.4启…

使用示例解释.NET中的Mocking是什么?

让我们踏上探索.NET软件开发中Mocking概念的旅程&#xff0c;让我们深入了解Mocking是多么简单易懂、易于访问。请与我一起穿越这个主题&#xff0c;我将涵盖以下内容&#xff1a; 理解Mocking&#xff1a;为何它对于构建强大的测试策略至关重要。探索一些最常见的Mocking库&a…

python教学入门:字典和集合

字典&#xff08;Dictionary&#xff09;&#xff1a; 定义&#xff1a; 字典是 Python 中的一种数据结构&#xff0c;用于存储键值对&#xff08;key-value pairs&#xff09;。字典使用花括号 {} 定义&#xff0c;键值对之间用冒号 : 分隔&#xff0c;每对键值对之间用逗号 …

SQL-Oracle 获取最大值,第二大,第三大,第 N 大值

目录 1、原始数据2、获取最大值记录3、获取第二大值记录4、获取第三大值记录 1、原始数据 select * from test_2024_04_15_001 order by 销量 desc,渠道2、获取最大值记录 select 渠道,销量 from ( select a.渠道, a.销量 from test_2024_04_15_001 a order by a.销量 desc,…

AI边坡监测识别摄像机

AI边坡监测识别摄像机是一种利用人工智能技术进行边坡监测的智能设备&#xff0c;其作用是及时监测边坡变化并识别潜在的滑坡、崩塌等危险情况&#xff0c;以提供及时预警和采取必要的安全措施。这种摄像机通过高清摄像头实时捕捉边坡的图像&#xff0c;并利用AI算法对边坡的形…

实验室三大常用仪器2---函数信号发生器的基本使用方法(笔记)

目录 函数信号发生器的基本使用方法 如何连接函数信号发生器和示波器 实验室三大常用仪器1---示波器的基本使用方法&#xff08;笔记&#xff09;-CSDN博客 实验室三大常用仪器3---交流毫伏表的使用方法&#xff08;笔记&#xff09;-CSDN博客 示波器是用来显示和测量信号的…

Java | Leetcode Java题解之第35题搜索插入位置

题目&#xff1a; 题解&#xff1a; class Solution {public int searchInsert(int[] nums, int target) {int n nums.length;int left 0, right n - 1, ans n;while (left < right) {int mid ((right - left) >> 1) left;if (target < nums[mid]) {ans mi…

阿里云图片处理之 图片样式(裁剪)

文档 : https://help.aliyun.com/zh/oss/user-guide/image-styles?spma2c4g.11186623.0.0.5961fe7aq3111v 需求 : 由于客户端界面展示的图片较多, 而且每个图片都过大并且高清高分辨率的, 导致打开页面时图片加载很慢, 而且是缩略图, 对图片清晰度要求不是那么得高, 因此可以…

ASP.NET MVC企业级程序设计 (商品管理:小计,总计,删除,排序)

目录 效果图 实现过程 1创建数据库 2创建项目文件 3创建控制器&#xff0c;右键添加&#xff0c;控制器 ​编辑 注意这里要写Home​编辑 创建成功 数据模型创建过程之前作品有具体过程​编辑 4创建DAL 5创建BLL 6创建视图&#xff0c;右键添加视图 ​编辑 7HomeCont…

【问题处理】银河麒麟操作系统实例分享,adb读写缓慢问题分析

1.问题环境 处理器&#xff1a; HUAWEI Kunpeng 920 5251K 内存&#xff1a; 512 GiB 整机类型/架构&#xff1a; TaiShan 200K (Model 2280K) BIOS版本&#xff1a; Byosoft Corp. 1.81.K 内核版本 4.19.90-23.15.v2101.ky10.aarch64 第三方应用 数据库 2.问题…

Spring Security详细学习第一篇

Spring Security 前言Spring Security入门编辑Spring Security底层原理UserDetailsService接口PasswordEncoder接口 认证登录校验密码加密存储退出登录 前言 本文是作者学习三更老师的Spring Security课程所记录的学习心得和笔记知识&#xff0c;希望能帮助到大家 Spring Sec…

buuctf——[ZJCTF 2019]NiZhuanSiWei

buuctf——[ZJCTF 2019]NiZhuanSiWei 1.绕过file_get_contents()函数 file_get_contents函数介绍 定义和用法 file_get_contents() 把整个文件读入一个字符串中。 该函数是用于把文件的内容读入到一个字符串中的首选方法。如果服务器操作系统支持&#xff0c;还会使用内存映射…
最新文章