热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

函数计算助力语雀构建稳定且安全的业务架构

简介: 语雀是一个专业的云端知识库,用于团队的文档协作。现在已是阿里员工进行文档编写和知识沉淀的标配,并于2018年开始对外提供服务。客户介绍语雀是一个专业的云端知识库,用于团队的

简介: 语雀是一个专业的云端知识库,用于团队的文档协作。现在已是阿里员工进行文档编写和知识沉淀的标配,并于 2018 年开始对外提供服务。


客户介绍

语雀是一个专业的云端知识库,用于团队的文档协作。现在已是阿里员工进行文档编写和知识沉淀的标配,并于 2018 年开始对外提供服务。


客户痛点

语雀是一个复杂的 Web 应用,也是一个典型的数据密集型应用(Data-Intensive Application),背后依赖了大量的数据库等云服务。语雀服务端是 Node.js 技术栈。当提到 Node 的时候,可能立刻就会有几个词浮现在我们脑海之中:单线程(single-threaded)、非阻塞(non-blocking)、异步(asynchronously programming),这些特性一方面非常的适合于构建可扩展的网络应用,用来实现 Web 服务这类 I/O 密集型的应用,另一方面它也是大家一直对 Node 诟病的地方,对 CPU 密集型的场景不够友好,一旦有任何阻塞进程的方法被执行,整个进程就被阻塞。

像语雀这样用 Node 实现整个服务端逻辑的应用,很难保证不会出现一些场景可能会消耗大量 CPU 甚至是死循环阻塞进程的,以 markdown 转换举例,由于用户的输入无法穷举,总有各种可能让转换代码进入到一个低效甚至是死循环的场景之中。在 Node 刚出世的年代,很难给这些问题找到完美的解决办法,而即便是 Java 等基于线程并发模型的语言,在遇到这样的场景也很头痛,毕竟 CPU 对于 Web 应用来说都是非常重要的资源。而随着基础设置越来越完善,当函数计算出现时,Node 最大的短板看起来有了一个比较完美的解决方案。


解决方案

“把函数计算引入之后,我们可以将那些 CPU 密集型、存在不稳定因素的操作统统放到函数计算服务中去执行,而我们的主服务再次回归到了 I/O 密集型应用模型,又可以愉快的享受 Node 给我们带来的高效研发福利了!”语雀产品技术负责人不四表示。

“以语雀中遇到的一个实际场景来举例,用户传入了一些 HTML 或者 Markdown 格式的文档内容,我们需要将其转换成为语雀自己的文档格式。在绝大部分情况下,解析用户输入的内容都很快,然而依然存在某些无法预料到的场景会触发解析器的 bug 而导致死循环的出现,甚至我们不太敢升级 Markdown 解析库和相关插件以免引入更多的问题。但是随着函数计算的引入,我们将这个消耗 CPU 的转换逻辑放到函数计算上,语雀的主服务稳定性不会再被影响。”
yq1.png

除了帮助 Web 系统分担一些 CPU 密集型操作以外,函数计算还能做什么呢?

语雀支持使用各种代码形式来绘图,包括 Plantuml、公式、Mermaid,还有一些将文档导出成 PDF、图片等功能。这些场景有两个特点:
1、他们依赖于一些复杂的应用软件,例如 Puppeteer、Graphviz 等;
2、可能需要执行用户输入的内容;

支持这类场景看似简单,通过 process.exec 子进程调用一下就搞定了。但是当我们想把它做成一个稳定的对外服务时,问题就出现了。这些复杂的应用软件可能从设计上并没有考虑要长期运行,长期运行时的内存占用、稳定性可能会有一些问题,同时在被大并发调用时,对 CPU 的压力非常大。再加上有些场景需要运行用户输入的代码,攻击者通过构建恶意输入,可以在服务器上运行攻击代码,非常危险。

在没有引入函数计算之前,语雀为了支持这些功能,尽管单独分配了一个任务集群,在上面运行这些三方服务,接受主服务的请求来避免影响主服务的稳定性。但是为了解决上面提到的一系列问题还需要付出很大的成本:
1、需要维持一个不小的任务集群,尽管可能大部分时间都用不上那么多资源。
2、需要定时对三方应用软件进行重启,避免长时间运行带来的内存泄露,即便如此有些特殊请求也会造成第三方软件的不稳定。
3、对用户的输入进行检测和过滤,防止黑客恶意攻击,而黑客的攻击代码很难完全防住,安全风险依旧很大。
yq2.png

最后语雀将所有的第三方服务都分别打包在函数中,将这个任务集群上的功能都拆分成了一系列的函数放到了函数计算上。通过函数计算的特点一下解决了上面的所有问题:
1、函数计算的计费模式是按照代码实际运行的 CPU 时间计费,不需要长期维护一个任务集群了。
2、函数计算上的函数运行时尽管会有一些常驻函数的优化,但是基本不用考虑长期运行带来的一系列问题,且每次调用之间都相互独立,不会互相影响。
3、用户的输入代码是运行在一个沙箱容器中,即便不对用户输入做任何过滤,恶意攻击者也拿不到任何敏感信息,同时也无法进入内部网络执行代码,更加安全。
yq3.png

