我多年困扰的微服务开发架构(最适合微服务的7大编程语言)
我多年困扰的微服务开发架构(最适合微服务的7大编程语言)如果组织拥有多个团队,每个团队负责一个大型系统的一部分,那么就可以通过微服务分离关注点,将各个独立封装的服务分配给不同的团队。这些团队之间应建立明确的职责界限,根据自己的时间计划部署各个服务。康威定律指出,“设计系统的架构受制于产生这些设计的组织的沟通结构。”译者:弯月出品 | CSDN(ID:CSDNnews)微服务是一种架构风格,通过一组服务构成应用程序,这些服务具备以下特质:
摘要:本文中,将介绍微服务项目中常用的7种语言,并通过几个因素对比一下,包括技术方面的考虑、社会(生态系统)方面的考虑以及经济方面的考虑。
链接:https://t.csdnimg.cn/SQZO
声明:本文为 CSDN 翻译,未经允许禁止转载。
作者:JOSH WULF
译者:弯月
出品 | CSDN(ID:CSDNnews)
微服务是一种架构风格,通过一组服务构成应用程序,这些服务具备以下特质:
- 高可维护性和可测试性;
- 松散耦合;
- 可独立部署;
- 紧紧围绕公司业务组织;
- 由一个小团队负责。
康威定律指出,“设计系统的架构受制于产生这些设计的组织的沟通结构。”
如果组织拥有多个团队,每个团队负责一个大型系统的一部分,那么就可以通过微服务分离关注点,将各个独立封装的服务分配给不同的团队。这些团队之间应建立明确的职责界限,根据自己的时间计划部署各个服务。
这些因素有利于采用多种编程语言。由于每个服务都是单独开发和部署的,而且是松散耦合的,由不同的团队负责,因此完全可以采用不同的语言编写。
那么,适合编写微服务的最佳编程语言有哪些呢?
这要视具体情况而定,而且决定因素多种多样。
在本文中,我将介绍一下微服务项目中常用的7种语言,并通过几个因素来对比一下这几种语言,其中包括技术方面的考虑、社会(生态系统)方面的考虑以及经济方面的考虑。我打算介绍的7种语言如下:
- Java
- C#
- Go
- Typescript
- Python
- Haskell
- Ballerina
我选择这7种语言主要基于以下因素:
- 受欢迎程度(参考指数:https://pypl.github.io/PYPL.html);
- 微服务的适用性(例如,PHP虽然很流行,却不适合微服务);
- 某个方面表现出众(例如,Haskell的绝对受欢迎程度不高,但在函数式语言中的排名很高;Ballerina虽是一种早期的小众语言,却展示出了强大的网络级抽象能力)。
此外,我还会提到一些值得注意的语言,虽然它们没有进入前七名,但仍然值得考虑。
JavaJava 创立于 1995 年,是世界上最流行的编程语言之一。长期的维护和高人气说明Java是一个可靠的选择。曾有人说:“没有人会因为购买IBM而被解雇”,Java也是如此:没有人会因为选择的Java作为实现语言而被解雇。
Java离不开JVM,这个跨平台执行环境可以让Java代码“编写一次,随处运行”,此外JVM还有助于实现规模经济。
虽然你不太可能将服务部署到多个操作系统上,但开发人员能够在多个目标操作系统之间来回切换对创造规模经济有很大的好处。这意味着,愿意应聘JVM相关岗位的开发人员有很多。
这种规模经济也造就了一个庞大的生态系统。Spring Boot是一个功能十分强大的流行框架,可用于在 Java 中构建微服务。此外,Micronaut也是一种流行的选择。
早期版本的JVM有一个主要问题:性能。JVM是一个抽象层,任何抽象都会引入开销。现代版本的JVM已经解决了运行时的性能问题,尤其是 GraalVM。如果你在为启动时的开销而头疼,则可以考虑Quarkus。启动时的开销对于响应式架构来说尤其是一个问题,例如函数即服务(lambda函数)。
此外,Kotlin、Scala 或 Ballerina等其他语言也可以编译出在JVM上运行的程序。你可以利用现有的 Java 库和框架生态系统,因为Java具备互操作性。
Java曾因为空指针异常的问题,引发了“十亿美元的错误”事件。为此,Java 8引入了 Optional 类型。Kotlin 使用不可为空的类型,因此默认就带有这种保护机制。
下面是一些使用 Spring Boot 实现 REST 路由的示例 Java 代码:
package com.example.springboot;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/")
public String index {
return "Greetings from Spring Boot!";
}
}
优点
- 庞大的支持生态系统。
- 悠久的历史,成功的企业应用程序。
- 大量的开发人员。
- 冗长的语法(Kotlin等JVM的替代语言解决了这个问题)。
- 开发人员的技术水平层次不齐。
- 你已掌握Java。
- 你希望雇佣大量开发人员,外包一些开发。
- 你希望在部署和管理中使用JVM专业知识,而且还可以选择代替JVM的语言。
C#是微软早期开发的一种编程语言,微软开发C#是为了阻止JVM和Java语言在Windows上的不断扩张。
C#的语法与Java非常相似。二者都是基于C的现代语言,支持面向对象。如前所述,最初微软开发C#是为了在Windows上取代Java。C#是编译的中间语言,相对应的底层虚拟机是.NET VM。
近年来,.NET VM 已实现跨平台,.NET Core可以让 C# 代码在 Linux 和 Mac 操作系统上运行。因此,开发人员也可以在Linux 服务器上运行C#。
虽然.NET 和 C#近期才实现了跨平台,但由于Windows庞大的用户基础,这两门语言也拥有庞大的库生态系统。微软自己的框架ASP.NET也可用来开发微服务。
C# 8.0 引入了可为空的引用类型,以防止在运行时出现空指针异常。
下面是一些在 ASP.NET 中实现 REST 路由的示例 C# 代码:
[ApiController]
public class PeopleController : ControllerBase
{
[HttpGet("people/all")]
public ActionResult> GetAll
{
return new
{
new Person { Name = "Ana" }
new Person { Name = "Felipe" }
new Person { Name = "Emillia" }
};
}
}
优点
- 背后拥有微软的强大支持,用户基础庞大,财力雄厚。
- 大量的开发人员。
- 冗长的语法。
- 开发人员的技术水平层次不齐。
- 你已掌握C#技术。
- 你使用的操作系统是Windows。
Go是一种网络及系统现代编程语言,由谷歌开发,于2012年发布1.0版本。相较于Java 和C#,Go是一种静态类型的编译语言,生成的是静态链接的原生二进制文件,而不是在 VM 中执行的中间代码。
Go旨在成为一种底层的系统和网络现代编程语言,它在强大的功能(例如指针)和安全性(例如内存管理)之间找到了平衡点。
Go提供了一套标准的格式化规则,还有一个将这些规则应用到代码库的内置实用程序。因此不会再有Tab键与空格之类的争论。
虽然你可以利用Go开发底层的网络功能,但在开发微服务时可能并不需要这么做。有大量的框架构建在高级抽象之上,比如Gin Web Framework、Buffalo、Gorilla、Fiber 和 Echo等,可供你选择。
Go的许多微服务和 Web 框架都是由其他编程语言编写的。因此,Ruby on Rails、Express Node.js等开发人员都可能发现一两种感觉很熟悉的微服务或框架。
许多程序员在遇到Go后,重拾了编程的乐趣。TJ Holowaychuk是Node.js的早期采用者之一,也是 Node 生态系统的主要贡献者,他都选择转而使用 Go。
Go没有在运行时针对nil 指针异常的保护,但它有一个标准的“error result”模式,会强制使用者编写错误处理,这在大多数时候也能提供一定的安全性。
Go的示例代码:
func ListAction(out http.ResponseWriter req *router.Request) {
resource exists := resources[req.Param("resource")]
if exists == false {
//todo: return not found
return
}
action exists := resource["list"]
if exists == false {
//todo: return not found
return
}
action(out req)
}
优点
- 现代编程语言。
- 语言的设计考虑了安全性和开发效率,适合编程新手。
- 生态系统不够成熟。
- 可雇用的开发人员数量较少。
- 如果你对Go感兴趣。
- 团队喜欢Go,且重燃了对编程的热情。
- 你需要比JavaScript更安全的编程语言。
TypeScript是JavaScript的超集,它添加了严格类型(可选)。TypeScript需要转译为JavaScript,然后在JavaScript解释器中执行。
JavaScript本身是一种动态的弱类型语言,最初编写于 1995 年(作者只用了10天的时间),旨在实现网页中的少量交互性。随后,JavaScript逐步扩展到为浏览器中的整个应用程序提供支持,如今还可通过Node.js、Deno 或 Bun提供服务器端代码。
如今,JavaScript无处不在,使用范围非常广泛,因为它的“虚拟机”可通过 Web 浏览器安装到互联网的每台计算机上,而 .NET 和 Java 虚拟机没有这样的载体。
虽然JavaScript产生了爆炸式的增长,但从语言的角度来看,它的结构性远远跟不上它的增长速度。
TypeScript旨在解决使用动态的解释性语言构建大型应用程序时出现的许多问题。TypeScript让JavaScript的类型变得更加严格。代码库可以通过静态分析进行推理,并通过重构强化,而且还提供了代码提示和自动补齐等功能,此外转译还增加了一层安全性。
TypeScript 是由 C# 的语言设计者 Anders Hejlsberg 设计的,因此 C# 甚至是 Java 开发人员对TypeScript都不陌生。
Node.js 有一个庞大的库和框架生态系统,比如功能齐全的NestJS、极简主义Express等。
NPM(Node包管理器)包含数千个可在应用程序中使用的包。
你可以选用函数式编程模式,比如使用 fp-ts 之类的库,以防止运行时空指针异常,但这并不会一直深入技术栈底层。你引入的库依然可能会引发运行时空指针异常。
使用 NestJS 的示例 TypeScript 代码:
import { Controller Get } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Get
findAll: string {
return 'This action returns all cats';
}
}
使用 Express 的示例 TypeScript 代码:
import express { Express Request Response } from 'express';
const app: Express = express;
const port = process.env.PORT;
app.get('/' (req: Request res: Response) => {
res.send('Express TypeScript Server');
});
app.listen(port => {
console.log(`[server]: Server is running at https://localhost:${port}`);
});
优点
- 大量的库和框架。
- 大量了解 JavaScript 的开发人员。
- TypeScript 引入了安全功能,对经验不足的开发人员很友好。
- 整个技术栈只需要这一种语言。
- NPM包可能被污染,是一个安全隐患。
- 庞大的 node_modules 目录会导致应用程序膨胀。
- 你希望整个技术栈只使用一种语言。
Python是一种高级通用解释型语言。Python最显著的特征是“有意义的空白”。Python没有使用花括号,而是使用缩进来表示嵌套。
Python 最初发布于上个世纪80年代初期,是目前最流行的编程语言之一,并且由于其在数据科学中的大量使用而越来越受欢迎。
你只需使用Python的标准库就可以编写 gRPC 微服务,而且还可以利用许多流行的框架,例如 Flask、Django、Nameko、FastAPI 和 MinOS。
Python 没有针对空指针异常的保护。
下面是使用 Flask 实现 REST 路由的示例 Python 代码:
from flask import Flask #importing the module
app=Flask(__name__) #instantiating flask object
@app.route('/') #defining a route in the application
def func: #writing a function to be executed
return 'PythonGeeks'
if __name__=='main': #calling main
app.debug=True #setting the debugging option for the application
instance
app.run #launching the flask's integrated development webserver
优点
- 历史悠久的大型社区,广泛的工具库。
- 美观的代码格式(如果你讨厌花括号的话)。
- 解释型语言,速度可能是一个问题。
- 多线程很棘手。
- 你已在使用Python。
- 你的领域涉及机器学习、数据科学或人工智能。
Haskell是一种纯粹的函数式语言,它是惰性求值和静态类型的,非常适合并发处理。然而,Haskell的学习曲线非常陡峭,不仅仅是语法,还有范式。Haskell 最初是作为大学的学术语言开发的,现已成为深入了解程序抽象的高级程序员的流行语言。
Haskell 程序经过编译后,可保证每次运行(95% 的时间里)都没有未处理的运行时异常。只要程序编写正确,Haskell 在运行时就非常稳定。
Mu-haskell是一组Haskell的微服务库。Haskell的范式并不适用于框架,但适用于库。
下面是实现 gRPC 服务器的示例 Haskell 代码:
main :: IO
main = runGRpcApp msgProtoBuf 8080 server
server :: (MonadServer m) => SingleServerT Service m _
server = singleService
优点
- 能够确保程序的正确性,逻辑表达非常优雅。
- 能够获得其他程序员的敬畏和尊重。
- 开发人员数量较少(相应的竞争压力也很小)。
- 对运行时的安全性和程序的正确性重视超过了开发人员的生产力。
- 你厌倦了常见的编程语言,想尝试“疯狂的”编程模式。
- 你对函数式编程充满热情。
我们曾在介绍Java的时候提到过Ballerina,这是一种运行在JVM 上的语言,但由于在抽象级别上的创新,我们来单独介绍一下这门语言。
Ballerina 是一种开源的 C 衍生语言,于 2015 年开发,该语言的首要目标是现代网络抽象。gRPC 服务器、JSON 和 XML 之类的技术都是该语言中的首要抽象,这就像Docker 和 Kubernetes的关系一样。如果你曾在Java中遇到过JSON序列化的难题,并想念JavaScript对JSON的原生支持,就会明白正确的抽象级别可以在语言中产生多大的影响。
Ballerina还可以根据代码生成序列图,这为现代微服务项目带来了一个重大优势:永不过时的文档。
Ballerina具有 Java 的互操作性,因此你可以利用现有的Java 库生态系统。但是,Ballerina 几乎不需要微服务框架,因为该语言内置了必要的原语。Ballerina的抽象级别与微服务完美匹配,这就是我单独讨论该语言的理由。
Ballerina的示例代码:
import ballerina/http;
import ballerinax/googleapis.sheets;
configurable string githubPAT = ?;
configurable string repository = "ballerina-platform/ballerina-lang";
configurable string sheetsAccessToken = ?;
configurable string spreadSheetId = ?;
configurable string sheetName = "Sheet1";
type PR record {
string url;
string title;
string state;
string created_at;
string updated_at;
};
如下是代码生成的序列图:
优点- 最新的系统文档。
- 一门现代语言,借鉴了之前的语言的许多优秀思想,并将抽象层放到了微服务组合层面上。
- 新语言,仍在积极的开发中,处于其生命周期的早期。
- 很难聘请到有经验的开发人员。
- 你是一家 JVM 开发公司,并且有一个想要试验的项目。
- 你是一家初创公司,想挑战极限。
- 你需要最新的文档。
还有一些其他的编程语言也可用于微服务开发,但没有入选,主要是因为不太受欢迎,但还是值得一提:
- Swift:苹果于2014年推出的编程语言。开源且跨平台,Vapor、Perfect 等多个框架都可用于编写微服务。Swift因其在iOS应用中的使用而广受欢迎,但在微服务中的使用较少。
- Rust:Mozilla于2006年推出的现代编程语言。适合编写微服务的框架有两个:Rocket 和 Tide。
- Dart:谷歌于2011年推出的现代跨平台编程语言。Aqueduct是一个包罗万象的微服务框架。
- Elixir:一种在 BEAM VM 上运行的现代函数式语言,于2012年推出。在寻求高性能语言的 Ruby on Rails 开发人员中很受欢迎。Phoenix 是一个流行的 Elixir 框架。