简洁应用框架VSEF的架构

f0192fd8f5fa59419129346029c45d14.gif

本文介绍了一些简洁架构VSEF的一些框架结构理解,并且抛出了一些演化的主题,这些主题的不同思考会让系统发展成不同的风格,实际也是应用定位的必然结果。

1e95960ac4d5aee95250b0a3c14a23c2.png

总体

VSEF 架构理念 =  基本结构 + 演化

  1. 基本结构 = 入口 + 内核 + 依赖

    内核= 简单逻辑 + 复杂流程

    简单逻辑 = 业务脚本 + 能力执行

    复杂流程 = 流程编排 + 节点衔接 + 能力(任务)执行

  2. 演化 =  主题讨论 + 组件选取(市场组件优先)

    

974e5f4c7af7819702b801f033ddfb63.jpeg

VSEF 总体结构

6e7dbf4b9b4382851735a1564b240175.png

核心架构

架构 = 组成要素 + 关系 + 设计/演化原则

  入口

VSEF 观点:入口要清晰明确

就像 “要理清乱了的线团,就要找到线头一样”,将入口放在一个完整的目录,或者模块中的好处是:可以快速地功能总览,了解“提供哪些服务”、“接收那些消息”、“实现哪些任务”。

这里的目录类型有:

  1. 服务 service : 对外提供的 rpc 服务, 如HSF。这个一般会搭配一个服务 client 可调用者使用。

  2. 消息 message:可以再区分 metaq 和 notify 目录。

  3. 调度 scheduler:一些调度任务。

ad82b5b6a689b4d9a07962f20b0d8f8b.png

业务入口

  内核

业务逻辑进入之后,常见的结构是 Service + Component + Mapper。但随着操作链路的增多,会逐渐交织耦合,变得复杂。所以,需要一些设计,包括:纵向的分层、横向的目录划分、并定义复用的区域,缓解代码安放问题造成的复杂度。

VSEF 观点:内核 = 简单逻辑 + 复杂流程

ecaefe3d6e73b40d59fcf224deed28af.png

内核结构

复杂流程,主要是写入服务,或者是带页面表达的详情服务,采用流程分类框架(Process Classification Framework,PCF)。进入到应用的时候,主要分为3层:

  1. 流程 l3.process:进行业务活动编排,理解整个请求要完成什么事情。

  2. 活动 l4.activity:提供每个执行步骤的能力,代表了事情的关键节点。

  3. 能力(任务) l5.ability:节点执行时要做的一些具体任务,期望包装为能力,具备一定的复用性。

79fa21405aeaec5f90e0e9d4eddd277d.png

流程分类框架 PCF 层次

简单流程,主要是只读服务,如查询数据等,可以直接进入服务脚本 service。简单服务直接使用 l5能力(任务)。当逻辑逐渐复杂的时候,可以重构为复杂流程。



VSEF 观点:完成任务需要使用的资源都是依赖,依赖皆服务。服务都通过 l5能力 进行使用。

l5 能力在进行具体操作的时候,需要从数据、扩展、外调、中间件等渠道获取需要加工的数据,形成自己的理解。这个过程中,依赖的东西被称为“依赖”,通过“服务”的方式进行集成。

  依赖

可以放进依赖的类型:

  1. 存储实现 repository : 数据库的读写操作。

  2. 中间件使用 middleware:包括缓存(tair)、发送消息(metaq、notify)、配置(diamond、switch)等。

  3. 网关实现 gateway:外部系统的调用,比如订单服务、退款服务等。

  4. 扩展实现 extension:业务差异性设计的扩展能力,需要业务提供扩展插件,或者平台代写。

1aed336746f583c898127528a38459c0.png

依赖内容

VSEF 观点:基础设施是否易变,可自行判断,稳定时可以直接依赖。

这里值得讨论的是:如果基于六边形架构,这些基础设施被视为具体实现,应该通过抽象接口,依赖倒置的策略,实现解耦。但是实际在大家的系统中,可以判断其易变性,如果长期保持稳定的话,可以减少依赖抽象这一层,直接依赖基础设施,减少抽象成本,在思考层面做到 less is more。

7f3a174ee60a0bbe5ac5dfd4d9dee231.png

主题演化