除了上面提到的这些功能之外,语雀最近还使用 OSS + 函数计算替换了之前使用的阿里云视频点播服务来进行视频和音频的转码。

由于浏览器可以直接支持播放的音视频格式并不多,大量用户上传的视频想要能够直接在语雀上进行播放需要对它们进行转码,业界一般都是通过 FFmpeg 来对音视频进行转码的。转码服务也是一个典型的 CPU 密集型场景,如果要自己搭建视频转码集群会面临大量的资源浪费,而使用阿里云视频点播服务,成本也比较高,而且能够控制的东西也不够多。函数计算直接集成了 FFmpeg 提供音视频处理能力,并集成到应用中心,配合 SLS 完善了监控和数据分析。语雀将音视频处理从视频点播服务迁移到函数计算之后,通过优化压缩率、减少不必要的转码等优化,将费用降低至之前的 1/5。
yq4.png


使用效果

语雀产品技术负责人不四表示:从语雀的实践来看,语雀并没有像 SFF 一样将 Web 服务迁移到函数计算之上(SFF 模式并不是现在的函数计算架构所擅长的),但是函数计算在语雀整体的架构中对稳定性、安全性和成本控制起到了非常重要的作用。总结下来函数计算非常适合下面几种场景:

1、对于时效性要求不算非常高的 CPU 密集型操作,分担主服务 CPU 压力。
2、当做沙箱环境执行用户提交的代码。
3、运行不稳定的三方应用软件服务。
4、需要很强动态伸缩能力的服务。

在引入函数计算之后,语雀现阶段的架构变成了以一个 Monolith Application 为核心,并将一些独立的功能模块根据使用场景和对能力的要求分别拆分成了 Microservices 和 Serverless 架构。应用架构与团队成员组成、业务形态息息相关,但是随着各种云服务与基础设施的完善,我们可以更自如的选择更合适的架构。

由于 Serverless 的出现,我们可以将这些存在安全风险的,消耗大量 CPU 计算的任务都迁移到函数计算上。它运行在沙箱环境中,不用担心用户的恶意代码造成安全风险,同时将这些 CPU 密集型的任务从主服务中剥离,避免出现并发时阻塞主服务。按需付费的方式也可以大大节约成本,不需要为低频功能场景部署一个常驻服务。所以我们会尽量的把这类服务都迁移到 Serverless 上。

原文链接

本文为阿里云原创内容,未经允许不得转载。



推荐阅读
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • javascript分页类支持页码格式
    前端时间因为项目需要,要对一个产品下所有的附属图片进行分页显示,没考虑ajax一张张请求,所以干脆一次性全部把图片out,然 ... [详细]
  • 原文网址:https:www.cnblogs.comysoceanp7476379.html目录1、AOP什么?2、需求3、解决办法1:使用静态代理4 ... [详细]
  • 第二十五天接口、多态
    1.java是面向对象的语言。设计模式:接口接口类是从java里衍生出来的,不是python原生支持的主要用于继承里多继承抽象类是python原生支持的主要用于继承里的单继承但是接 ... [详细]
  • 本文是Java并发编程系列的开篇之作,将详细解析Java 1.5及以上版本中提供的并发工具。文章假设读者已经具备同步和易失性关键字的基本知识,重点介绍信号量机制的内部工作原理及其在实际开发中的应用。 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • Python全局解释器锁(GIL)机制详解
    在Python中,线程是操作系统级别的原生线程。为了确保多线程环境下的内存安全,Python虚拟机引入了全局解释器锁(Global Interpreter Lock,简称GIL)。GIL是一种互斥锁,用于保护对解释器状态的访问,防止多个线程同时执行字节码。尽管GIL有助于简化内存管理,但它也限制了多核处理器上多线程程序的并行性能。本文将深入探讨GIL的工作原理及其对Python多线程编程的影响。 ... [详细]
  • Spring – Bean Life Cycle
    Spring – Bean Life Cycle ... [详细]
  • MySQL 5.7 学习指南:SQLyog 中的主键、列属性和数据类型
    本文介绍了 MySQL 5.7 中主键(Primary Key)和自增(Auto-Increment)的概念,以及如何在 SQLyog 中设置这些属性。同时,还探讨了数据类型的分类和选择,以及列属性的设置方法。 ... [详细]
  • 深入解析 Synchronized 锁的升级机制及其在并发编程中的应用
    深入解析 Synchronized 锁的升级机制及其在并发编程中的应用 ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • 深入解析CAS机制:全面替代传统锁的底层原理与应用
    本文深入探讨了CAS(Compare-and-Swap)机制,分析了其作为传统锁的替代方案在并发控制中的优势与原理。CAS通过原子操作确保数据的一致性,避免了传统锁带来的性能瓶颈和死锁问题。文章详细解析了CAS的工作机制,并结合实际应用场景,展示了其在高并发环境下的高效性和可靠性。 ... [详细]
author-avatar
我们一起美容瘦身
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有