《从单体应用到微服务》读后感_第1页
《从单体应用到微服务》读后感_第2页
《从单体应用到微服务》读后感_第3页
《从单体应用到微服务》读后感_第4页
《从单体应用到微服务》读后感_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、从单体应用到微服务读后感目标:共同学习、共同进步、告别码农,成为受人敬仰的、有态度的程序猿。拒绝不知其所以然的复制粘贴、拒绝人云亦云。用最严谨的态度、最专业的方法、最可靠的知识来源,探究技术内幕,死磕到底!内容简介原书名字是Monolith To Microservices,是大神Sam Newman的新书,目前还没有中文版本。原本是想写一个简短的读后感的,但是写着写着,发现书中的内容真的是太经典了,浅尝辄止的描述完全不能体现本书的价值。于是就改成了用我自己的语言对书中每一章的内容进行了精炼。因此这个读后感也可以作为原书的精简版来看,只不过用的是我自己的语言总结的。也是由于这个原因,这篇文章越

2、写字数越多,最后接近三万字,花费的时间也很多。为了便于阅读,分成4部分来发。注:本文中的图片截自原书第一章、微服务介绍什么是微服务应用?微服务是围绕一个业务领域建模的可独立部署的服务。通过网络彼此交互。微服务是一种SOA架构,并且它是技术不可知论的,即:微服务并不要求使用特定的技术。这点需要重点强强调下,因为很多人采用微服务都是技术驱动的,这种认识不是非常合适。微服务通过网络端点互相访问,这让微服务具有分布式系统的特点。下面罗列一些微服务的核心思想:独立可部署性这本书认为微服务最重要的特性就是独立可部署性。这要求微服务在部署自身的时候,不依赖任何其它服务。为了保证独立可部署性,因此需要服务之间

3、松耦合、服务之间使用稳定的协议交互数据。围绕一个业务领域建模传统的单体应用中,我们最常用的架构是分层架构,如将系统分为展示层、业务层和数据层。根据康威定律:任何设计系统的组织,都会产生这样一个设计,即该设计的结构与该组织的沟通结构相一致。因此在分层架构中,不同技术角色的人员被分配在一起工作,如前端组、后端组和DBA组等。这是一种以技术视角设计的架构。在微服务中,则是围绕业务领域的,将一个大的业务领域划分成若干尽可能独立的子域,每个子域自己可以是分层架构的。根据康威逆定律,这样的架构势必也会影响到组织的沟通方式的变化。拥有自己数据的所有权微服务的核心思想之一是不使用共享的数据库,每个服务唯一的拥

4、有自身数据的控制权。这可以让服务决定公开哪些数据和隐藏哪些数据。这进一步要求了微服务之间需要维护稳定的接口协议。对数据的控制会促进服务做到高内聚,而通过隐藏自身数据又可以促进服务间的松耦合。微服务带来的优势微服务带来的优势很多。天生的可独立部署性可以促进系统的伸缩性和鲁棒性,并且可以混合使用多种技术。通过服务和团队的划分,每个服务都是独立演进的,也就是说,所有的服务都可以并行开发,服务的开发团队也将专注于一个特定的业务领域,不受其它业务领域的影响。虽然微服务带来了很多优势,但是这并不代表可以免费的使用微服务。另一方面,微服务的优势中,针对某个方面可能还有其它替代方面,而并非只能使用微服务来获得

5、。因此在应用微服务架构时,非常重要的一点是需要明确自身想从微服务中获得哪些好处。微服务带来的问题计算机的价格越来越低,这让SOA架构广泛的被应用。使用SOA可以将系统分布在多台计算机上。但这带来的挑战是服务之间的网络通信问题。网络连接是不稳定的,尤其是考虑延迟的时候,延迟会让整个系统变得不可预测,除此之外,还需要额外处理网络错误的情况。分布式的部署结构会让一切变得复杂起来。某种意义上说,单体应用也存在一些分布式的场景,例如:数据库在一台服务器上,另一台服务器上的程序从数据库服务器读取数据,而客户端使用一台电脑访问程序获取数据。在这个场景中已经出现了3台电脑间的网络通信。单体应用和微服务在分布式