VSEF 的目录只是一个初始化、相对简单的系统结构。如果随着业务的发展,各个组成部分会逐渐臃肿,系统风格可能也会变化。所以需要引入一些主题的讨论,结合业务情况进行一些设计,并选取相关组件,进行集成,形成有具体组织特征的、新特性的应用结构。

VSEF 观点:演化后的系统结构,结合了功能特性,才是各个组织的合适的系统结构。

这样的系统结构可能会彼此差异很大,会成为不同的类型,就像七个葫芦娃一样,核心本领各不一样:

  1. 注重平台服务的:关注平台逻辑和扩展机制。

  2. 注重组件表达的:与用户有交互,需要关注组件化协议。

  3. 注重领域协作的:需要关注协调者的模型和设计、应用内的领域划分逻辑。

  4. 注重数据服务的:关注数据能力性能、功能范围、数据模型映射。

ffe072a768a760ef15bb71f07727000b.png

VSEF 主题

下面,会基于VSEF的主题,简单谈一下思考,有了这一部分,才会知道如何去选择组件,而不是“被组件的厚重所绑架”,避免为了用而用,实际并不合适。

  组件协议

如果系统是平台型的,并且带界面表达,那么需要解决的就是各个端、各个页面、各个业务不一样的扩展能力。在内部模型和视图模型之间增加一层ViewModel, 然后基于这个进行各种转换,是不错的思路,比较典型的组件有:奥创、Astore等。

3de8ba3f357bead9857c7f83f46a1d39.png

Model-View-ViewModel(MVVM) 模式

这里细化开来,关于 ViewModel 能够有多定制,有2个不同的走向:

  1. 转换主要在组件框架中:在核心逻辑之外,进行各种框架植入,如奥创、Astore, 在数据出口侧进行转换,转换的手段一般是基于规则表达式,利用相关反射能力进行数据组装。

  2. 转换主要在业务扩展中:不想在组件框架中承载过多代码,想和业务普通扩展逻辑走的近一些,在系统执行过程中的扩展逻辑中,植入视图的扩展,可以较好匹配前台组件。

6710e401eb3ba49d50424bed4f6ce24c.jpeg

奥创&DinamicX 方案运行原理

  活动编排

流程编排是对一个业务操作执行过程进行进一步的划分,常见的编排组件有:Tbbpm、SmartEngine 等。但在实际开发过程中,常常会有这样的疑惑:为什么是这几个节点?为什么是这样的顺序?

  • 为什么是这些节点?

这和我们看到一段非常长的代码,把它切分成几个方法是类似的。关键是切分的依据是什么?常用的一些划分点有:

  1. 是不是调用了一个服务?那么准备服务参数,调用,返回结果判断可以包装为一个节点。

  2. 是不是都在操作一个对象?那么这些操作可以归类为:初始化,修改,转换等内聚的方法。

  3. 是不是一些通用的处理?比如安全校验、日志监控、数据统计等。

  4. 是不是存在业务扩展性?可以单独独立出来,作为抽象方法,或者使用组合,提供相关接口定义。

71b472d066220c02d8eb02630a652004.jpeg

切分的背后是理解

  • 为什么是这样的顺序

基于这些切分原则,可以对一个执行过程的核心要点进行切分,切分完后排序的依据是什么?为什么一定要是这样的顺序?这个问题本质是需要了解各个部分的依赖关系,这些依赖关系可能是:

  1. 上下文数据依赖

  2. 本身地位:需要对最终结果进行收口,需要最后执行。

  3. 系统框架要求必须进行初始化先执行

  4. 其它等等

那么我们可以去梳理这些依赖关系,形成一个有向无环图,最后变成寻找了拓扑排序这样的问题:

  1. 每个顶点出现且只出现一次

  2. 若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面

有时候,这个顺序是唯一的,但是大多数时候这个顺序是不唯一的,所以我们更应该去了解内部的依赖关系,而不是纠结于表面的顺序。

51620cf3766a31adbc80dd99c41d9e9f.jpeg

排序的背后是依赖

  设计模式

在比较重的业务逻辑处理过程中,除了集成一些框架、目录与jar包层次的设计之外,比重最大的启示是普通 java 代码,而这些能够影响最大的是,是设计原则与设计模式。这些应该是不能忽略的点。

