写点什么

工程师每天都在研究的软件架构是什么?

  • 2019-12-31
  • 本文字数:3589 字

    阅读完需:约 12 分钟

工程师每天都在研究的软件架构是什么?

在某些时候,工程师必须绘制一些方框和箭头来描述软件系统的顶层设计。但是,这些方框和箭头叫什么?我们经常使用诸如微服务,实体,REST 或事件驱动之类的术语,这些又是什么?


作为研究论文的一部分,我一直在阅读有关软件体系结构概念和定义的知识,并且在整篇文章中,我将解释其中的一些概念,这些概念适用于我在研究生期间也一直在从事的项目:JSON- RPC Playground 控制台。

软件架构是什么?

我将使用 Roy Fielding(HTTP 规范的主要作者之一和 REST 风格的创建者)在其博士学位论文中给出的定义(如果您对 Software Architecture 感兴趣,我推荐您看看这篇论文)。


软件体系结构是软件系统在其操作的某个阶段的运行时元素的抽象。一个系统可能由许多抽象级别和许多操作组成,每个阶段都有自己的软件体系结构。

架构是抽象的

在描述体系结构时,可以对实现细节进行抽象,以简化设计。如用 Elixir 或 Java 编写身份验证服务有关系吗,显然这不是在架构层面要考虑的事情?还是它在系统中扮演的角色-验证用户-我们应该关注什么?

架构与运行时有关

源代码结构不是系统的体系结构。当系统处于活动状态时,不同的应用程序可以共享公共库或模块,但彼此之间完全断开连接,这个是低耦合的设计。我们专注于处理数据以及如何移动数据。软件架构一般用高内聚、低耦合方式构建。

架构专注于特定的阶段

并非每个组件都会始终发挥作用或成为各个流程的一部分。系统关闭时涉及的组件及其配置可能与系统正常操作模式中涉及的组件及其配置完全不同。

架构是嵌套的

在抽象元素实现时,我们将忽略与当前架构无关的细节。如果我们将重点转移到更深层次,则将出现具有其自身的元素和配置集的新体系结构。我们将找到许多嵌套的体系结构,直到元素足够简单以至于无法分解为止,实现原子性构建。


一系列决策的结果是创建了一个软件体系结构,每个决策都带来了一组属性和约束。无论它们在图表中是明确指出的,还是仅存在于架构师和开发人员的思想中,对于这些决定和约束应该都有一种理解或意图。随着系统的发展,这些最初的决定很可能与架构的实际情况不符。如果这些差异是不希望的或偶然的,那么我们说该体系结构已被侵蚀,造成了体系结构的“技术负债”。

案例研究:JSON-RPC 控制台

我们的客户平台之一是由数十个 JVM 微服务组成,它们使用 JSON-RPC 2.0 协议相互通信。每个服务使用一组 Java 接口声明其 RPC API,这些 Java 接口作为“ Service-API”库(JAR)发布在公共存储库中。想要与服务进行交互的客户端只需将其 API JAR 声明为项目依赖项即可。平台库将生成实现此类接口的对象,并通过依赖注入提供实现代码类。从代码角度来看,您只是在调用常规方法,但是在后台,平台库正在执行 RPC 调用并为您处理所有涉及的管道。这在编写代码时极大地提高了工作效率!


但是,要手动测试所有这些 RPC 方法(例如,使用诸如 Postman 或 curl 的工具),就必须找到正确的代码库,手动检查服务接口,其方法和参数(可能具有许多嵌套对象级别) ),然后手动构建所需的 JSON payout 以执行 API 调用。一般而言,API 文档有帮助,但是很难保持最新,这是一个问题。


这里,我创建一个 GUI 应用程序,该应用程序会自动生成可轻松填充的表单,以调用服务公开的任何 RPC 方法。这些表单是通过与 JSON-RPC 2.0 兼容的服务描述文件生成的,该文件是通过分析 Service-API JAR 库创建的。通过使用与生产中运行的实际代码相同的源,可以确保它们保持最新。


架构元素

构架系统意味着要做出一系列决定,这些决定可以塑造构成系统的不同元素(组件,连接器和数据)的配置。

组件(Components)

组件是软件指令和内部状态的抽象单元,它通过接口提供转换或执行数据计算。组件是由它们向其他组件提供的服务定义的,而不是由它们的界面后面的实现定义的。如果其他组件无法识别某些行为,则该行为不是体系结构的一部分。

示例

  • RPC 控制台:将服务描述转换为一组表单,捕获用户输入,执行 RPC 调用并显示其结果。

  • RPC 服务器:接收 RPC 请求,对其进行计算,然后返回结果。

  • 分析器:将 Service-API JAR 转换为服务描述。

  • JAR 存储库:存储并提供 Service-API JAR。

  • 服务说明存储库:存储并提供服务说明。