6、上的差别主要在分布的程度上,微服务会使用更多的主机、更多的网络通信。开始的时候,微服务的规模较小,问题可能看起来并不十分严重,但随着微服务规模的逐渐增多,出现问题的频率和难度也会逐步上升。为了解决微服务带来的分布式问题,将会花费很多的真金白银。这也是在打算使用微服务架构时需要考虑的一点:是否值得?用户界面使用微服务架构的一个误区是只对服务端程序进行微服务架构,而依然采用单体应用来作为展示层提供UI访问。单体的展示层使得从用户视角来看,服务无法独立的发布,这是不正确的。根据上面围绕业务领域建模中讲述的,每个微服务都应该负责自身业务领域的所有分层,包括:UI层、业务层和数据层。因此在用户界面上也应

7、和微服务的拆分保持一致。这可能需要一些专门的技术来实现,如:微前端。技术微服务是一个技术不可知论的架构,因此,如何实现微服务并没有技术上的要求。只要服务间基于网络可以互相通信就可以了,不必使用K8S、Docker、公有云等也可以实现微服务。在编程语言上也可以使用任何一种语言进行实现。但是微服务是非常复杂的,主要是因为它带来的分布式问题,这些问题可能是之前使用单体应用从来没遇到过的问题。因此,不应盲目的跟风新技术,应该使用自己最熟悉的技术来实现微服务应用。大小微服务应该有多大,这应该是最常被讨论的问题。要解答这个问题,首先需要定义大小的衡量标准。常用的衡量标准如代码行数,但这在微服务中是没有意义

8、的,因为微服务是技术不可知论的,而使用不同的编程语言实现同样的逻辑,代码行数差别是非常大的。书中引述了一位微服务专家对微服务大小的建议是:“尽可能小的接口”。实际上,微服务的大小在不同的上下文和人群中的感受是不一样的,因此不必过于纠结微服务大小的问题。在考虑大小的时候,最应该考虑的是以下两个问题:1)你可以处理多少个服务。随着服务的增多,系统也会变得更加复杂,需要团队学习更多的知识来应对;2)服务的边界如何定义。不合适的边界划分最终可能会导致恐怖的耦合混乱。所有权传统的IT企业采用职能型的组织架构,软件的生命周期分别由不同的部门负责,如需求部门负责采集用户需求,开发部门收到需求部门输出的需求文

9、档后进行软件开发。这种方式如下图所示:图片现在越来越多的企业将组织方式调整为矩阵型,提高沟通效率,加快开发速度。而微服务架构是围绕业务领域建模的,这非常适合矩阵型组织的沟通方式。组织可以使用微服务所代表的业务领域对组织进行划分,根据微服务的特性,团队之间也会减少跨团队的共享、最小化发布时的竞争。如下图所示:单体应用什么是单体应用呢?单体应用的特征是系统的所有功能共同组成一个唯一的部署单元。通常单体应用分为三类:单进程单体应用模块化的单体应用分布式的单体应用:分布式的单体应用由多个服务组成,但是这些服务必须同时部署。这种方式拥有分布式系统和单体系统的所有缺点,并且对于单纯的分布式系统和单体系统而

10、言没有任何优势。所有的服务都混乱的耦合在一起。一个服务的变更就可能导致系统不可用。第三方黑盒系统:我们可以将第三方的系统都视为单体应用。单体系统的挑战单体应用由于实现和部署耦合,更加的脆弱。如果有很多人在一起工作,可能会引发混乱。一些开发人员可能同时修改同一段代码,团队之间的工作互相依赖。微服务提供的概念边界会更加容易地解决这些问题。单体系统的优势单体应用的部署拓扑比分布式系统简单的多,这样会让开发流程更加简单;并且在监控、排错和系统测试方面也要简单许多;单体系统内部的代码可以更简单的复用,这在微服务中,可能意味着代码拷贝或者共享代码等权衡。很多人将单体系统视作老土的架构,视为应该被抛弃的架构

