我如何处理每个请求的条目 - 使用 Go!
在我们开始之前,先介绍一下我是谁以及为什么它在这种情况下很重要。我是笔记本制造公司的软件开发人员,过去两年在这里工作。在我现在所在的团队中,我是唯一的开发人员,负责使用 Go 和 Grafana 创建、监控和维护数据管道、自动化以及监控系统。
我还要补充一点,前一年我是实习生。而且我是自学的。
好吧,但是为什么这很重要呢?
嗯,当我遇到自己无法解决的障碍或问题时,我没有高级开发人员,也没有任何形式的内部指导可以指导我,这就是我写作的主要原因。我认为这是一件有趣的事情并且想要分享。它不会是一个令人惊叹的软件,一个突破或类似的东西,但它提醒我们从头开始构建东西是可能的。您不需要成为百万分之一的 10 倍开发人员或类似的人。
P.S:顺便说一句,我使用 neovim。
一百万行
这个数字可能看起来有些夸张或类似的东西,尽管我希望如此,但事实并非如此。看,在制造环境中工作时,有时我们不会考虑需要多少个项目,以及当您必须跟踪每个组件的许多制造队列的每个点时它会生成多少数据。
无论是一个小螺丝,还是上一代 CPU,都必须被跟踪,带有时间戳!
所以,是的,生成的数据量是正确的,而这只是开始。以下是使问题变得很酷的其他酷点(在我看来):
- 该数据的来源没有经过压缩或类似的处理,因此天气好的时候平均请求时间接近 2 到 3 分钟。如果源代码滞后,它可能会超过 5 分钟(这是一个比我更旧的 java 系统。)。
- 关于格式,我可以选择处理 XML 响应或 CSV 响应,当然我选择了 CSV 路线。我不是受虐狂。
- 并且需要选择数据获取的间隔,至少一小时(不,我不知道为什么,是的,我尝试过较小的间隔)。
- 源没有延迟加载或缓存系统,因此两个相同的请求将生成相同的响应,但时间不同。
- 最后,让事情变得更有趣的是,它是 Microsoft 的产品,称为 SQL Server Reporting Services,但也有一些晦涩的警告。哦,而且我需要使用的数据库是 MSSQL,这很痛苦。
这就是整个上下文,现在有趣的部分开始。
第一次迭代——DMP
我喜欢使用软件的方式非常简单。让它变得丑陋且几乎不起作用 ->保持丑陋并改进功能 ->仍然丑陋,但优化得更好 ->漂亮、优化且工作 ->然后你的经理说你所做的工作太好了,源无法处理它,导致中断。卧槽。
无论如何,DMP 代表 Dumb Mode Protocol,只要让它以最愚蠢的方式工作即可,这意味着勉强可以工作。
所以,对于第一轮,我的目标很简单,进行身份验证,发出请求,解析数据,发送到数据库。很简单,对吧?而且,在纸面上,它是,直到我发现我必须使用的身份验证和授权方法是 ntlmssp,这是一种我不知道存在的质询响应身份验证方法。事实上,我必须进入旧版 .NET 4 代码才能找到它。我没学过C#。
在浏览了比我年长的遗留代码之后,我在尝试理解它时遇到了困难,因为出于某种原因,编写它的人认为将其隐藏到 5 层抽象、构造函数和 OOP 中是一个好主意。不有趣,令人羞愧的经历。然后我成功了。一小时后,我的用户被屏蔽,因为显然该来源有速率限制。但没有缓存或延迟加载。
好吧,在这一切之后,我只需要传递查询参数并获取数据,不再需要源的复杂性。好吧,我们来查一下查询参数的文档。
...
此时,考虑到所有因素,您可能猜对了。文档?这是只有硅谷才有的异国美食吗?
不管怎样,在绞尽脑汁之后,我决定检查一下这个 SQL Server Reporting Services 的站点/界面,令我高兴的是,然后是仇恨,它有一种方法来了解过滤器及其值。
只知道页面中的(“全部”)过滤器,例如选择所有生产线,只是选中所有框的抽象。好吧,让我们复制过滤器并将其放入查询字符串中,对其进行编码,然后开心吧!
成功了!或者说我是这么想的。
还记得我说过我的用户被屏蔽了吗?好吧,看起来拥有执行此类任务的管理员权限,并由 C-Suite 授权执行此操作(事实上,这是他们要求的),但不足以允许我执行多个请求。我的用户被屏蔽了,但是,对于我的经理来说,这就像说“什么也没发生”。幸运的是,我很快就解封了。
与此同时,我决定按照我处理该项目其余部分的方式进行工作。此时我已经有了一个样本,它符合帖子的标题。看到这七位数字让我怀疑自己是否能够做到,因为我对这个数据量的经验为零。
为了将我的想法付诸实践,我希望进入 exlidraw 并设计出我想做的事情。我知道工作池的概念,但之前没有实现过。因此,我阅读了相关内容,看到了一些实现,并询问了一位对我帮助很大的朋友。他是我没有的前辈。
用伪代码写出来后,我心里想:
“哇,这非常简洁,所有这些通道和 goroutine 肯定不会产生内存泄漏,对吧?”
好吧,可能不是那些确切的词,但大致意思是这样的。在完成第一次迭代、设法执行请求(不会被阻止)并将其加载到内存中之后,我应用了工作池概念。
然后我就遇到了 BSOD。有趣的是,就在 CrowdStrike 罢工的同一天,我当然不认为我造成了工厂的重大停电。
另外,是的,我必须使用 Windows 来工作,但不用担心!我使用 WSL2。
在检查了我的第一次堆栈溢出的大量堆栈跟踪后,我发现了这个错误。在将数据发送到消费者通道时,我没有考虑到某些数据可能会出错,主要是由于违反了主键,或者仅仅是因为,也许,我没有正确处理错误。
经验教训,使用错误通道来避免重大问题。并处理您的错误,无论是通过简单的字符串检查(丑陋,但有效),或者只是顶级记录它,然后高兴。由于我遇到的错误并不严重,所以我可以继续。
第二次迭代。内存泄漏。
这一步产生的内存泄漏量让我以为我在做 C。但这只是主要的技能问题。
不管怎样,你可能会想:
“你是如何在如此简单的过程中造成内存泄漏的?”
很简单,我正在学习和尝试。
这一步中的主要问题是我天真地没有确保数据被正确插入,并且我得到的主键违规量违反了我的记忆。这是我知道如何解决的问题,让我们缓存数据吧!
等等,考虑到每一行都是唯一的,如何为每一行创建一个唯一标识符?
现在,这是很多人会嘲笑我的部分,因为,公平地说,这是最让我崩溃的部分。我只是简单地加入当前行的信息并将其解析为哈希函数,该哈希就成为我在映射中的键。
“为什么不使用 Redis?” - 你可能会问自己。
很简单,官僚主义。这不是一家小公司。事实上,你们中的许多人可能正在使用他们制造的笔记本电脑。请求一个 Redis 实例这个简单的行为至少需要三个工作日、四次会议、对官僚之神的牺牲,以及一份解释原因和方式的完整文档。
所以,是的,让我们使用一个简单的哈希图并在第一次运行之前对其进行预初始化。它会增加整体加载时间,但会比请求更快。
通过这样做,整个过程得到了改善,就像有了一个新电机一样,memleaks 停止了,批次不会每次都失败,错误和断开连接的数量也减少了,非常好,对吧?对吗?
现在,您知道有些事情变得混乱了。
第三次迭代。生活本来可以很美好。
我没有考虑到的一点是,通过批量插入,可以验证数据。这是流程的简单表示。
获取数据->检查hashmap中是否存在数据的hash ->批量&插入
这有什么问题吗?那么,如果我的批次中的单个插入失败,会发生什么情况,它会在没有条目的情况下重试吗?如果是这样,我可以重试多少次而不会使系统混乱并失去工作池实现的优势?
只有一种方法可以找出答案!我们来检查一下。
我要补充的一点是,该源返回了超过 25 列,因此我必须小心每批插入的数据量,以免超过 2100 个参数,这是 MSSQL 的限制。
此时,我已经在 Docker 容器中运行一些东西,该容器模仿资源有限的生产空间。为了添加上下文,该进程使用 1GB RAM 和大约 0.5CPU 运行。我本可以分配更多的资源,但这只是强行逼我出路。
通过在容器内运行这个新的迭代,添加一些时间戳并将其记录到文件中以供以后分析。我发现由于重试次数增加了大约 5 分钟。这是行不通的,删除“脏”条目不是一个选项。
第四次迭代。生活是美好的。
为了解决这个问题,我增加了工人的数量。我使用了大约 50 名工作人员,并且由于 ThePrimagen 顶级货架上的不和谐用户的随机猜测,我将其增加到 1000 名工作人员,并确保每个工作人员都验证交易中的每个条目。万一交易失败,我直接回滚。
通过这样做,我能够解决核心问题并总体上提高该过程的整体速度。现在是时候将其放入产品中并对其进行监控了,因为,你知道,产品妖精可能会弄乱你的软件。 (它们也被称为技能问题,但这个名称是禁止的。)
知道减少该系统的获取间隔,要求使其接近实时(这意味着足够快,让他们不会注意到延迟),我创建了一个新容器,这一次具有更强健的功能检查是否能够承受负载,并将间隔设置为 3 分钟。考虑到平均获取时间,这意味着我可能会有一些重叠,但我真的很想看看会发生什么。
我让它运行了一夜,记录结果以便稍后查看,令我惊讶的是,在工作日结束之前,我接到了经理的电话。请注意,他不是技术人员或类似的人。
“嘿,‘我们’部署了一些与[我无法透露的系统名称]交互的东西吗?”
“是的,我按照要求实时部署了数据获取系统。为什么?”
“你能,嗯,停下来吗?它导致了停电,我们无法在这里工作。”_
这,gadies and lentleman,完全是另一个级别的破坏性刺激。毫不夸张地说,我让 20 多条生产线停止了一分钟左右。无论如何,我停止了系统,一切都恢复正常。
第二天,我被要求将读取之间的间隔从 3 分钟增加到 30 分钟,好吧,我想没问题。我不会说谎,我有点难过,因为我无法看到它以最大速度运行,但是嘿,至少我让它工作了。
使用这个新系统,使用该数据的报告的平均更新时间减少到 8~10 秒,这导致经理以相同的方式请求更多相同来源的报告。良好的工作会得到更多工作的回报!
注意事项
这是一次有趣的经历,主要是因为它让我真正意识到 Go 的强大之处。使用比谷歌浏览器更少的内存,比微软应用程序更少的存储空间,比 Windows 计算器更少的 CPU 功率,我能够改进一个旧的进程,这个进程实际上是暴力强制通过的(它在插入之前实际上检查了数据库中的每一行。我不知道)不知道前一个人怎么认为这是一个好主意。)。真的很有趣。
无论如何,请随意分享您在整个过程中的想法,您会如何处理以及您会采取哪些不同的做法。由于我没有开发同事,我想了解更多对此的看法。
以上是我如何处理每个请求的条目 - 使用 Go!的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Golang在性能和可扩展性方面优于Python。1)Golang的编译型特性和高效并发模型使其在高并发场景下表现出色。2)Python作为解释型语言,执行速度较慢,但通过工具如Cython可优化性能。