请注意,就此体系结构的观点而言,在定义 RPC Server 组件时,我们对 RPC Server 提供的特定功能不感兴趣,因为它与其余组件无关。我们甚至将这个组件的许多不同实例均等地分组,即使实际上它们在功能上会有很大不同。如,一个可能是 Users 服务,而另一个可能是 Books 服务。

连接器(Connectors)

连接器可实现不同组件之间的通信和数据传输。他们不转换数据,而是通过界面在不同组件之间对数据进行移动。但是在内部,当查看一个特定连接器的体系结构时,我们可能会发现它实际上是由一个子系统组成的,这些子系统接收数据,将其转换为更好的格式以进行传输,将其发送到另一端,然后反转转换,然后再传递给系统的其余部分。由于这些转换对系统的其余部分不可见,因此我们可以将它们抽象化为更高的层次。


在示例中:


  • RPC 客户端:开始 RPC 调用。

  • RPC 服务器:接收 RPC 请求并返回 RPC 响应。

  • HTTP 客户端:启动 HTTP 连接以获取服务描述。

  • AWS 库:将服务描述从分析器传输到服务描述存储库。

  • Gradle 库:将 Service-API JAR 依赖项从 JAR 存储库传输到分析器。


对于 AWS Library 和 Gradle Library 而言,我们不直接负责这些数据传输的方式。然后,我们可以使用连接器的视图,而忽略其实现的细节。

数据 (data)

许多软件体系结构定义没有将数据作为核心概念提及,我认为这并不完整。数据是系统存在的原因,有时甚至是驱动系统配置的主要因素。数据定义为通过连接器从一个组件传输到另一组件的信息。


在示例中:


  • 服务描述:以 JSON-RPC 2.0 兼容结构描述服务公开的可用 RPC 方法。它包括服务器 URL,方法名称,参数和类型之类的信息。

  • RPC 请求:包括 RPC 方法名称及其参数。

  • RPC 结果:RPC 调用执行的结果。

  • Service-API JAR:包含 RPC 服务的 Java 接口的 JAR 文件。

架构风格

架构风格是架构设计决策的命名集合,当在特定上下文中应用时对应不同的系统元素,它们的配置以及它们之间的关联方式施加约束,进而生成具有众所周知架构解决方案。


样式是一种用于对体系结构进行分类并定义其共同特征的机制。每种样式都为组件的交互提供了抽象,通过忽略架构其余部分的细节来捕获交互模式的本质。样式可以仅关注体系结构的某些方面,甚至可以将它们组合以生成更复杂的样式或混合样式。


客户端-服务器,微服务,Monolithic 甚至是 REST 都是不同的体系结构样式,您很可能已将其应用于数十种异构系统。

创造自己的风格

如果您熟悉诸如Swagger的 REST API 之类的工具,您可能会注意到我的 JSON-RPC 项目与之相似。虽然我的控制台使用了针对基于 JSON-RPC 的服务量身定制的服务描述作为输入,但是 REST API 具有OpenAPI标准。从服务的源代码生成规范格式是一种强大的模式,可用于创建许多不同的使用者工具:文档导航器,客户端代码生成器,模拟服务器等。


让我们尝试为该工具系列定义通用的体系结构样式,该样式可以应用于任何其他协议以获得相同的好处:我将其称为“服务描述”样式。

服务风格描述

让我们开始定义架构的不同元素


数据元素:


  • 目标源代码:目标服务接口的源代码。

  • 服务描述:特定于协议的格式,遵循协议标准,可以描述任何目标服务的接口。


组件:


  • 生成器:自动从目标源代码创建服务描述,并将其发布到提供者。

  • 存储库:存储并提供服务说明。

  • 客户端:使用存储库中的服务描述,并将其用作提供针对目标服务动态定制功能的唯一来源。


连接器(connectors):


  • 生成器->存储库:将服务描述从生成器传输到存储库。

  • 存储库->客户端:将服务描述从存储库传输到客户端。


必须从源代码创建服务描述。客户端需要始终保持最新的服务说明才能正常运行,因为除非服务说明中包含客户信息,否则他们对目标服务的具体情况一无所知。主要来源是代码,如果流程不是自动化的,则很可能会出现服务描述过时且客户端损坏的风险。这并不意味着不能手动构建服务描述。这样做有很多有效的用例,例如,如果您想在实际实现之前拥有一个模拟服务器。但是,依赖于手动任务的系统将不被视为该体系结构样式的实现。