11、,这是绝对是不正确的观点。内聚和耦合内聚的目的是将相关的代码放在一起,一起应对变更;而耦合则表示对一个部分的修改会对其它部分造成影响。高内聚、低耦合会让架构保持稳定。单体应用通常是高耦合、低内聚的,各种不相关的代码都耦合在一起。当需要代码调整的时候,通常很困难。同时,松耦合在单体应用中实际并不存在,因为任何变动都需要将整个应用一起打包部署。在微服务中,如果要想做的松耦合,一方面是保证自身的修改不需要改变其它部分,另一方面是保证接口的稳定。我们需要谨慎的考虑系统中的耦合,耦合可分为以下4类:实现耦合:这是一种危害最大的耦合类型,但通常比较容易处理。例如A服务的实现依赖于B服务如何实现,当B服务需

12、要修改时,A服务需要同时修改。典型的例子是共享数据库,当A和B共享同一个数据库时,A对数据库的变更会直接影响B。临时耦合:这种耦合发生在运行时,一般发生在分布式环境中的同步调用时。例如A服务要同步地调用B服务获取信息,而B服务此时又需要同步地调用C服务,这就构成一个临时耦合。这里问题是,请求若要成功,这三个服务必须都正常运行并且可以相互调用。解决时可以考虑使用缓存或者异步消息。部署耦合:不管代码是不是模块化的,如果在发布的时候需要打成一个包统一部署,这时就是部署耦合。部署耦合带来的问题一方面是需要协调各个团队的发布计划,另一方面,每次部署都会有风险,越大的部署范围风险也会越大。并且少量的代码更

13、容易实现自动发布。领域耦合:每个微服务都处在一个领域限界上下文中,当它们之间的概念有交互时,就形成了领域耦合。例如服务A中需要理解服务B中的一个领域概念。实际上,服务A中所需要的概念可能与服务B中的不一样,例如仓库服务需要访问订单服务中的订单信息,实际上仓库服务需要的订单信息可能只是订单编号,它不需要理解订单服务中订单信息的全部业务概念。因此,仓库服务应该维护一个在自己限界上下文内的订单信息实体。领域驱动设计前面介绍了我们为什么要围绕业务领域建模。那么具体如何做呢?这就是领域驱动设计(DDD)解决的问题。DDD介绍了一系列的思想来在程序中表示问题域。设计微服务的重要概念有:聚合:聚合是一个自包

14、含的单元,表达了一个实际的业务概念。通常聚合拥有一个生命周期,这会让聚合的实现类似一个状态机。我们需要保证一个业务概念的状态转移完全被包含在一个聚合之中。一个微服务会处理一个或多个聚合的生命周期和数据存储。将一个系统划分成聚合可能需要考虑众多因素,例如:性能问题、实现的难易程度等。这也意味着聚合可能会对聚合进行重新划分。在实际中,事件风暴非常有用。限界上下文:限界上下文通常代表了组织中的一个较大范围的边界。这个边界内有单一的职责。从实现角度来看,一个限界上下文中有一个或多个聚合。这些聚合中的一些可能会对外暴露,另一些则被内部隐藏。将聚合和限界上下文映射成服务聚合和限界上下文都提供了高内聚的单元

15、,并且提供设计良好的接口。聚合涉及一个单一领域概念的自包含状态机,而限界上下文则代表一组相关的聚合。聚合和限界上下文都可以作为微服务的边界。考虑到初期尽量减少服务的数量,建议使用范围更大的限界上下文来作为微服务边界,熟悉后,可以进一步使用聚合拆分。第二章、规划迁移是否应该使用微服务?微服务不应作为一个目标,使用微服务也不会让你获得胜利。采用微服务的决定一定是经过深思熟虑的。从单体应用迁移到微服务应用应该有充分的理由,例如获得当前单体应用不具备的能力。在考虑想微服务架构迁移之前,需要明确三个问题:你希望从微服务中获得什么?除了微服务,还有什么其它的解决方案?你怎么衡量微服务带来的成效?微服务不是

16、免费的,它可能会引起组织系统性的变化,需要引入更多的运维组件,改变现有的开发方式等等。因此需要充分考虑ROI,以判断一个迁移是否值得。微服务带来的好处主要有以下几点,但请注意,带来的这些好处大部分都可以通过其它方式获得。提升团队自治性非常多的企业证明了团队自治带来的好处。自治的团队通常不会很大,确保团队内成员彼此都非常熟悉,自治团队在一个较小的范围内工作。业界有一些关于团队规模的范例,如亚马逊的“两个披萨”模型。如果正确使用团队自治性,会激发团队成员成长并提升效率。当团队拥有微服务的全部控制权,就会提升团队在整个组织中的自治性。自治性不是微服务独有的,有很多方式可以获得自治。团队的自治主要涉及