常见的场景举例有:

  1. 模版方法:模版方法是说对一个执行过程进行抽象分解,通过骨架和扩展方法完成一个标准的主体逻辑和扩展。平台和扩展能力的设计,做类比是比较合适的。基础的模版就是整个流程的编排和对应的节点,可扩展的地方就是各种业务定制区域。这样形成了平台和业务较好的融合。

  2. 策略模式:策略是说完成一个事情有不同的算法,可以进行相关切换。在逆向退款中,需要支持不同的退款链路,有些需要是担保交易,有些是保证金链路,有些是微信支付,有些是退卡、退资产。为了支持多种出账策略,采用了策略模式,可以通过扩展点定制各种资金策略。

  3. 责任链模式:责任链是说将请求让队列内的处理器一个个执行,直到找到愿意执行的。扩展中,在执行回收结果的时候,会遍历实现的插件,并结合回收规则,进行及时的熔断。

  4. 观察者模式:观察者模式是说我们通过注册、回掉这样的协作设计,完成变化通知的协作机制。系统间基于消息的观察模式还是很多的。通过消息的异步通知方式,既可以较好地进行解耦,也可以在失败时利用消息的重投机制,增加成功的概率。

  5. 中介者模式:当多个类之间要协调的时候,往往引入中介者进行协调,减少大家的知识成本。系统中的流程执行过程中,会有一个大的上下文,这个上下文会协调各个领域的数据。

......

357e8ecd5c9a54538e6b9a85212563aa.png

常见的策略模式

  元数据

当内部结构开始复杂的时候,就期望使用一些元数据。一方面,期望这个能够将理念传达给开发者,知道对应类的角色。另一方面,这部分的扫描,可以形成结构知识,并通过各种数据转存,在另外一个系统无关的页面进行展示,可以站在更高地抽象和中文描述层次,更好地方便大家理解。

认知复杂性:度量理解软件所需要的努力,即捕获程序的逻辑流,并度量逻辑流的各种特性。

60229dbc766c576985ab0aa0f1fadbdb.png

简单元数据设计

  复用独立

单刃为刀,双刃为剑。们在用这个双刃剑的时,当一面对着敌人,另一面一定会对着自己,这时如果将剑刃对着敌人砍去的时候,敌人用兵器一挡,剑就会反弹回来,对自己就会有一定的危险。

代码复用是一把双刃剑。复用意味着代码的影响面会增加,虽然提高了开发效率,但是一但进行改动,影响范围变大的副作用也很明显:要求你得足够了解影响的范围,进一步增加了认知的复杂性。在影响较大的情况下,不合理的复用会产生很多令人崩溃的补丁逻辑。

  1. 有时,为了业务独立快速迭代,会独立逻辑,因为我们预判一直演化下去最终可能会产生两份完全不同的代码。

  2. 有时,虽然业务逻辑看上去不太一样,但是我们会收口到一起,尽量复用一份逻辑,因为我们预判发展下去会产生更多的复用逻辑。

到底是分还是合?哪些要复用?哪些要独立发展?显然与我们的预判息息相关。总的来说,离“业务”越近的地方,应该越尽可能独立,离“平台”越近的地方,应该近可能复用,代码是否稳定是重要的判断因素。

87b06f0c4fa7875d4fee669cfad695fd.png

订单管理系统中复用独立的不同场景

  领域划分

在VSEF里面,淡化了领域的概念,因为认为领域都在网关服务里面,而系统本身的领域,则分散在能力里面,对外整体作为一个领域。

领域中,关于领域的划分是很非常挑战的,相关思考,在我们的能力划分,目录的设计等方面都可以借鉴:

  1. 思想一:看核心管理数据载体。

    我们可以认为一个域实际上是一个或多个实体对象的信息集合,并对所管理的实体对象的生命周期进行管理。

  2. 思想二:确定核心白名单,其它可扩展。

    既然无法维护一个涵盖整个企业的统一模型,那就不要再受到这种思路的限制。通过预先决定什么应该统一,并实际认识到什么不能统一,我们就能够创建一个清晰的、共同的视图,然后需要用一种方式来标记出不同模型之间的边界和关系。

此外,我们常常会发现划分调整的背后事务:

  1. 调整的内容:其实是匹配生产关系。

  2. 调整的原则:追求职责的内聚,精细化分工。

  3. 不断调整的原因:业务在发展,内聚的标准需也要与时俱进。

从关联的角度看,往往我们看组织架构,就能看到领域的边界,核心原因还是组织架构也是要适应生产关系,follow更优解的结构,是相辅相成的,也就能互相窥探。

