近期手上的一个基于Function Grap(类AWS的Lambda)小项目的改造引发的思考

函数式Function是云计算里最近几年流行起来的新的架构和模式,因为它不依赖云主机,非常轻量,按需使用,甚至是免费使用,特别适合哪种数据同步,数据转发,本身不需要保存数据的业务场景,或者通过一个输入转换或者变化,处理以后流转到下一个输出。

我们刚好有这样的业务,云云对接,把一个储能云的数据,经过接口查询以后,转换后保存到我们的私有云平台上(内部是微软提供的IoT平台底座)。

但是在实际开发中发现了有两个痛点,
 触发方式,云厂商一般会提供2个方式,
1.基于事件的调用,比如Python语言的固定式的函数,比如

def handler(event, context)

,函数名和内存占用,网络设置等配置,这里有一个重要的设置就是触发器,

一般最常用的是定时触发器:

当你编写好以后,在云平台上直接点击运行测试,云平台会调用你的这个handler,你也可以通过参数event, context 获取运行时的一些数据。如果是简单任务,只需要在这里调用你的业务代码就开发完成。

一切都很自然,这里的定时器,相当于linux里的cronjob, 最后运行的python ss.py 这样的方式会导致每次启动都会把代码重新执行一遍,但是如果你的业务要求严格的话,希望这个程序运行了以后一直不退出,在程序内部运行Schedule,这样的好处会节省调用方的资源,比如代码需要访问MQ,每隔3分钟程序重新执行的时候,会频繁得创建TCP连接。会给MQ broker的连接创造一定的压力,我刚好遇到了对方投诉我们占用了他们的连接资源。所以我需要改造程序,让程序一直不退出的方式,复用创建好的连接。一共经历了3次优化

  1. 修改代码,创建一个全局的Connection对象,然后在handler里直接写while True的方式执行,发现云平台给的handler函数,有个限制,如果超时没有返回,平台强制终止程序,可以在日志里查看到,程序超时被终止。这条路走不通
  2. 不改架构使用异步,handler里启动一个线程,在线程里while True,后来发现执行一段时间后,效果并不好。
通过Schedule包,顺便说一下,Python竟然没有一个特别强大的定时器,非常不好用,想这样, import schedule
schedule.every(3).minutes.do(job1)需要设置好了以后,还需要 if __name __ =="__main__":         schedule.run_pending()为了防止程序退出还有在主线程里写上while True: time.sleep(5)
 
或者类似这样的代码
import time
import threadingdef background_task():print("后台任务开始")time.sleep(5)  # 模拟长时间任务print("后台任务完成")def handler(event, context):print("收到请求")def delayed_run():time.sleep(0.1)background_task()thread = threading.Thread(target=delayed_run)thread.start()# 主线程故意睡一会儿,防止函数提前退出time.sleep(6)return {"statusCode": 200, "body": "已尝试启动后台任务"}
这样恶心的代码,非常的不优雅。

3. 改动架构,使用彻底异步

  1. 使用redis的发布订阅模式(或者其他MQ),把启动和执行分开。在执行同步的代码里,handler里把连接建立好,就等待redis的消息通知,代码如下:
  2. def handler(event, context):
  3.     localtime = time.asctime(time.localtime(time.time()))
  4.     print(f"execution at {localtime}.")
  5.     startConn()
  6.     start_redis_listener()
  7.     print("??",client)
  8.     return {"statusCode": 200, "isBase64Encoded": False, "headers": {"Content-Type": "application/json;charset=UTF-8"},
  9.             "body": "sucess"}

  10. 这样非常优雅,如下:
  11. def sync_data():
  12.     print("开始执行耗时的数据同步任务...")    
  13.     print(client)  
  14.     try:
  15.         while True:
  16.             time.sleep(5)
  17.             print("开始处理站点列表")
  18.             for conf in configLs:
  19.                 print(f"开始处理站点: {conf.station_name} 数据")
  20.                 site = AccessSite(conf)
  21.                 site.publish_mqtt()
  22.                 # msg = msg + f"{conf.station_name}"
  23.                 print("成功处理站点数据至能源平台!")
  24.     except Exception as e:
  25.         print("同步出错:", str(e))
  26. # Redis 订阅客户端
  27. def start_redis_listener():
  28.    
  29.     pubsub = redisClient.pubsub()
  30.     pubsub.subscribe(["stored_energy_sync_channel"])
  31.     print("等待 Redis 消息...")
  32.     for message in pubsub.listen():
  33.         if message['type'] == 'message':
  34.             print(f"收到消息: {message['data'].decode()}")
  35.             if message['data'].decode() == "start_sync":
  36.                 sync_data()

