关键要点更新的、专用的编程语言可以提供新颖的做事方式,比我们习惯的方式更有效率。如果使用得当,使用正确的语言和正确的抽象来解决您的问题本身就是企业的竞争优势。无论是使用领域特定语言(DSL)还是模板,集成仍然过于困难。就在最近,这份基准报告表明,由于集成固有的复杂性,许多数字化转型项目失败或受到挑战。Ballerina是一种开源编程语言,专为云原生编程和集成而构建。该语言旨在使其更易于使用、组合和创建网络服务,从而允许您无缝集成分布式应用程序。Ballerina语言自2019年1。0版本以来取得了长足的进步。最新的SwanLake版本通过网络感知和灵活的类型系统、用于开发服务和API(包括REST)的构造进一步简化了云原生应用程序的构建和部署、GraphQL和gRPC)、序列图表语法、JSON支持和内置并发以及本文将探讨的许多其他功能。Ballerina的背景 集成可以被认为是一种编程类型,并且通常已经成为一种视觉表示,采用不同的技术试图简化和抽象复杂性。DSL变得非常流行,因为它们为编程提供了正确的抽象,但它们也有局限性通常情况下,集成开发人员必须使用常规代码来解决部分问题。此外,集成编程实践已经变得孤立,以至于使用所选集成工具进行编程的开发人员必须使用另一种工具或编程语言来开发其应用程序的其余部分。视觉表示对于能够观察端点之间的流动和交互仍然很重要。最重要的是,借助云原生工程,集成系统现在在容器中运行, 拥有一种能够提供与代码集成的能力以及可视化工具的语言不是非常有用吗?这样我们就可以解决DSL的局限性,并且能够保留软件工程的最佳实践?这种想法正是导致了芭蕾舞女演员项目的原因。目标是创建一种现代编程语言,将最好的编程语言、集成技术和云原生计算结合成一种针对集成进行优化并具有主流潜力的文本和图形语言。 让我们通过下面的列表来探索在SwanLakeBeta版本中引入或增强的Ballerina语言的关键特性,从而了解为什么Ballerina是创建网络服务和分布式应用程序集成的绝佳选择。Ballerina的主要特征1。Ballerina以应用程序语言的健壮性和可扩展性解决脚本语言的大多数用例 您可以认为语言的范围从Perl或Awk等脚本语言到Rust或C等系统语言,中间有Go或Java等应用程序语言。程序可以用一行脚本编写,甚至可以编写数百万行代码。Ballerina介于脚本语言和应用程序语言之间。 Ballerina具有独特的功能,使其特别适合小型节目。大多数其他为较小程序设计的脚本语言与Ballerina的显着区别在于它们是动态类型的,并且它们不具有Ballerina所具有的独特的可伸缩性和健壮性功能。您可以使用其他脚本语言解决的前云时代的问题仍然是相关问题。除了现在,涉及网络服务;稳健性现在比以往任何时候都更加重要。使用标准脚本语言,一个50行的程序往往会在几年后变成一个不可维护的1000行程序,而且这不会扩展。Ballerina可用于解决通过脚本语言程序解决的问题,但它更具可扩展性、更健壮且更适合云。2。Ballerina是面向数据而非面向对象的 在网络交互中,面向对象的方法将数据与代码捆绑在一起,这并不是通过广泛分布的微服务和API网络发送数据的最佳方式。 在前云时代,你的API是对路径中库的函数调用,你可以在调用中传递对象。但是当您的API在云中时,您不能这样做。您希望能够通过独立于代码的网络发送数据,因为您不想公开您的代码。尽管JAVARMI和CORBA尝试支持分布式对象,但当您具有紧密耦合并且两端都属于同一方时,它就可以工作。分布式对象在松散耦合的云中不起作用。Ballerina强调独立于用于处理数据的任何代码的纯数据。虽然Ballerina为内部接口提供对象,但它不是面向对象的语言。 随着云中的服务越来越多,开发人员被赋予了在其代码中使用网络资源的额外责任。编程语言本身必须有助于此操作。这就是为什么Ballerina配备了一个网络友好型系统,该系统具有强大的功能来处理网络上的数据。 JSON是Ballerina中的通用语。Ballerina中的数据类型非常接近JSON,并且一组基本的数据类型(数字、字符串、映射和数组)一对一映射到JSON。Ballerina的普通内存数据值几乎是内存中的JSON。这允许来自网络的JSON有效负载立即进入语言并在没有转换或序列化的情况下对其进行操作。importballerinaio;importballerinalang。value;jsonj{x:1,y:2};ReturnsthestringthatrepresentsjinJSONformat。stringsj。toJsonString();ParsesastringintheJSONformatandreturnsthevaluethatitrepresents。jsonj2checkvalue:fromJsonString(s);AllowsnullforJSONcompatibility。jsonj3null;publicfunctionmain(){io:println(s);io:println(j2);}3。Ballerina有一个灵活的类型系统 编程语言的类型系统允许您描述您的位如何组合在一起,并且已经超越了捕获一类错误现在这只是类型系统为您所做的一小部分。这也是提供良好IDE体验的重要部分。 脚本语言具有动态类型,而应用程序语言具有传统的静态类型,如C或Java。如前所述,Ballerina是一种脚本语言,但它也具有应用程序语言的特性,包括静态类型系统。在静态类型语言中,类型兼容性在编译时进行检查。静态类型语言通常对重构更健壮,更容易调试,并有助于创建更好的语言工具。 尽管Ballerina的类型系统是静态的,但它比应用程序语言中的类型灵活得多。Ballerina语言的类型系统主要是结构化的,并增加了对名义类型的支持。这意味着类型兼容性是通过考虑值的结构来识别的,而不仅仅是依赖于类型的名称。这与具有标称类型系统的Java、C和C等语言不同,其中类型兼容性受实际类型名称的约束。您可以根据需要对结构多说或少说。有了这个,我们通过接受在编译时不会捕获某些东西来获得简单性和灵活性。 详细地说,您可以说它类似于在XML模式中定义结构的方式。如果程序接收到的XML有效负载发生变化或偏差,它仍会处理它可以识别的内容。如果有效载荷中的某些更改无法识别,则不会导致失败。Ballerina的类型系统既可以用作描述网络数据的模式语言,也可以用作处理内存中值的程序的类型系统。 在此处阅读有关Ballerina灵活类型系统的更多信息。4。Ballerina具有处理网络数据的强大功能 Ballerina还带有一组用于处理数据的语言功能,其中集成的查询功能脱颖而出。此功能允许您使用类似SQL的语法查询数据,如下所示。查询表达式包含一组类似于SQL的子句来处理数据。它们必须以from子句开头,并且可以执行过滤、连接、排序、限制和投影等各种操作。importballerinaio;typeEmployeerecord{stringfirstName;stringlastName;decimalsalary;};publicfunctionmain(){Employee〔〕employees〔{firstName:Rachel,lastName:Green,salary:3000。00},{firstName:Monica,lastName:Geller,salary:4000。00},{firstName:Phoebe,lastName:Buffay,salary:2000。00},{firstName:Ross,lastName:Geller,salary:6000。00},{firstName:Chandler,lastName:Bing,salary:8000。00},{firstName:Joey,lastName:Tribbiani,salary:10000。00}〕;Querylikeexpressionsforlistcomprehensionsstartwithfromandendwithselect。Theorderbyclausesortsmembersinemployeesbasedonthelastname。Employee〔〕sortedfromvareinemployeesorderbye。lastNameascendingselecte;io:println(sorted);} 还有一种Table数据类型,可以轻松处理关系数据和表格数据。下面的代码创建了一个包含Employee类型成员的表,其中每个成员都使用其名称字段进行唯一标识。主函数检索键值为John的Employee并为每个员工执行加薪。importballerinaio;typeEmployeerecord{readonlystringname;intsalary;};CreatesatablewithEmployeetypemembers,whereeachmemberisuniquelyidentifiedusingtheirnamefield。tableEmployeekey(name)ttable〔{name:John,salary:100},{name:Jane,salary:200}〕;functionincreaseSalary(intn){Iteratesovertherowsoftinthespecifiedorder。foreachEmployeeeint{e。salaryn;}}publicfunctionmain(){RetrievesEmployeewithkeyvalueJohn。Employee?et〔John〕;io:println(e);increaseSalary(100);io:println(t);} 在此处阅读有关在Ballerina中编写集成查询的更多信息。 此外,Ballerina提供了内置的XML支持,其功能类似于XQuery,并带有XPath等XML导航机制。这对于大量使用XML但不想使用特定于XML的语言的人特别有用,因为他们现在使用各种数据格式。importballerinaio;publicfunctionmain()returnserror?{xmlx1xmlnameSherlockHolmesname;xml:Elementx2xmldetailsSirArthurConanDoyleauthorlanguageEnglishlanguagedetails;doesconcatenation。xmlx3x1x2;io:println(x3);xmlx4xmlnameSherlockHolmesnamedetailsSirArthurConanDoyleauthorlanguageEnglishlanguagedetails;doesdeepequals。booleaneqx3x4;io:println(eq);foreachiteratesovereachitem。foreachvariteminx4{io:println(item);}x〔i〕givesithitem(emptysequenceifnone)。io:println(x3〔0〕);x。idaccessesrequiredattributenamedid:resultiserrorifthereisnosuchattributeorifxisnotasingleton。xmlx5xmlparaidgreetingHellopara;stringidcheckx5。id;io:println(id);x?。idaccessesoptionalattributenamedid:resultis()ifthereisnosuchattribute。string?namecheckx5?。name;io:println(nameis());Mutateanelementusinge。setChildren(x)。x2。setChildren(xmllanguageFrenchlanguage);io:println(x2);io:println(x3);} 在无缝处理不同类型数据的其他功能中,Ballerina中还有十进制数据类型。这些是为业务需求设计的浮点数,例如,用于指示价格。因为值在普通语言中以二进制表示,所以它们不能准确地表示所有实数。当数字多于格式允许的数字时,将省略剩余的数字数字被四舍五入,从而产生精度错误。现实世界运行在十进制数字上,这就是为什么我们认为它是一种强大的能力。importballerinaio;Thedecimaltyperepresentsthesetof128bitsIEEE754Rdecimalfloatingpointnumbers。decimalnanos1d1000000000d;functionfloatSurprise(){floatf100。100。01;io:println(f);}publicfunctionmain(){floatSurprise();io:println(nanos);}5。Ballerina本质上是并发的,并为并发提供了内置的安全性 并发是云中的一项基本要求,因为您的网络操作具有很高的延迟。脚本语言通常不能很好地处理并发。像Javascript这样的脚本语言通常使用异步函数,这比回调稍微好一点(但不是很多)。使用Ballerina,您拥有一个更简单的编程模型,它提供了异步函数的优点,但它是一种比异步函数更直接和直观的并发方法。 在Ballerina中,主要的并发概念是strand,类似于Go中的goroutine。Ballerina程序在一个或多个线程上执行。一个线程可以与其他线程同时在单独的核心上运行,或者可以与其他线程在单个核心上抢先执行多任务。每个线程可以分为一个或多个线程,它们是语言管理的逻辑控制线程。从程序员的角度来看,strand看起来确实像一个OS线程,但实际上并非如此它更便宜、更轻量级。可以在单独的OS线程上调度Strands。Go遵循类似的方法,但没有多少编程语言这样做。事实上,大多数动态脚本语言不支持并发。例如,Python有一个全局锁,因此它并不真正支持并行执行。 Ballerina中的函数可以命名为workers,每个函数都与函数的默认工作者和其他命名工作者同时在新链上运行,如下所示:importballerinaio;publicfunctionmain(){Codebeforeanynamedworkersisexecutedbeforenamedworkersstart。io:println(Initializing);finalstringgreetingHello;Namedworkersrunconcurrentlywiththefunctionsdefaultworkerandothernamedworkers。workerA{Variablesdeclaredbeforeallnamedworkersandfunctionparametersareaccessibleinnamedworkers。io:println(greetingfromworkerA);}workerB{io:println(greetingfromworkerB);}io:println(greetingfromfunctionworker);} Ballerina还允许strands共享可变状态。通常,将并发和共享可变状态结合起来会产生数据竞争并给出不正确的结果。这是动态语言通常不公开线程的原因之一。然而,芭蕾舞女演员为这个问题提供了一个很好的解决方案,并通过协作多任务处理确保并发安全。属于同一线程的两条链不能同时运行。相反,Ballerina合作(而不是抢先)将所有线程多任务处理到单个线程上,以避免锁定问题。这类似于异步函数,其中所有内容都在单个线程上运行,但没有复杂的编程模型。一条链通过让步实现协作式多任务处理。当一个链在特定的屈服点屈服时,运行时调度程序可以暂停该链的执行, 我们还可以确定何时可以并行运行strand注释可用于使strand在单独的线程上运行。这是因为Ballerina独特的类型系统可以确定服务何时锁定到足以安全地使用多个线程来并行处理传入请求。虽然这似乎无法提供大量的并行执行,但足以有效利用常见的云实例类型。importballerinaio;publicfunctionmain(){Eachnamedworkerhasastrand(logicalthreadofcontrol)andexecutionandswitchesbetweenstrandsonlyatspecificyieldpoints。workerA{io:println(InworkerA);}Anannotationcanbeusedtomakeastrandrunonaseparatethread。strand{thread:any}workerB{io:println(InworkerB);}io:println(Infunctionworker);}6。Ballerina有一个内在的图形视图 处理并发和网络交互是编写云程序的固有部分。在Ballerina中,每个程序都是一个自动说明分布式和并发交互的序列图。Ballerina程序中的函数在文本语法和序列图中都有等效的表示。您可以在两个视图之间无缝切换。芭蕾舞女演员独特的图形视图并不是事后才想到的。事实上,它已被深入设计到语言中,以便提供关于函数的网络交互及其并发使用的真正洞察力。序列图是最适合这种情况的图表。 为了解释,Ballerina的命名工作者(在第5点中讨论)和其他功能级并发特性描述了并发性,而客户端和服务的语言抽象描述了网络交互。垂直线也称为生命线,代表工作人员和远程端点。远程端点是一个客户端对象,它包含表示与远程系统的出站交互的远程方法。远程方法调用有不同的语法,大多数语言不区分远程调用和常规函数调用。水平线表示从函数的工作人员发送到另一个工作人员或从函数的工作人员发送到远程端点的消息。Ballerina可以轻松区分这些关键方面,并向用户展示它们的高级视图,而无需用户执行任何操作。这仅是可能的,因为图形元素从一开始就被设计成语言。你没有得到这个用任何其他语言! BallerinaVSCode插件可以从源代码动态生成序列图。要从上述Ballerina代码开始生成序列图,请下载VSCode插件并启动图形查看器。7。Ballerina是云原生的,具有用于生产和消费服务以及将代码部署到云的简单模型 除了网络感知类型系统,Ballerina还提供了用于处理网络服务的基本语法抽象。该语言还包括使用Docker和Kubernetes在云上部署Ballerina应用程序的内置支持。 服务对象产生服务 Ballerina容纳了服务的概念,一个服务可以只用三四行Ballerina代码编写。Ballerina中的服务由三个协同工作的事物提供支持:应用程序、侦听器和库。应用程序定义服务对象并将它们附加到侦听器。监听器由图书馆提供;例如,每个协议(HTTPGraphQL等)都有一个侦听器,由库提供。侦听器接收网络输入,然后调用应用程序以查找服务对象。服务对象支持两种接口样式:远程方法以动词命名,支持RPC风格资源以方法命名(例如GET)名词,并支持RESTful风格(用于HTTP和GraphQL) 由于Ballerina的服务方法与其独特的面向线路的类型系统相结合,您可以从Ballerina代码生成接口描述。这可以是OpenAPI或GraphQL规范。因此,您实际上可以编写常规的芭蕾舞演员服务对象并生成您的客户端代码。这些功能的组合使云集成能够顺利工作。importballerinahttp;serviceonnewhttp:Listener(9090){resourcefunctiongetgreeting(stringname)returnsstring{returnHello,name;}} 使用远程服务的客户端对象 出站网络交互由客户端对象表示。客户端具有代表与远程系统的出站交互的远程方法。客户端对象是允许我们绘制序列图的语法元素之一。importballerinaemail;functionmain()returnserror?{email:SmtpClientscchecknew(smtp。example。com,user123example。com,passwd123);checkscsendMessage({to:contactballerina。io,subject:Ballerinabody:Ballerinaisprettyawesome!});} 代码到云 Ballerina支持从代码生成Docker和Kubernetes工件,无需任何额外配置。这简化了在云中开发和部署Ballerina代码的体验。代码到云通过从代码中派生所需的值来构建容器和所需的工件。有关更多详细信息,请参阅此示例。 要将您的代码部署到不同的云平台,例如AWS和MicrosoftAzure,请使用服务对象上的注释来实现轻松的云部署,如下面的代码片段所示。Ballerina编译器可以生成工件,例如Dockerfile、Docker映像、KubernetesYAML文件和无服务器函数。 例如,可以通过使用azurefunctions:Function注释Ballerina函数在Azure中部署Ballerina函数。importballerinauuid;importballerinaxazurefunctionsasaf;HTTPrequestresponsewithnoauthenticationaf:Functionpublicfunctionhello(af:HTTPTrigger{authLevel:anonymous}stringpayload)returnsaf:HTTPOutputstringerror{returnHello,payload!;}8。错误的显式控制流 处理错误的方法对语言设计和使用有着广泛的影响。它影响着语言的一切。当您处理网络时,错误是做生意的正常部分,尤其是考虑到分布式计算的八个谬误时。许多前云语言,例如Java、Javascript和Typescript,都使用异常作为处理错误的一种方式。但并非每种语言都遵循这种设计。Go和Rust等语言甚至根本没有异常。 除了例外,控制流是隐式的,代码更难理解和维护。当出现问题时,只是方便地抛出异常会使一切变得完全混乱。为了使错误处理工作,您必须能够查看程序并了解是否存在错误,错误可能发生在哪里以及控制流将如何变化。因此,现在有一个相当强烈的趋势是消除异常并回到更简单的方法,其中错误是显式的,并在错误时使用正常的控制流。这种方法可以在Go、Rust和Swift中找到。Ballerina遵循相同的方法,并允许开发人员使用带有显式错误控制流的错误数据类型。importballerinaio;Convertsbytestoastringandthentoanint。functionintFromBytes(byte〔〕bytes)returnsinterror{stringerrorretstring:fromBytes(bytes);Theisoperatorcanbeusedtodistinguisherrorsfromothervalues。ifretiserror{returnret;}else{returnint:fromString(ret);}}Themainfunctioncanreturnanerror。publicfunctionmain()returnserror?{interrorresintFromBytes(〔104,101,108,108,111〕);ifresiserror{Thecheckexpressionisshorthandforthispatternofcheckingifavalueisanerrorandreturningthatvalue。returnres;}else{io:println(result:,res);}}9。事务作为语言特征 编写使用事务的Ballerina程序非常简单,因为事务是一种语言特性。Ballerina提供的不是事务性内存,而是对分隔事务的基本语言支持。这样,您始终可以保证您的事务具有开始、回滚或提交选项。 Ballerina程序的运行实例包括事务管理器。这可以在与Ballerina程序相同的进程中运行,也可以在单独的进程中运行(不应通过不可靠的网络连接)。事务管理器维护从每个链到事务堆栈(或者,在分布式上下文中,事务分支)的映射。当一个链的事务栈非空时,我们说它处于事务模式;链的事务堆栈上最顶层的事务是该链的当前事务。importballerinaio;publicfunctionmain()returnserror?{Compiletimeguaranteesthattransactionsarebracketedwithbeginandcommitorrollback。Transactionstatementbeginsanewtransactionandexecutesablock。transaction{doStage1();doStage2();Committingatransactionmustbedoneexplicitlyusingacommitstatementanditmaycauseanerror。checkcommit;}}functiondoStage1(){io:println(Stage1completed);}functiondoStage2(){io:println(Stage2completed);} Ballerina中的事务还包括其网络交互功能,即客户端和服务,以支持分布式事务。用户可以通过将服务的资源远程方法和客户端对象的远程方法声明为事务性来创建客户端和服务之间的事务流。10。许多功能都很熟悉 语言的激增确实表明个人愿意学习新的语言。但企业似乎不愿意采用一种新语言,因为他们担心自己无法雇用熟悉该语言的人。重要的是要强调,虽然Ballerina提供了更好的做事方式,但它还附带了C系列语言程序员熟悉的部分功能,足以让开发人员在几个小时或更短的时间内开始使用。 流行的C系列语言(C、C、Java、JavaScript、C、TypeScript)有很多共同点,而Ballerina通过以同样的方式做很多事情来利用这一点。如果您是一名对任何C系列语言都有一定编程经验的程序员,那么使用Ballerina进行编码将相当简单。除了强大的语言功能外,Ballerina这意味着该语言带有丰富的标准库(包含用于网络数据、消息和通信协议的库)、包管理系统、结构化文档、测试框架,以及流行IDE(尤其是VisualStudioCode)的扩展插件以及其他支持该语言的工具。结论 虽然Ballerina具有现代编程语言的所有通用功能,但它的优势在于它独特地提供了语言功能,使其更易于使用、组合和创建云网络服务。开发人员现在可以构建弹性、安全和高性能的服务,解决分布式计算的谬误,并将它们集成以创建云原生应用程序,只需使用专门的编程语言即可。