c378ea6ed32695a67c8897a822c5b791.png

领域的划分应该尽可能正交

  逻辑模型

在数据库操作的时候,在数据服务的路口,选择逻辑模型是天然的一个选择。比如属性,在逻辑模型中可能是一个map,在DO中是一个String,如果使用DO流转,就会非常不方便。

这里还可以探讨的是,逻辑模型应该如何抽象?要不要聚合多个表。最容易理解、维护以及发展的情况,当然是领域模型与数据模型能够形成1:1的维护关系。但是由于底层数据很难变动,而理解和业务发展是与时俱进的,当我们持续设计的时候,逻辑模型势必会不太一样。常见的一些场景有:

  1. 一个逻辑模型维护一个表:这个是比较简单的场景,一个逻辑模型直接负责一个表,比较干净易理解。

  2. 多个逻辑模型共享一个表:这个是因为表中记录的数据比较多,但是实际上有不同的领域数据存的冗余储,比如交易订单上的营销优惠信息、资金信息、物流信息等。

  3. 一个逻辑模型维护多个表:当我们对原始的领域重新划分,又不能重新建立表结构的时候,对于较大的一些域,往往数据来自多个表,这时候就会遇到这样的情况,一个领域模型要从多个数据库表里面聚合数据。

  4. 聚合逻辑模型的复杂情况:这个在DDD里面主要是聚合根这样聚合了多个实体的情况。举个例子来说,资金单有支付单、垂直表、还有多个支付单,这样的聚合关系就更加复杂了。

34bd49994f7ec6ae91524cb47c3e2e00.png

逻辑模型与物理模型映射场景

  模型策略

当我们获得外部对象的时候,选择follow,还是选择拷贝,还是选择抽象定义。这里有不同的策略:

  1. 共享内核 shared kernel :通常是共享核心领域或者是一组通用子领域。

  2. 客户/供应商关系 customer/supplier:上下游关系。不同客户需要协商来平衡,上游团队需要有自动测试套件。

  3. 跟随者模式 conformist:单方面跟随模式。上游的设计质量较好,容易兼容,可以采用严格遵循上游团队的模型。

  4. 防腐层 anticorruption layer:防腐层、隔离层,使用 facade 等模式,减少其它系统变动对本系统的影响。

  5. 各行其道 separate way:声明一个与其它上下文毫无关联的限界上下文,使开发人员能够在这个小范围内找到简单、专用的解决方案。

d34ed6d22b9bb7429498ace645aae919.png

战略设计策略

  扩展机制

如果只是基于模式扩展,可能采用一些局部的策略模式就可以了。但是如果期望服务多个业务,且期望隔离业务定制,那么就需要提供一些插件包,隔离权责出来。

更为主要的是,不同的插件包,在运行态如何执行,如果有多个满足条件,该如何定义优先级。这里逃不掉的是一个插件身份的定义。这个定义可以有很多的玩法,不同的业务组织可能理解不一,这可能是扩展机制的核心难题。

每个层次都可以设计自己的扩展机制

  1. 无论是扩展框架TMF的迭代,还是后面星环体系的提出,一个重要的目的是为了解决“业务和平台的隔离”,这也是开闭原则的重要体现。核心逻辑应该由比较熟悉的平台人员进行控制,应该尽量通用,较少修改;扩展逻辑应该由业务开发人员理解,应该尽量灵活,便于调整。

  2. 往系统内部看,其实还有很多域能力的扩展,比如:支付的时候可以走直连支付宝,也可以经过支付系统链接到微信等非支付宝渠道。这样的扩展,也是开闭原则的体现,只是离核心流程更近,影响面更大。

  3. 往扩展外部看,即使是业务APP包、产品包等插件内部,还是可能会服务多个行业、多个场景,可能有很多的再次路由与扩展。比如:淘系要服务很多行业,服饰、家电等,不同业务定制也不太一样,往往会用一些策略、责任链的扩展模式。

7818302c0a457fa627c7aac31490dff8.png

“聚类”是插件的基因

c28859e190e9c0874b724934bf7e0a73.png

组件选取

不同业务组织,在进行相关主题的讨论与思考后,会定制一套适合自己的发展结构。后面在快速启动的时候,期望有一些复用的组件。这部分组件,分为外部市场的组件,和自己建立的组件。