17、分配给团队的职责,而与使用什么样的架构关系不大。比如可以通过将代码仓库中的一部分授权给一个团队来促进团队的自治。加快上市时间将变更的执行和部署聚焦到各自独立的微服务中,可以做到不用和其它服务协调发布时间,同时多个团队可以并行的处理待办任务列表,这让功能面世的时间大幅度加快。当然,不使用微服务也可以做到加快上市时间。如“优化上线流程”等也会起到一定的效果。通过对现有上线流程的分析,判断是否可以通过调整任务执行的顺序,或者采用并行的方式来加快流程执行的速度。为负载更有效的扩缩每个微服务都可以独立的进行扩缩,这样会更加有效。因为我们只需要扩展对处理当前复杂有瓶颈的部分。当负载降低,可以对这部分再进行

18、缩容。如果不使用微服务,有很多方法可以应对负载升高的情况。最简单的就是使用配置更高的机器。另外,传统的通过多个单体应用的拷贝来进行水平扩展的方案也是非常有效的,虽然它对于数据库的瓶颈没有帮助。提升鲁棒性例如多租户的SaaS系统,这类系统对可用性的要求很高,一旦出现宕机,影响范围将会非常广泛。通过使用微服务,将一个系统根据功能解耦成若干个独立的服务,也就是说,当一个功能出现问题时,不会影响其它服务的功能。这里需要注意的是,微服务提供的鲁棒性不是免费的,并且由于服务部署在不同的机器上,这也会增加调用失败的风险。如果不使用微服务,通过拷贝多个单体应用进行负载均衡也可以有效的提升系统的鲁棒性。另一方面

19、,系统的不稳定通常都是人为的,如果系统存在很多人工的操作,则使用自动化的手段在很大程度上解决问题。扩展开发人员的数量人月神话中提到,只有将工作分割成互不影响的小块,才能够通过增加人数来加快发布进度。微服务通过明确的边界,限制了其自身的范围和对其它服务的依赖。因此可以支持大量的开发人员。仅仅使用微服务通常是不够的,还需要结合团队自治和服务所有权。另一种不使用微服务的方法是实现模块化的单体应用,不同的团队拥有单体中的不同模块。只要它们对外暴露的接口是稳定的,那么就可以独自的演化。拥抱新技术单体应用限制了新技术的使用,因为通常它只使用一种开发语言,使用特定的部署平台、运维系统和一种数据库。而微服务中

20、的每一个独立的服务都可以根据自身的特点进行技术选型。成熟的微服务组织通常会限制可使用的技术栈。在这一点上,单体应用没有太好的办法。什么时候不应该使用微服务?在一些场景中是不适合使用微服务的,如下:不了解的领域:服务边界如果划分有误,则带来的代价可能是非常高昂的,可能会导致服务间的高度耦合,则要比单体应用更加糟糕。如果对业务领域尚不了解,不应盲目的进行服务拆分,而是应该先学习领域知识。初创系统:很多企业在系统初始阶段就会考虑使用微服务架构,但在实际实现时,都会先采用单体应用。微服务对于扩张来说是一个很好的选择,但在初始阶段,功能尚处于试验阶段,会根据用户的需求不断调整。一些功能可能会重写,另一些

21、功能可能会删掉。另一方面,初始阶段的资金有限,应该将关注点放在产品本身上,单体应用易于开发和测试,部署拓扑也非常简单,相比微服务不需要花费太多的资源和精力。通常来说,一个已经存在的“棕域”系统相比一个新的“绿域”系统来说,更加容易拆分。客户自己安装和管理的软件:如果软件打包后分发给客户自行安装和管理,那么不应该使用微服务。因为微服务的安装和运维非常复杂,客户可能没有安装和管理微服务架构应用的能力。没有充分理由的情况下:这个前面也提到过,微服务作为一个分布式系统,使用起来将会面临非常多的挑战,因此,一定是在经过深思熟虑后,确定微服务带来的优点大于缺点时,才可以使用。如何开始微服务?要在组织中推广