Golang在并发性上优于C ,而C 在原始速度上优于Golang。1)Golang通过goroutine和channel实现高效并发,适合处理大量并发任务。2)C 通过编译器优化和标准库,提供接近硬件的高性能,适合需要极致优化的应用。

goisidealforbeginnersandsubableforforcloudnetworkservicesduetoitssimplicity,效率和concurrencyFeatures.1)installgromtheofficialwebsitealwebsiteandverifywith'.2)

Golang适合快速开发和并发场景,C 适用于需要极致性能和低级控制的场景。1)Golang通过垃圾回收和并发机制提升性能,适合高并发Web服务开发。2)C 通过手动内存管理和编译器优化达到极致性能,适用于嵌入式系统开发。

Golang和Python各有优势:Golang适合高性能和并发编程,Python适用于数据科学和Web开发。 Golang以其并发模型和高效性能着称,Python则以简洁语法和丰富库生态系统着称。

Golang和C 在性能上的差异主要体现在内存管理、编译优化和运行时效率等方面。1)Golang的垃圾回收机制方便但可能影响性能,2)C 的手动内存管理和编译器优化在递归计算中表现更为高效。

Golang和C 在性能竞赛中的表现各有优势:1)Golang适合高并发和快速开发,2)C 提供更高性能和细粒度控制。选择应基于项目需求和团队技术栈。

Golangisidealforbuildingscalablesystemsduetoitsefficiencyandconcurrency,whilePythonexcelsinquickscriptinganddataanalysisduetoitssimplicityandvastecosystem.Golang'sdesignencouragesclean,readablecodeanditsgoroutinesenableefficientconcurrentoperations,t