组件分为市场已有的组件,还有自己期望自建的组件,这里VSEF框架中会提供一些概念组件。

  市场组件

市场组件应该被优先选择,因为那个是服务更多场景的,有更强的包容性。当然,如果系统比较小除外。如果定位比较大,那么还是建议及早引入,随着流量的增加,理解也不断增加,越到后面,越能巧妙应用。

交易系统中使用的一些组件举例如下:

  1. 协议化组件:Ultronage、Astore

  2. 流程编排组件:Tbbpm、SmartEngine

  3. 扩展组件:Lattice、TMF

  4. 配置化组件:Newton

1ead5a8e7eec48241188b4eb592783df.png

市场组件的一些案例

  VSEF组件

有些组件功能比较小,甚至可以作为工具类Util, 但是如果应用内有多个应用Application,想抽象复用的话,可以独立出来单独的组件,进行统一设计,避免重复劳动。

可能的一些组件设计有:

  1. 元数据组件:Metadata , 期望能够生成知识索引数据。

  2. 日志组件:CommonLog,期望能够统一格式,方便统一监控、清理。

  3. 预热组件:Preheat,期望能够抽象接口预热方式,便于预热操作。

  4. 适配器组件:Adapter,一些市场组件的抽象包装,快速集成。

  5. 扩展组件:Extension,简单扩展组件,解决系统扩展性问题,且不那么得重。

32b04705909524e35b8154a322d9d214.png

VSEF组件的一些案例

14377958e63b716e79206a94dcfa0f63.png

总结

本文介绍了一些简洁架构VSEF的一些框架结构理解,并且抛出了一些演化的主题,这些主题的不同思考会让系统发展成不同的风格,实际也是应用定位的必然结果。最后介绍了一些组件的部分,这个部分应该是水到渠成的结果,而不应该是事先预设的标准。

aa86d5c3736710c5543fa3738fd37abe.png

团队介绍

我们是交易平台-平台产品服务团队。团队主要从事交易链路交付工作,在交付工作中,抽象和建设横向产品能力(如:预售、电子凭证等),团队关注业务架构、DDD等理论与实践,致力于高效、稳定地实现业务接入,并抽象赋能。

¤ 拓展阅读 ¤

3DXR技术 | 终端技术 | 音视频技术

服务端技术 | 技术质量 | 数据算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/243374.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

「Leetcode」滑动窗口—长度最小的子数组

💻文章目录 📄题目✏️题目解析 & 思路📓总结 📄题目 209. 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, …,…