22、微服务,首先要做的是让其他人清楚的明白你希望从微服务中获得什么,当他们认同之后,要做的就是探讨如何实现。通常需要先引入一些成熟的模型来帮助组织变革。下面介绍John Kotter的“组织变革八步法”,整个过程如下图所示:创建变革的紧迫感:组织中的好主意有很多,微服务可能只是其中之一。因此需要让大家明白现在就是实现微服务的最佳时机,要做到这点的最佳实践是结合当前组织中的实际场景,结合当前的痛点,而不是干巴巴的说:“我们要使用微服务”,任何时候,微服务都不是目标。创建一个有足够力量的引导联盟:要推动一个变革,一个人是远远不够的。需要在组织中分辨哪些人可以帮助你,这些人可能是同事、领导或者其它部门的

23、相关方,让这些人加入到你的队伍中,让他们成为推动变革的一份子。这可能涉及到包含IT岗位的任何岗位。创建一个愿景和实现策略:愿景说明了你想从变更中获得什么,而策略则说明了你将如何实现变革。策略可能会不断调整,因此微服务不一定是唯一的方式。推广变革愿景:宏大的愿景看起来很棒,但是在推广的时候没人会相信。因此可以在开始的时候分享一个小的愿景。在推广方式上,建议使用面对面的方式,其它方式可以结合使用。赋予员工广泛的行动权力:当你完成了愿景的推广,大家都满怀激动的心情后,接下来会怎样呢?大家可能继续忙各自的工作。在使用微服务的时候围绕已存在的基础设施的流程可能是一个非常实际的问题。例如你需要发布一个新的

24、服务,但是硬件采购的流程非常长。因此需要赋能员工,帮助他们扫清障碍,做他们该做的事情。创建短期成效:如果实现的周期太长,人们可能会丧失对愿景的信心,因此需要将整个周期拆分成很多小的胜利。当使用微服务对功能解耦后,这可能更加容易实现。巩固收益并产生更多变化:当取得一些小胜利后,要趁热打铁。对流程和策略进行继续的优化,寻找如何能够驱动变革继续进行。例如在微服务拆分后,接下来可能意味着对数据库的解耦。将新方式融入文化:随着变革的深入,以及不断对成功或失败经验进行分享,团队会越来越熟悉新的工作方式,最终会形成组织特有的文化沉淀下来。逐步迁移的重要性逐步的迁移有助于在过程中学习微服务,当出现问题的时候,

25、影响的范围也是有限的。把迁移分为多个小步骤,也可以帮助分析每一步的成果,总结每一步的经验教训。也有助于实现上文提到的快速的小胜利。当确定使用微服务的时候,可以先挑选一到两个业务领域,用微服务实现它们,并将它们发布到生产环境,然后观察它工作的怎样。这里列出一些逐步迁移的好处:只有生产环境才算数:只有将拆分好的微服务发布到生产环境在表示这个服务实现完成。因为微服务解耦后会带来很多问题,如:排错、调用链、延迟、级联错误等。很多问题只有在生产环境中才能发现。如果做错了,逐步迁移会使你能够快速定位问题和回滚。变更成本:在向微服务迁移时,会犯很多错误,逐步迁移不会减少犯错误的可能性,但是当错误发生,其造成

26、的成本损失是可控的。可逆和不可逆的决策:有些决策是不可逆的,这意味着一旦它开始执行,就再也无法回到起点了。这类决策需要非常谨慎的评估,运用方法论,长时间的论证。而另一类决策在执行后,如果发现不合适,可以回到初始的地方重新来过,这类决策可以快速指定,并且可以授权给个人或者小的团体。更容易进行实验:调整代码的成本较低,有很多工具可以使用,但是调整数据库的成本就会非常高。高成本的变更的风险也会是很高的,因此最好的办法是进行一些小的实验来观察可能发生的问题,逐步迁移会让这些实验的影响范围是可控的。领域驱动设计接下来我们将讨论如何进行微服务的拆分,使用的思想是领域驱动设计。在使用领域驱动设计建立领域模型