至于程序何时启动,只需要在另外一个FG里,通过调用redis的pub接口,把这个sync_data()给启动。

非常的完美,容易维护。而第二个版本,使用线程和使用定时器都无法取得满意的效果。

注意这里的redis还可以替换成Kafka, RocketMQ,或者其他通知SMN, SQS。
2. 还有一个方式是基于http或者https的方式启动任务,方式大同小异,都是一次执行完成以后,需要再次触发才能继续执行。如下图:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是 SQL 注入?如何防范?

什么是 SQL 注入?如何防范? 1. SQL 注入概述 1.1 基本定义 SQL 注入(SQL Injection)是一种通过将恶意SQL 语句插入到应用程序的输入参数中,从而欺骗服务器执行非预期SQL命令的攻击技术。攻击者可以利用此漏洞绕过认证、窃取数据甚至破坏数据库。 关键结论:SQL 注入是O…

高德地图应用OceanBase单元化构建下一代在线地图服务

IEEE International Conference on Data Engineering (ICDE) 是数据库和数据工程领域的顶级学术会议之一(与SIGMOD、VLDB并成为数据库三大顶会),自1984年首次举办以来,每年举办一次。ICDE涵盖广泛的主题,包括数据库系统…

Vue3中Element-Plus中el-input及el-select 边框样式

如果不需要显示下边框&#xff0c;纯无边框直接将 【border-bottom: 1px solid #C0C4CC; 】注掉或去掉即可。 正常引用组件使用即可&#xff0c;无须自定义样式&#xff0c;最终效果CSS样式。 <style scoped> /* 输入框的样式 */ :deep(.el-input__wrapper) { box-sha…

如何做好一份技术文档:从信息孤岛到知识图谱的进阶之路

如何做好一份技术文档&#xff1a;从信息孤岛到知识图谱的进阶之路 在软件开发的漫长征程中&#xff0c;技术文档如同隐藏在代码丛林中的路标&#xff0c;不仅指引着开发团队的前行方向&#xff0c;更在产品迭代的岁月里构筑起知识传承的桥梁。一份优质的技术文档&#xff0c;既…

Docker Compose使用自定义用户名密码启动Redis

通常我们使用下面的命令来启动 redis 容器&#xff0c;此时连接 Redis 的时候是不需要用户认证的 sudo docker run -d --name my-redis -p 6379:6379 redis此时我们可以使用 redis-server --requirepass "mypassword" 来指定默认用户&#xff08;default&#xff09…

1.什么是node.js、npm、vue

一、Node.js 是什么&#xff1f; &#x1f63a; 定义&#xff1a; Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境&#xff0c;让你可以在浏览器之外运行 JavaScript 代码&#xff0c;主要用于服务端开发。 &#x1f63a;从计算机底层说&#xff1a;什么是“运…

如何在 Vue.js 中集成 Three.js —— 创建一个旋转的 3D 立方体

在这篇文章中&#xff0c;我将向大家展示如何将 Three.js 与 Vue.js 结合&#xff0c;创建一个简单的 3D 场景&#xff0c;并展示一个旋转的立方体。通过这个简单的示例&#xff0c;你将学习到如何在 Vue 项目中集成 Three.js&#xff0c;以及如何创建动态的 3D 内容。 1. 安装…

DeepSeek‑R1-0528 重磅升级:蚂蚁百宝箱免费、无限量调用

DeepSeek‑R1-0528 重磅升级&#xff1a;蚂蚁百宝箱免费、无限量调用 端午假期前一天&#xff0c;DeepSeek‑R1 更新到了 0528 版本&#xff01; 官方说明&#xff1a;0528 版本在深度思考与推理能力方面显著增强——在数学、编程与通用逻辑等多项基准测评中&#xff0c;表现已…

RS232转Profinet网关在检漏仪与西门子PLC里的应用

RS232转Profinet网关在检漏仪与西门子PLC里的应用 在工业自动化和控制领域&#xff0c;设备间的高效通信至关重要。RS232转Profinet网关作为一种关键的转换工具&#xff0c;能够将传统的RS232接口设备接入现代化的Profinet网络&#xff0c;从而实现数据的无缝传输和设备的远程…

jenkins-jenkins简介