小航助学2023年9月电子学会Scratch四级真题(含题库答题软件账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统(含题库答题软件账号) 单选题3.00分 删除编辑附件图文 答案:A 第1题角色为一个紫色圆圈,运行程序后,舞台上的图案是?( ) A…

Android 动画 Lottie 如何使用

Android 动画 Lottie 如何使用 一、简介 Lottie 是Airbnb开源的一个面向 iOS、Android、React Native 的动画库,能分析 Adobe After Effects 导出的动画,并且能让原生 App 像使用静态素材一样使用这些动画,完美实现动画效果。 二、Lottie动…

RRC下的NAS层

无线资源控制(Radio Resource Control,RRC),又称为无线资源管理(RRM)或者无线资源分配(RRA),是指通过一定的策略和手段进行无线资源管理、控制和调度,在满足服…

12.13_黑马数据结构与算法笔记Java

目录 098 堆 heapify 3 099 堆 增删替换 100 堆 e01 堆排序 100 堆e02 求数组第k大元素 100 堆e03 求数据流第k大元素 100 堆e04 求数据流中位数1 100 堆e04 求数据流中位数2 100 堆e04 求数据流中位数3 101 二叉树 概述 102 二叉树 深度优先遍历 103 二叉树 前中后…

人工智能导论习题集(2)

第三章:确定性推理 题1题2题3题4题5题6 题1 题2 题3 题4 题5 题6

Docker容器:docker推送镜像至Harbor

目录 1、Harbor创建项目 2、进入test项目,查看推送命令 3、在docker服务器上准备一个镜像 4、修改docker客户端配置 5、重启docker服务 6、docker登录Harbor 7、docker镜像推送到Harbor 1、Harbor创建项目 2、进入test项目,查看推送命令 3、在dock…

薅github的羊毛-用pages建自己的博客或资源站 - 博客工具 - 2/2

笔者调研了好多个静态博客工具,最后锁定Hexo了,但不等于其他博客不行。我只吐槽两个 Hugo - 难用Gridea - 简直就是骗钱的,我交钱用不了 theme没有链接,同步也同步不了,估计以前是可以,现在经营不下去&…

JUC并发编程 04——Java内存模型之JMM

一.CPU 缓存模型 为什么要弄一个 CPU 高速缓存呢? 类比我们开发网站后台系统使用的缓存(比如 Redis)是为了解决程序处理速度和访问常规关系型数据库速度不对等的问题。 CPU 缓存则是为了解决 CPU 处理速度和内存处理速度不对等的问题。 我们…

MDK 生成二进制bin文件 设置 任意路径

第一步:找到魔法, 第二步:拷贝语法到Run#1 : fromelf.exe --bin -o "$LL.bin" "#L" 第三步:点击Ok 第四步:重新编译即可生成bin文件

自炫锁2-b

1. 自旋锁 自旋锁也是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。 无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说&…

CGAL的3D网格生成

1、介绍 该软件包致力于生成离散三维域的各向同性简化网格。要网格化的域是三维空间的子集,需要有界。域可以连接或由多个组件组成和/或细分为几个子域。 边界曲面和细分曲面是平滑曲面或分段平滑曲面,由平面或曲面面片形成。表面可能表现出一维特征&…

TCP/IP详解——ARP 协议

文章目录 一、ARP 协议1. ARP 数据包格式2. ARP 工作过程3. ARP 缓存4. ARP 请求5. ARP 响应6. ARP 代理7. ARP 探测IP冲突8. ARP 协议抓包分析9. ARP 断网攻击10. 总结 一、ARP 协议 ARP(Address Resolution Protocol)协议工作在网络层和数据链路层之间…

浅谈 USB Bulk 深入浅出 (3) - USB Bulk 装置传输的注意事项

来源:大大通 作者:冷氣團 1 USB Bulk 是什么 USB 是即插即用使用差动信号的装置界面,是以 端点 ( Endpoint ),做为传输装置的输出入端,透过不同的端点 ( Endpoint ) 和模式,来进行与装置的沟通&#xff…

WWW 指南-万维网联盟(World Wide Web)

WWW - 万维网联盟 WWW通常称为网络。 web是一个世界各地的计算机网络。 电脑在Web上使用标准语言沟通。 万维网联盟(W3C)制定了Web标准 什么是WWW? WWW 代表 World Wide Web(万维网)万维网常常被称为 网络网络是世界各地的计算机网络网络中…

nestjs守卫/全局守卫校验jwt

一、守卫 目标 部分接口需要用户登录后才可以访问,用户登录后可以颁发 jwt_token 给前端,前端在调用需要鉴权的接口,需要在请求头添加 jwt_token,后端校验通过才能继续访问,否则返回403无权访问 创建守卫 anth 安装…

java.lang.NegativeArraySizeException

构建maven项目时发生的异常 maven-resources-production:gci-system-start:java.lang.NegativeArraySizeException:-1972174848解决方案 先将 target 目录删除,然后重新构建项目即可

【从零开始学习JVM | 第九篇】了解 常见垃圾回收器

前言: 垃圾回收器(Garbage Collector)是现代编程语言中的一项重要技术,它提供了自动内存管理的机制,极大地简化了开发人员对内存分配和释放的繁琐工作。通过垃圾回收器,我们能够更高效地利用计算机的内存资…

基于pandoraNext使用chatgpt4

1.登陆GitHub 获取pandoraNext项目GitHub - pandora-next/deploy: Pandora Cloud Pandora Server Shared Chat BackendAPI Proxy Chat2API Signup Free PandoraNext. New GPTs(Gizmo) UI, All in one! 在release中选择相应版本操作系统的安装包进行下载 2.获取license_…

【OS】操作系统总复习笔记

操作系统总复习 文章目录 操作系统总复习一、考试题型1. 论述分析题2. 计算题3. 应用题 二、操作系统引论(第1章)2.1 操作系统的发展过程2.2 操作系统定义2.3 操作系统的基本特性2.3.1 并发2.3.2 共享2.3.3 虚拟2.3.4 异步 2.4 OS的功能2.5 OS结构2.5 习…