27、后,这个模型可以帮助我们定义服务边界,以及引导我们分辨实现服务的优先级。通过限界上下文之间的依赖关系,对其它限界上下文依赖越少的服务在实现的时候就会越容易,这些也是我们有限选择实现的。实际上,有一些方法可以帮助我们决策,如下:打算走多远?开始的时候,一下子要对系统的整体领域模型都进行分析,往往不知道如何入手,也会让人心生畏惧。其实,在将单体应用解耦的时候,只需要了解足够的关于从什么地方开始解耦的信息就够了。缺少全局的理解确实会带来一些风险,但是开始的时候并不是非常重要,因为开始的时候只需要获取如何进行下一步的信息就可以了,在解耦过程中需要不断结合新的领域只是对领域模型进行重新定义。事件风暴事件

28、风暴可以帮助技术相关方和非技术相关方共同定义一个共享的领域模型。事件风暴是自下而上的,首先参与者一起定义领域事件系统中真实发生的事件。然后用这些事件组成聚合,再将聚合组成限界上下文。事件风暴的输出不仅仅是领域模型,最终要的是对领域模型的一致性理解。因此需要相关方在一起工作,这是使用这个方法最大的挑战。使用模型排序优先级通过分析上下游服务的依赖关系,就可以明白哪些服务相对容易拆分,哪些会更加困难。这可以作为服务实现顺序的排序因素。但需要注意的是,领域模型表达了系统的逻辑概念,虽然从逻辑上看没有依赖,但可能在物理层面存在关系,因此仍然需要在进一步的从实现代码中分析是否存在依赖。另一个决定优先级的因

29、素是业务本身,因为我们需要实现快速的成功,所以需要选择能够实现这个目标的恰当的业务。模型分组在实际选择要实现的服务时,大部分人可能会选择最容易解耦的部分,但我们的另一个关注点是取得快速的成功,这意味着我们应该选择能够为系统带来立竿见影效果的部分,而这些部分通常都是核心业务,可能并不容易拆分。这时我们可以按照难易程度和效果将候选服务进行分组,如下图所示:X轴表示效果,越向右效果越明显。Y轴表示实现的难度,越向上越容易。显然,我们最终应该选择位于图的右上方的候选服务。有时候我们在实现的时候会发现,原本以为简单的服务实际实现起来很困难,反之亦然。这是很正常的,这也意味着需要重新对服务进行排序后选择新

30、的服务进行实现。重新组织团队使架构和组织保持一致是充分发挥微服务架构优势的关键,但这在组织中通常并不容易。下面提出一些对此有帮助的想法:转变结构传统上,IT组织的结构是围绕核心能力的。例如Java开发人员在一起,测试人员在一起,DBA和其它DBA在一起。在开发系统的时候,每个只能团队中的人只完成系统生命周期中的一部分任务。这也导致过程中需要各个部门之间相互协调。在微服务的架构中,每个服务涉及多个软件层次,也会涉及多个职能。因此当今的组织开始向DevOps转变,测试人员不再是一个单独的部门,而是作为发布团队中的一员,和开发团队更紧密的合作。通过将不同职能的人员放在一个发布团队中,授予他们足够的权

31、限,这可以促进他们为服务的发布提供各种帮助。没有范式组织方式没有一个范式可以适合所有企业,它会收到企业环境、工作文化以及具体的人的影响。因此,盲目拷贝别的企业的组织方式是很危险的。其它企业的成功经验可以用来参考,但是要清楚它可能不会在你的场景中成功。做出一个改变如果你不能拷贝其它企业的组织结构,那应该怎么做呢?首先可以先罗列日常涉及的工作和流程,然后将它们和当前企业的组织结构映射起来。然后分析哪些职能需要跨越组织结构来工作,结合愿景重新绘制一个理想的结构图。将两个图进行对比,然后规划迁移方案。改变技能从单体向微服务迁移,需要对组织中原有的能力进行更新。一个有效的方法是,首先罗列出所有需要的能力,然后让员工对自己进行评价,评估自己当前的能力。这里需要重点强调的是,自我评价是非公开

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论