一、简介 jenkins是一个可扩展的持续集成引擎。持续集成&#xff0c;也就是通常所说的CI&#xff08;Continues Integration&#xff09;&#xff0c;可以说是现代软件技术开发的基础。持续集成是一种软件开发实践&#xff0c; 即团队开发成员经常集成他们的工作&#xff0c;通…

vue发版html 生成打包到docker镜像进行发版

将Vue项目打包成Docker镜像部署主要分为以下几个步骤&#xff1a; 1. Vue项目打包‌ 执行npm run build生成dist文件夹&#xff0c;包含静态资源文件 注意检查index.html中资源引用路径是否正确&#xff08;避免绝对路径问题&#xff09; 2. 编写Dockerfile Copy Code FROM…

扫地机器人苦寻新引擎,大疆们却已攻入腹地

原创 科技新知 前沿科技组 作者丨江篱 编辑丨樱木、九黎 竞争激烈的扫地机器人赛道&#xff0c;迎来了新玩家。 据近日相关报道&#xff0c;大疆扫地机器人产品已开始量产&#xff0c;预计将于6月份发布。消息称大疆研发扫地机器人已超过四年&#xff0c;即将上市的产品是扫…

【C++】22. 红黑树封装实现Mymap和Myset

上一章节我们实现了红黑树&#xff0c;这一章节我们就用红黑树封装来实现一个我们自己的map和set 1. 源码及框架分析 SGI-STL 3.0版本的源代码中&#xff0c;map和set的实现主要分布在若干头文件中&#xff0c;这些头文件构成了这两个容器的完整实现架构&#xff1a; 核心头文…

02_redis分布式锁原理

文章目录 一、redis如何实现分布式锁1. 使用 SETNX 命令2. 设置过期时间3. 释放锁4. 注意事项5. 示例代码二、Java中分布式锁如何设置超时时间1. Redis分布式锁2. 基于Zookeeper的分布式锁3. 基于数据库的分布式锁注意事项一、redis如何实现分布式锁 Redis 实现分布式锁是一种…

酷派Cool20/20S/30/40手机安装Play商店-谷歌三件套-GMS方法

酷派Cool系列主打低端市场&#xff0c;系统无任何GMS程序&#xff0c;也不支持直接开启或者安装谷歌服务等功能&#xff0c;对于国内部分经常使用谷歌服务商店的小伙伴非常不友好。涉及机型有酷派Cool20/Cool20S /30/40/50/60等旗下多个设备。好在这些机型运行的系统都是安卓11…

技术为器,服务为本:AI时代的客服价值重构

在智能化浪潮中&#xff0c;大语言模型的出现为客户服务行业注入了全新动能。然而技术创新的价值不在于技术本身&#xff0c;而在于其赋能服务的深度与广度。AI对于我们来说&#xff0c;如同发动机之于汽车&#xff0c;重要的不是引擎参数&#xff0c;而是整车带给用户的驾驶体…

技术创新如何赋能音视频直播行业?

在全球音视频直播行业的快速发展中&#xff0c;技术的持续创新始终是推动行业进步的核心动力。作为大牛直播SDK的开发者&#xff0c;我很荣幸能分享我们公司如何从产品的维度出发&#xff0c;精准把握市场需求&#xff0c;并不断推动产品的发展&#xff0c;以满足不断变化的行业…

Linux线程池(下)(34)

文章目录 前言一、v3版本二、单例模式概念特点简单实现 三、其余问题STL线程安全问题智能指针线程安全问题其他锁的概念 总结 前言 加油&#xff01;&#xff01;&#xff01; 一、v3版本 「优化版」&#xff1a;从任务队列入手&#xff0c;引入 「生产者消费者模型」&#xff…

Netty 实战篇:Netty RPC 框架整合 Spring Boot,迈向工程化

本文将基于前面构建的 RPC 能力&#xff0c;尝试将其与 Spring Boot 整合&#xff0c;借助注解、自动扫描、依赖注入等机制&#xff0c;打造“开箱即用”的 Netty RPC 框架&#xff0c;提升开发效率与工程规范。 一、为什么要整合 Spring Boot&#xff1f; 手动 new 实例、写注…

Axure中继器学习笔记

一、中继器概述 中继器(Axure Repeater)是Axure中的高级组件&#xff0c;功能类似于数据集成器&#xff0c;主要用于&#xff1a; 数据存储与管理 数据的增删改查操作 数据的分页与展示控制 二、中继器基本使用流程 数据存储&#xff1a;将数据储存在中继器组件中 数据展…