首页 文章 精选 留言 我的

精选列表

搜索[公有云],共10000篇文章
优秀的个人博客,低调大师

京东云开发者|探寻软件架构的本质,到底什么是架构?

不论是开发人员还是架构师,我们都一直在跟软件系统打交道,架构是在工作中出现最频繁的术语之一。那么,到底什么是架构?你可能有自己的答案,也有可能没有答案。对“架构”的理解需要我们不断在实践中思考、归纳、演绎,形成自己的认知。 1 到底什么是软件架构 ? 定义 ”架构是什么“ 是件非常困难的事情,不同的组织对于软件架构有不同的定义,每个人心中也有自身对于系统架构定义的认知。就好比我们无法百分之百表述模型而只能产出模型不同维度的视图,对架构进行完备的定义是不可能的。 “道可道,非常道。名可名,非常名”。 行业内不同的组织和个人从不同的视角对 “什么是架构” 进行了定义或阐述。 IEEE 关于架构的定义 the fundamental organizationof a system, embodied in its components, their relationshipsto each other and the environment, and the principlesgoverning its design and evolution --ANSI/IEEE 将系统架构定义为:架构是系统组织结构+组件及联系(组件间以及组件和环境之间)+原则的组合。通过图形化的形式表述该架构定义如下图所示,这是一个非常简洁、概念清晰的定义,其言简意赅的表达了架构的几个核心要素: •系统的组织:表达系统的宏观结构 •组件及联系:组件化的思维,同时突出了环境要素。组件表达了系统的模块化,组件相互之间及组件与环境之间的关联表达元素间的相互作用。 •原则:用于指导设计和系统演进的原则 大师Martin Fowler对于架构的定义有着更加简洁的抽象,Martin Fowler 认为软件架构是:重要并且难以改变的决策。架构设计是关于权衡的艺术,架构设计过程中充满了各种各样的决策,这些决策也终将反应系统架构。 Software Architecture = Importantand hardto change decisions -- Martin Fowler 而Ralph Johnson则对架构有更加 “泛化” 的定义:软件架构就是重要的东西,不论它是什么! The software architecutre is the important stuff! Whatever it is ! -- Ralph Johnson 以上的定义从高层抽象视角对什么是架构给予了自己的回答,相比之下,Neil Ford 从架构组成元素入手,从更偏向实践的角度对架构进行了阐述。核心思想是软件系统的架构包括以下组合元素: •结构:应用系统所选择的架构风格,比如微服务架构、单体架构还是SOA等 •架构属性:系统的非功能性属性,比如性能、可用性、可维护性等 •架构决策:系统设计过程中重要的架构决策 •设计原则:设计过程中的指导性原则 结构 结构是系统架构的重要组成部分,其从宏观上表述了系统的结构组成。架构设计的核心任务之一是为系统选择合适的架构风格。比如,架构师基于上下文的权衡,可以选择模块化单体架构风格,也可以选择微服务架构风格。 架构属性 架构属性亦称质量属性,或非功能属性,通常表示系统需要具备或满足的某种 “能力”,比如高性能、可扩展性、弹性、伸缩性、容错性、可测试性、可维护性等等。架构设计的目标需要关注系统需要满足的架构属性,架构最终要体现对架构属性支持的相关架构决策。架构属性众多,系统需要关注的是这些架构属性的子集,具体的某次特定的架构设计所需要关注的架构属性需要依据问题域的上下文而具体分析。同时,不同的架构属性间可能存在冲突,这种情况同样需要架构师的权衡和决策。 架构决策 架构决策是系统架构设计过程中对解决方案的选择,其描述了系统必须遵循的规则。架构决策随着权衡分析而自然存在,其是系统架构设计的重要维度之一。并不是所有的决策都是架构决策,架构决策应该关注对系统有重要影响的部分。比如对架构风格的选择对系统存在重要影响,其改变的成本较高,理当属于架构决策的范畴。比较典型架构决策包括但不限于: •直接影响高优先级的架构属性 •修改对外接口:对外提供的接口修改往往需要进行充分影响分析 •引入或者移除依赖:依赖的加入和移除往往标示着组件能力的引进和废弃 •改变系统的通用结构:工程结构是应用架构的重要维度之一 •迫使研发人员改变开发方式 •接受战略性技术债:重构影响较大的技术债往往对现有系统会有较大影响 注:架构决策建议以轻量级的文档化形式进行记录,参考文章 《轻量级的架构决策记录机制》一文 设计原则 设计原则与架构决策不同,其本质区别是:设计原则是一种指导,而非强制的规则。架构决策需要遵守,设计原则提供参考性指引。 比如,设计原则可能是:在可能的情况下,跨系统间的通信尽可能使用异步消息机制以提高性能和降低耦合。 以上对架构的定义各有特点: •IEEE定义更加结构化和规范化 •Martin Fowler的定义侧重架构决策的重要性 •Ralph Johnson 则更加泛化,突出 “重要” 这一核心因子 •Neil Ford则更具象化 我个人更倾向于Ralph Johnson 对于架构的抽象化定义,简单却不失对架构本质的阐述,这也是我在工作中判断架构边界的准则之一。 2 架构设计的边界 如果你是团队的架构师,你是否有以下困惑: •系统的架构应该设计到什么粒度? •架构设计是否要足够详细以便能直接指导开发人员开展编码工作? 如果你是团队的核心开发人员,你是否 “抱怨” 过: •"架构设计" 太过详细,涵盖了实现的 “细枝末节”,自己除了CRUD没有发挥的空间 •"架构设计" 太过宏观,基于设计方案根本无法指导开发,自己还得重新设计 很多架构师自身对架构和设计的边界缺乏深入认知,相比于对架构边界的缩小,更多时候会出现架构设计边界放大的情况: 架构师把架构设计当作详细的技术方案设计,牢牢把控系统实现的所有细节,产出大量的设计文档,然后交由核心开发人员做代码实现的执行工作。 这种现象会导致如下问题: •压缩了团队核心开发人员的设计发挥空间,不利于其技术水平及认知的提升 •作为架构师你真的能讲所有的细节都Cover住吗?即使耗费巨大精力完成了 “完备” 的设计,来自一线开发所面临的各种场景是否能够提前预知和捕获? •如果需求迭代持续如此,作为核心开发人员多半会有所 “怨言” •作为团队的架构师精力有限,持续的细节输出会耗费巨大精力,而无法关注更加宏观的层面 •....... 以上问题的根源是什么?不能明确架构设计的边界! •架构设计与设计(实现相关)的边界或粒度问题 •团队架构师与开发人员间的职责边界 判断架构边界的前提之一是:明确架构和设计的关系! 所有的架构都是设计,但设计不一定是架构! 从架构的定义看架构设计的边界,选取两个视角: •架构是系统中重要的东西!无论它是什么(之所以重要,是因为改变的成本高) •架构设计涵盖系统中重要的架构决策 所以,架构设计应该涵盖系统中重要的东西,这些 “重要的东西” 可能是: •应用架构风格的选择 •子系统间信息通信的方式 •工程采取的分层以及层间约束 •工程应该遵循的开发规范 •工程引入的三方类库,或者三方框架 •高优先级的架构属性:比如某次需求建设非常关注系统的性能,或者扩展性等架构属性 •其它 "重要的东西" 架构设计涵盖了系统所需的重要的架构决策,从宏观层面对系统实现予以指引。而详细的设计则为具体的开发实现提供指导,比如,详细的E-R图设计、具体的代码级别的模式选择、某个组件的具体实现等等。 架构不是一成不变,需要持续演进,而实现相关的设计也可能在项目进行中持续变化,因此,二者不能完全割裂,而是需要在实现过程中进行双向反馈: •架构设计信息要高效的同步至开发人员 •实现过程中的变更同样也要回向反馈至架构,以便对架构设计进行调整 在进行架构边界判定时要注意一个至关重要的因子:上下文!!!以上的判断准则必须要给定的上下文中才有价值。 比如:实现过程中大家经常会适用一些设计模式,例如策略模式。那么,这种设计模式的选择是属于架构设计还是详细的实现设计?答案就是:It depends!!! 具体情况,具体分析。 如果当前上下文,我们非常关注系统的扩展性,该架构属性是我们高优先级的架构属性,那么,核心模块的策略模式的应用可以看作是架构设计的范畴。而如果上下文中扩展性不是我们关注的高优先级的架构属性,相比我们更关注性能,那么,这种代码级的设计模式选择应该属于架构设计的范畴之外了,而需要划分到实现设计层面,交由核心开发自主决定。 3 架构模式(Patterns)与架构风格(Styles) 架构模式和架构风格是极容易混淆的两个概念,很多开发人员将其理解为同一事物,而实际上二者有本质区别。 •架构风格是系统设计的顶层抽象,从宏观视角表述我们的系统组成。更进一步,架构风格聚焦于系统的分层、模块以及交互形式。 •架构模式聚焦于对重复出现问题提供解决方案 二者概念不同,并不存在冲突,其联系如下图所示: •架构模式可以应用于架构风格,在同一架构风格上下文内可以应用一或多种架构模式 •架构风格可以组合以产生新的架构风格 比较典型的例子是CQRS:CQRS本身是一种模式,将命令和查询的职责在不同维度进行分离。该模式我们可以在单体架构风格中使用,也可以在微服务架构风格中使用,当然也可以在SOA架构风格中使用。 4 为什么要做架构设计 ? 至于 “为什么要做架构设计” 也是一个古老且频繁出现的问题,有太多的文章阐述为社么要架构设计:有的宏观,有的具体,有的“务实”,有的“务虚”。我把这个问题作为一个独立章节阐述,并不是想进行大篇幅的论述,只是想突出它的重要性,这个问题值得耗费一些精力去深入理解其背后的原因。但,在此不做展开过多说明,通过一句话来进行概括: 之所以要进行架构设计,是因为:重要 ! •做,收益高 •不做,成本高 5 开发人员和架构师的知识模型 作为开发人员,更加关注知识的深度,以便有足够的知识储备满足工作需要。开发人员在职业生涯的早期,应该关注于自身知识储备的增长,并保持技术深度。 作为架构师,之所以技术的广度比深度更重要,是因为架构师的重要职责之一是进行架构决策。系统架构设计是关于权衡的艺术,在特定的问题域上下文下,架构师需要在诸多可行的解决方案间进行权衡和决策,这也对其技术广度提出了要求。开发人员成长为架构师,应该更加关注知识的广度,并在几个特定领域深耕,以便有足够的知识支撑架构决策。 虽然开发人员和架构师在知识域的关注点上存在差异,但在认知层面都可以统一到Bloom认知层次模型。该模型将认知层次划分为逐步递进的六个层次: •识记:识别和回溯事实性知识 •理解:理解事实的内涵 •应用:将事实、规则、概念、思想加以应用 •分析:将信息分解、关联、区分、实验、测试 •评估:将信息或思想的价值进行评价 •创造:整合不同的信息形成新的知识体系 不论是架构师还是开发人员,Bloom认知层次模型都适用。通过不断的学习扩展自身的知识体系,在识记、理解和应用的同时,要持续的培养分析、评估和创造的能力,逐步向高层次的认知水平提升。 但需要注意的是:知识不等于认知,避免陷入知识学习的陷阱。知识是无限的,没有人能够以有限的精力去学习无限的知识。不论是开发人员还是架构师,又或者其他角色,不应该只将精力投入在知识边界的扩充,而应该注重从知识到认知提升的转变。 吾生也有涯,而知也无涯。以有涯随无涯,殆矣!已而为知者,殆而已矣! ----《庄子》 格物以致知,对表象不断的归纳、演绎直至事物的本象,探寻事物背后的规律,建立更高层的认知。这种认知层次由下及上的跃升有两种方式: •悟:由内向外,通过不断积累、持续思考,由量变到质变,直至 “开悟” •破:自外向内,高层次或不同的思想输入碰撞,加速认知层次的突破 为学日益,为道日损。损之又损,以⾄于⽆为。⽆为⽽⽆不为。 --《道德经》 6 结语 对架构定义的探讨实际上是一种朴素的 “格物” 的过程,每个人都应该寻找自己的答案。跳脱对架构定义探讨的视野,大家的工作和学习何尝不是如此呢 ?!大道至简,殊途同归,格物致知,与君共勉! 作者:倪新明

