前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《架构整洁之道》第 18 章 边界剖析

《架构整洁之道》第 18 章 边界剖析

原创
作者头像
巴啦啦的积累
发布2023-06-04 09:13:03
2480
发布2023-06-04 09:13:03
举报
文章被收录于专栏:巴啦啦的积累

一个系统架构是由一系列组件以及它们之间的边界定义的。而这些边界拥有不同的形式。

跨边界调用

跨边界调用是指边界的一侧,调用另一侧的函数,并传递数据的行为。构造合理的跨边界调用,需要我们对源码中的依赖进行管控。

因为当一个模块发生变更时,其他的模块源码可能也会跟着变动。划分边界,就是为了防止这种事情发生。

令人生畏的单体结构

这是最常见的一种架构,单体结构对源代码进行了解耦分组件(源代码边界),它们的运行仅在同一个进程内。但在部署的角度上来看,架构边界并不存在。在静态语言中,通常以一个可执行文件体现,即所有程序都在这一个执行文件中。

但这并不意味着这种架构就没有意义。即使这种解耦在部署过程中并不可见,但边界的划分还是对该系统的各个组件的独立开发,存在着相当大的意义。

这类架构一般都需要利用某种动态形式的多态,来管理内部依赖。如果不采用面向对象或是类似多态的实现,架构师们就只能退回到例用函数指针,来进行解耦的时代,这太过于危险。

最简单的跨边界调用,就是低层客户端,调用高层服务函数。这种依赖关系,在运行和编译时,方向保持一致。

但是当高层组件的客户端,要调用低层组件中的服务时,我们就需要用多态,来反转依赖关系了。

可以看到,控制流方向,还是和上图一样,由左至右。但是依赖关系,反转过来了。ServiceImpl依赖左侧了,由低层组件依赖高层组件。

所以说,即使是在单体项目中,这种组件划分,仍然对开发,测试,部署,起了极大作用,它可以使得不同的团队一起协作开发,高层组件与低层组件之间也可以得到良好隔离,独立演进。

部署层次的组件

架构系统中最常见的物理边界形式:动态链接库。如.NetDLLJava中的jar文件,以及Unix中的共享库等。这种类型的文件,在部署时不需要重新编译,因为他们已经是二进制的或者已经编译过后的文件。这种属于部署层次上的解耦。

这种按部署层次上的解耦组件,几乎和单体结构一样,也是运行在同一个进程,同一个地址空间的。管理组件,划分依赖的策略基本上和单体结构也一样。它们的跨边界调用也只是普通的函数调用。

线程

单体结构和按部署层次的划分,都可以采用线程模型。当然,线程不属于架构边界,也不属于部署单元。它仅仅是一种管理并调度程序的执行方式。一个线程既可以被包含在单一组件中,也可以横跨多个组件。

本地进程

系统架构还有更明显的物理边界,那就是本地进程。本地进程运行在一个处理器或者同一组处理器上,进程与进程的内存是隔离的,但它们可以通过某个独立的内存区域来实现共享。

每个本地进程,既可以是静态链接的单体结构,也可以是由动态链接的多个组件构成。本地进程的隔离策略也与单体结构,二进制组件基本相同,其源码的依赖关系和跨越边界的方向是一致的,始终指向更高层次的组件。其目的是让低层次进程成为高层进程的一个插件。

服务

系统架构中最强的边界形式就是服务。一个服务就是一个进程。其服务不依赖于具体的运行位置,它们既可以运行在同一个服务器上,也可以位于不同的服务器上。因为服务会假设它们的所有通信都是由网络来进行。

服务之间的通信,相较于函数调用来说,速度是非常缓慢的,所以我们需要控制通信次数。此外,依然要使用低层次服务应当是高层次服务的插件这个规则。为此我们要保证,高层次服务中,不会包含任何低层次服务相关的物理信息,如URI

本章小结

除单体结构外,多数系统都会同时采用多种边界划分策略。无论是服务还是本地进程,它们几乎肯定都是由一个或多个源码组件组成的单体结构,或者一组动态链接的可部署组件。只是形式不一样。

这也意味着一个系统中,通常会同时包含高通信量,低延迟的本地架构边界,和低通信量,高延迟的服务边界。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 跨边界调用
  • 令人生畏的单体结构
  • 部署层次的组件
  • 线程
  • 本地进程
  • 服务
  • 本章小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档