请注意,我们对生成器如何使用源代码没有任何限制。实际上,生成器甚至可以作为目标构建过程中的一个步骤来实现(例如,使用 Maven 插件)。服务描述应遵循协议标准。该体系结构的主要优点之一是客户端可针对使用同一协议的许多不同目标服务进行重用,因此,服务描述无法了解仅适用于一项特定服务的特定实现细节。客户端提供的功能不属于体系结构的一部分:客户端可以与目标服务(例如,用于 Playground 控制台)进行交互,或者根本不进行交互(对于静态文档而言)。客户背后的主要限制是,除了服务描述所包含的信息外,他们还应该对目标服务的实施细节一无所知。连接器的定义非常宽松,因为我们对信息的传输方式没有任何限制。


2019-12-31 09:402844

评论 1 条评论

发布
用户头像
这是翻译过来的吗?读起来很拗口,很多概念不明白写的是啥?样式?
2019-12-31 16:01
回复
没有更多了
发现更多内容

天谋科技连续获中国信通院认可,认定为时序数据库领航者厂商

Apache IoTDB

蓝易云 - Centos安装openjdk11并配置JAVA_HOME

百度搜索:蓝易云

Java centos 运维 Openjdk 高防服务器

使用观测云监控观测 AutoMQ 最佳实践

观测云

监控 AutoMQ

Spark内核的设计原理

数新网络官方账号

spark Spark 源码

同样是人工智能 客户在哪儿AI和GPT等大模型有什么不同

客户在哪儿AI

ToB营销 ToB增长 大客户营销

直播预告丨如何抓住“数字经济发展红利”,重塑企业可持续竞争能力?

轶天下事

win版DBeaver Ultimate (数据库连接管理) v24.1.3 特别版

iMac小白

蓝易云 - 三方面告诉你中小企业配备服务器是上云还是物理机

百度搜索:蓝易云

云计算 运维 服务器 云服务器 高防服务器

年中工作汇报必备的3个PPT网站推荐,办公效率直线上升!

彭宏豪95

人工智能 PPT 办公软件 AIGC AI生成PPT

2024火山引擎AI创新巡展:五城联动,解锁AI落地新密码

新消费日报

数字揭秘丨AI 和结构优化技术让《星球大战》的帝国军队在恩多战役中转败为胜

Altair RapidMiner

人工智能 机器学习 仿真 altair

tuxera手动批准内核扩展 如何手动批准其内核扩展 Tuxera Ntfs for mac内核扩展批准不了怎么办

阿拉灯神丁

Mac 内核 磁盘管理 Tuxera NTFS2023\ Tuxera NTFS教程

IoTDB 分段查询语句详解:GROUP BY + 时序语义

Apache IoTDB

比亚迪王传福对话九牧林孝发,一场火出圈的“科技跨界”

Alter

找国内API,用哪家API平台?

幂简集成

API

天谋科技连续获中国信通院认可,认定为时序数据库领航者厂商

Apache IoTDB

idm下载速度慢解决办法 idm批量导入下载使用方法 idm下载速度只有几百kb

阿拉灯神丁

网络 批量 加速器 IDM idm下载

首批通过 | 百度通过中国信通院H5端人脸识别安全能力评估工作

百度安全

蓝易云 - C语言关于&与&&运算符

百度搜索:蓝易云

云计算 运维 C语言 云服务器 高防服务器

以工业互联网为支撑 低代码推动数字技术赋能新型工业化

不在线第一只蜗牛

低代码 数字化 工业互联网 制造业

AI与心理疗愈:探索心大陆的七大应用领域

心大陆多智能体

智能体 AI大模型 心理健康 数字心理

以Zookeeper为例 浅谈脑裂与奇数节点问题

数新网络官方账号

zookeeper

2024年第二季度 DDoS 威胁趋势报告

网络安全服务

TCP udp DDoS Cloudflare DDoS 攻击

深入理解 Vue 3 组件通信

快乐非自愿限量之名

JavaScript vue.js 前端

OpenAI 发布 GPT-4o mini;FasterLivePortrait 支持实时表情转移丨 RTE 开发者日报

声网

最新资讯!《可观测性能力建设指南(2024年)》即将在2024可信云大会上发布!

乘云数字DataBuff

白皮书 可观测 信通院

面试阿里,直呼太难了!

王中阳Go

Go 后端 面经

蓝易云 - vim替换命令 “:s“

百度搜索:蓝易云

vim Linux 运维 pattern flags

win版BluffTitler Ultimate16(3D文字制作软件) v16.6.0.3 特别版

iMac小白

蓝易云 - Tortoise Git(乌龟git)常用命令总结

百度搜索:蓝易云

git Linux 运维 windows Tortoisegit

低代码开发:推动企业数字化转型的创新利器

快乐非自愿限量之名

低代码 数字化 企业转型

工程师每天都在研究的软件架构是什么?_架构_Ignacio Piantanida_InfoQ精选文章