首页 > 其他分享 >Solo开发者社区-重新思考云原生应用的开发模式

Solo开发者社区-重新思考云原生应用的开发模式

时间:2024-01-15 21:44:47浏览次数:35  
标签:原生 Solo const 函数 代码 应用程序 开发 开发者 FaaS

当前云原生应用的开发模式在 FaaS 环境下存在挑战,本文提出一种开发模式构想:“单体式编程,编译时拆分,分布式执行”,旨在简化云应用开发,提升开发效率和应用性能。思路是通过编译器自动拆分单体应用代码,实现云基础设施上的分布式运行。(Solo 社区 投稿)

背景

云原生应用通常形象地解释为应用架构出生或生长在云基础设施上的应用程序。此类基于云基础设施构建的应用程序能够有效利用云提供的自动扩缩、高可靠性等特性,这对于个人开发者和中小型企业来说,不需要关心基础设施的复杂性,又能获得强大的支撑能力,显然是一件很香的事情。

现状

那么,现在是怎么开发云应用程序的?提到云原生应用,大家通常会想到容器、微服务,这两项技术也在 CNCF 对云原生的定义中被提到。一个典型的开发流程可能是:开发者开发微服务粒度的应用代码,封装成容器,最终托管到 PaaS 平台上。

但随着云的发展,函数计算(Function as a Service, FaaS)已经成为云的重要组成部分。相较于 PaaS,FaaS 与云的各项能力结合的更紧密,在扩缩容、冷启动等方面,FaaS 的性能也更加强悍,例如,AWS Lambda 的冷启动时延已经达到百毫秒级。

问题

那么,微服务、容器的开发模式是否仍适用于基于 FaaS 的云原生应用?分析来看:

  1. 函数承载的服务通常被称为 NanoService,比微服务的粒度更小,如果由开发者将一个应用程序的每个函数逐个打包、发布,即使云厂商提供了命令行工具,整个操作过程也会比较繁琐
  2. 将一个应用程序拆分成若干个函数进行开发,各个函数在代码关系上互不相干,函数间的调用必须通过 SDK 进行,这使得开发一个应用需要在不同函数间反复切换,在编程思维上极不连贯
  3. 对函数进行编排需要了解云基础设施提供的事件机制、编排工具等,有了更高的学习成本

整体来说,直接基于 FaaS 的开发模式体验较差,如何有效管理和协调这些函数成为了一个重要问题。显然,我们不希望开发一个应用程序是这种体验,那么,我们该如何开发云原生应用呢?在这里提出一个构想:单体式编程,编译时拆分,分布式执行

联想

看到这个构想,你可能会觉得这与并行编程框架 OpenMP 的思路比较相近,的确如此。OpenMP 利用编译器在代码并行区域添加多线程代码实现并行执行,而在这个构想中同样是利用编译器识别并提取可独立计算的代码区域,但具体的分布式执行则交由云基础设施负责。

大数据计算的 MapReduce、Spark 可能也有些相似,以及近来比较火热的 Ray,同为云计算领域,同样都是面向大规模分布式计算。这里,与以上各类框架显著不同的一个点是,底层运行时实现方式的不同。以上各类框架都是各自构建了一套底层运行时环境来支撑特定种类任务的分布式执行,而这里的构想则是希望基于云基础设施提供的 FaaS 作为统一的底层环境,来实现通用计算,支撑各类云原生应用。两种方式相较而言,前者针对特定负载可能有调度、性能优势,而后者能与云基础设施提供的各项能力结合的更紧密,同时也能让各种场景的负载有结合的可能。

在开发体验上,的确是相近的。

构想

为什么要“单体式编程”

因为我们在开发一个单体应用程序时体验是非常好的,我们的上下文都在一个工程项目中,变量间的依赖关系、函数间的调用关系能够在执行前由 Lint、Format 工具,IDE 插件等各类工具进行检查。

为什么能“编译时拆分”

没有任何编程约束的代码文件的确难以进行拆分,但是可以通过定义关键字、特殊类、特殊函数等方式来指导编译器对代码进行拆分。

例如下面这份代码,可以将 Function 看作使特殊类,而它在构造函数中传递的函数定义就可以被分析提取成一个独立的计算模块。当然,在实际实现时肯定需要考虑更多的情况。

class Function  {
	constructor(fn: (...args: any[]) => any) { /* ... */ }
}

const fn = new Function((a: number, b: number ) => { return a + b; });

async main() {
	const c = await fn.invoke(1, 1);
	console.log("1 + 1 = ", c);
}
main();

特别的是,在拆分出一个个计算模块后,整个代码文件相应去除各个计算模块的代码,剩下的部分也应该成为一个计算模块。而这个计算模块就是整个应用程序的入口,类似单体应用中的 main 函数,而这个 main 函数就可以完成整个应用程序的逻辑编排。

这样,我们就获得了单体式编程的开发体验,并通过编译时拆分的方式获得了基于云的分布式执行的能力。这种开发模式的产物是直接长在云基础设施上的,属于云原生应用。

示例

来看一个基于这种构想的示例程序。这个程序是利用蒙特卡洛计算 Pi,整个代码逻辑很简单:创建 10 个 Worker,每个 Worker 各自执行 100 万次采样,最终汇总采样结果。

const calculatePi = new Function((iterations: number): number => {
  let insideCircle = 0;

  for (let i = 0; i < iterations; i++) {
    const x = Math.random();
    const y = Math.random();
    if (x * x + y * y <= 1) {
      insideCircle++;
    }
  }

  const piEstimate = (insideCircle / iterations) * 4;
  return piEstimate;
});