优秀的个人博客,低调大师

浪潮云溪分布式数据库协议代码解析(2)

- 数据请求阶段 - Part 1 - 简单查询 1.客户端发送Query (‘Q’)消息给服务端,包含了一条字符串类型的SQL语句。 func(cn *conn) query(query string, args []driver.Value)(_ *rows, err error){ ... // Check to see if we can use the "simpleQuery"interface, which is // *much* faster than going through prepare/exec iflen(args)==0{ return cn.simpleQuery(query) } ...} 2.服务端收到Query消息,解析SQL语句,生成抽象语法树(AST),并传给执行器执行,获得结果。 func(c *conn) serveImpl( ctx context.Context, draining func()bool, sqlServer *sql.Server, reserved mon.BoundAccount, stopper *stop.Stopper,)error{ ...Loop: for{ typ, n, err = c.readBuf.ReadTypedMsg(&c.rd) if err !=nil{ break Loop } ... switch typ { case pgwirebase.ClientMsgSimpleQuery: ... case pgwirebase.ClientMsgExecute: ... case pgwirebase.ClientMsgParse: ... case pgwirebase.ClientMsgDescribe: ... case pgwirebase.ClientMsgBind: ... case pgwirebase.ClientMsgSync: ... } } ...} 3.服务端根据SQL结果,首先发送RowDescription(B:‘T’)消息,包含列的数量,列名,列的类型等参数。​​​​​​​ func(c *conn) writeRowDescription( ctx context.Context, columns []sqlbase.ResultColumn, formatCodes []pgwirebase.FormatCode, w io.Writer,)error{ c.msgBuilder.initMsg(pgwirebase.ServerMsgRowDescription) c.msgBuilder.putInt16(int16(len(columns))) for i, column :=range columns { ... c.msgBuilder.writeTerminatedString(column.Name) ... c.msgBuilder.putInt32(0)//Table OID (optional). c.msgBuilder.putInt16(0)//Column attribute ID (optional). c.msgBuilder.putInt32(int32(typ.oid)) c.msgBuilder.putInt16(int16(typ.size)) ... } ...} 4. RowDescription消息后面将跟着多个DataRow(B:‘D’)消息,每个DataRow消息包含一行的数据。 func(c *conn) bufferRow( ctx context.Context, row tree.Datums, formatCodes []pgwirebase.FormatCode, convsessiondata.DataConversionConfig, types []*types.T,){ c.msgBuilder.initMsg(pgwirebase.ServerMsgDataRow) c.msgBuilder.putInt16(int16(len(row))) for i, col :=range row { ... switch fmtCode { case pgwirebase.FormatText: c.msgBuilder.writeTextDatum(ctx, col, conv, types[i]) case pgwirebase.FormatBinary: c.msgBuilder.writeBinaryDatum(ctx, col, conv.Location, types[i]) ... } if err := c.msgBuilder.finishMsg(&c.writerState.buf); err !=nil{ panic(fmt.Sprintf("unexpected err from buffer: %s", err)) }} 5.发送CommandComplete(B:‘C’)消息表示这个SQL请求执行结束了。 6.服务端发送ReadyForQuery(‘Z’),通知客户端可以发送下一条SQL请求了。 func(r *commandResult) Close(ctx context.Context, t sql.TransactionStatusIndicator){ ... switch r.typ { case commandComplete: tag := cookTag( r.cmdCompleteTag, r.conn.writerState.tagBuf[:0], r.stmtType, r.rowsAffected, ) r.conn.bufferCommandComplete(tag) case parseComplete: r.conn.bufferParseComplete() case bindComplete: r.conn.bufferBindComplete() case closeComplete: r.conn.bufferCloseComplete() case readyForQuery: r.conn.bufferReadyForQuery(byte(t)) // The error is saved on conn.err. _ /* err */= r.conn.Flush(r.pos) ... } ...} 7.客户端根据接受SQL请求的结果。 func(cn *conn) simpleQuery(q string)(res *rows, err error){ b := cn.writeBuf('Q') b.string(q) cn.send(b) for{ t, r := cn.recv1() switch t { case'C','I': ... case'Z': ... case'E': ... case'D': ... case'T': ... } }} Part 2 - 扩展查询 1.客户端发送扩展查询请求,依次发送Parse (F:‘P’), Bind (F:‘B’), Describe (F:‘D’), Execute (F:‘E’), Sync(F:‘S’)消息。 func(cn *conn) query(query string, args []driver.Value)(_ *rows, err error){ ... if cn.binaryParameters { cn.sendBinaryModeQuery(query, args) cn.readParseResponse() cn.readBindResponse() rows :=&rows{cn: cn} rows.rowsHeader = cn.readPortalDescribeResponse() cn.postExecuteWorkaround() return rows,nil } ...} func(cn *conn) sendBinaryModeQuery(query string, args []driver.Value){ b := cn.writeBuf('P') b.byte(0)//unnamed statement b.string(query) b.int16(0) b.next('B') b.int16(0)//unnamed portal and statement cn.sendBinaryParameters(b, args) b.bytes(colFmtDataAllText) b.next('D') b.byte('P') b.byte(0)//unnamed portal b.next('E') b.byte(0) b.int32(0) b.next('S') cn.send(b)} 2.服务端处理扩展查询请求。 3.服务端发送回应消息,ParseComplete (B:‘1’), BindComplete (B:‘2’), ParameterDescription(B:‘t’), CommandComplete (B:‘C’), CloseComplete (B:‘3’), ReadyForQuery (B:‘Z’)。​​​​​​​ func(r *commandResult) Close(ctx context.Context, t sql.TransactionStatusIndicator){ ... switch r.typ { case commandComplete: tag := cookTag( r.cmdCompleteTag, r.conn.writerState.tagBuf[:0], r.stmtType, r.rowsAffected, ) r.conn.bufferCommandComplete(tag) case parseComplete: r.conn.bufferParseComplete() case bindComplete: r.conn.bufferBindComplete() case closeComplete: r.conn.bufferCloseComplete() case readyForQuery: r.conn.bufferReadyForQuery(byte(t)) // The error is saved on conn.err. _ /* err */= r.conn.Flush(r.pos) ... } ...}

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册