async main() {
  const workerCount = 10;
  const iterationsPerWorker = 1000000;
  
  let piPromises: Promise<number>[] = [];
  for (let i = 0; i < workerCount; i++) {
    piPromises.push(calculatePi.invoke(iterationsPerWorker));
  }
  
  const piResults = await Promise.all(piPromises);

  const piSum = piResults.reduce((sum, current) => sum + current, 0);
  const pi = piSum / numWorkers;
  console.log(`Estimated value of π: ${pi}`);
}

main();

这份代码执行起来的预期效果应该像上面这张图展示的:

  1. 在编译阶段,拆分出两个计算模块,一个对应 calculatePi,另一个对应整体代码去除 calculatePi 后的剩余代码(main 代码)。
  2. 然后将两个计算模块部署成两个 FaaS 资源实例。
  3. 部署完成后,调用执行 main 代码对应的 FaaS 实例,从日志中获取输出结果。

更复杂的示例可以从这里了解:

2024 年 Pluto 也将基于这个构想继续进行尝试,在具体实现时,会利用静态分析、IaC 等技术来支撑,感兴趣或有适用场景的朋友也欢迎交流。如果觉得想法不错,可以给项目点个 Star,谢谢。

GitHub 仓库: https://github.com/pluto-lang/pluto

订阅

这个专栏会同步更新在 Solo 社区、公众号、知乎、社群。
微信搜索"Solo 独立开发者社区"或者扫描二维码,即可手机订阅。

标签:原生,Solo,const,函数,代码,应用程序,开发,开发者,FaaS
From: https://www.cnblogs.com/Baiang/p/17966433

相关文章

  • 云原生周刊:OpenTofu 宣布正式发布 | 2023.1.15
    开源项目推荐kubeauditkubeaudit是一个开源项目,旨在帮助用户对其Kubernetes集群进行常见安全控制的审计。该项目提供了工具和检查规则,可以帮助用户发现潜在的安全漏洞和配置问题。ChronosChronos是一款综合性开发人员工具,可监控通过RESTAPI或gRPC通信的容器化(Docker......
  • 刚上线三天,OpenAI GPT 商店的「AI 女友」就已泛滥丨 RTE 开发者日报 Vol.126
      开发者朋友们大家好: 这里是「RTE开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(RealTimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但内容仅代表编辑......
  • 独立开发者碎碎念 1115
    关于心态❤在巨大焦虑的心态下,人都来不及生病。我记忆中,高考前神经高度紧张,高考后一场大病如期而至。人啊,真复杂。心态啊,真正能做到面对任何事客观平常心的,有几个呢因此尽可能保持客观平常心面对,想到最糟糕的结局和处理方式吧关于目标......
  • SpringBoot 2.x 正式停更了。Java 8 就看 Solon 的了!
    最近有好多个新闻说:SpringBoot2.x正式停更了,Java8怎么办?当然用Solon喽!Solon,同时支持jdk8,jdk11,jdk17,jdk21。也支持graalvmnativeimage。既支持java8,也支持java21的:@SolonMainpublicclassApp{publicstaticvoidmain(String[]args){Sol......
  • ByConity 社区回顾|ByConity 和开发者们一起展望未来,携手共进!
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群新年伊始,我们想在这里感谢一群ByConity社区的小伙伴们。正是因为有社区的开发者的支持,截止到2023年底,ByConityGitHub获得1409Star,595pullrequest,累计61位Contributor共建者参......
  • 【云原生 • Kubernetes】k8s功能特性、k8s集群架构介绍
     序言你只管努力,其他交给时间,时间会证明一切。文章标记颜色说明:黄色:重要标题红色:用来标记结论绿色:用来标记一级论点蓝色:用来标记二级论点Kubernetes(k8s)是一个容器编排平台,允许在容器中运行应用程序和服务。今天学习一下k8s日志查看相关方法希望这篇文章......
  • Solo 开发者周刊 (第 1 期):开源产品的探索之路
    产品推荐如何着手将一个简单的想法转变为一个成熟的开源项目,以及如何在此过程中利用和贡献于开源社区。同时使其达到商业化的同时,保持原有的开源精神。这些是我们需要探索的。Spug开源运维平台Spug是面向中小型企业设计的轻量级无Agent的自动化运维平台,整合了主机管理、主......
  • Nocalhost 为 KubeSphere 提供更强大的云原生开发环境
    1应用商店安装NocalhostServer已集成在KubeSphere应用商店,直接访问:设置应用「名称」,确认应用「版本」和部署「位置」,点击「下一步」:在「应用设置」标签页,可手动编辑清单文件或直接点击「安装」。建议把service.type设置为ClusterIP,以确保安装不受Kubernetes网络环境......
  • 开发篇1:使用原生api和Langchain调用大模型
    对大模型的调用通常有以下几种方式:方式一、大模型厂商都会定义http风格的请求接口,在代码中可以直接发起http请求调用;方式二、在开发环境中使用大模型厂商提供的api;方式三、使用开发框架Langchain调用,这个就像java对数据库的调用一样,可以直接用jdbc也可以使用第三方框架,第三方框架......
  • 云原生技术专题 | 云原生容器编排问题盘点,总结分享年度使用Kubernetes的坑和陷阱
    Kubernetes与云原生随着云原生的兴起,越来越多的应用选择基于Kubernetes进行部署,可以说Kubernetes是最流行的容器编排和部署平台。它的强大功能特性,可以保障在生产中可靠地运行容器化应用程序,相关的DevOps等工具也应运而生,下面就是小编简单化了一个Kubernetes的逻辑架构图。如何开......