1.png

作者 | 张瓅玶(谷朴)  阿里巴巴研究员

**导读:**对于大型的软件系统如互联网分布式应用或企业级软件,为何我们常常会陷入复杂度陷阱?如何识别复杂度增长的因素?在代码开发以及演进的过程中需要遵循哪些原则?本文将分享阿里研究员谷朴关于软件复杂度的思考:什么是复杂度、复杂度是如何产生的以及解决的思路。较长,同学们可收藏后再看。

软件设计和实现的本质是工程师相互通过“写作”来交流一些包含丰富细节的抽象概念并且不断迭代过程。> 另外,如果你的代码生存期一般不超过 6 个月,本文用处不大。

软件架构的核心挑战是快速增长的复杂性

越是大型系统,越需要简单性。

大型系统的本质问题是复杂性问题。互联网软件,是典型的大型系统,如下图所示,数百个甚至更多的微服务相互调用/依赖,组成一个组件数量大、行为复杂、时刻在变动(发布、配置变更)当中的动态的、复杂的系统。而且,软件工程师们常常自嘲,“when things work, nobody knows why”。

2.png
图源:https://divante.com/blog/10-companies-that-implemented-the-microservice-architecture-and-paved-the-way-for-others/

如果我们只是写一段独立代码,不和其他系统交互,往往设计上要求不会很高,代码是否易于使用、易于理解、易于测试和维护,根本不是问题。而一旦遇到大型的软件系统如互联网分布式应用或者企业级软件,我们常常陷入复杂度陷阱,下图 the life of a software engineer 是我很喜欢的一个软件 cartoon,非常形象地展示了复杂度陷阱。

3.png
图源:http://themetapicture.com/the-life-of-a-software-engineer/

作为一个有追求的软件工程师,大家肯定都思考过,我手上的项目,如何避免这种似乎难以避免的复杂度困境?

然而对于这个问题给出答案,却出乎意料的困难:很多的文章都给出了软件架构的设计建议,然后正如软件领域的经典论著《No silver bullet》所说,这个问题没有神奇的解决方案。并不是说那么多的架构文章都没用(其实这么方法多半都有用),只不过,人们很难真正去 follow 这些建议并贯彻下去。为什么?我们还是需要彻底理解这些架构背后的思考和逻辑。所以我觉得有必要从头开始整理这个逻辑:什么是复杂度,复杂度是如何产生的,以及解决的思路。

软件的复杂度为什么会快速增长?

要理解软件复杂度会快速增长的本质原因,需要理解软件是怎么来的。我们首先要回答一个问题,一个大型的软件是建造出来的,还是生长出来的?BUILT vs GROWN,that is the problem.

1. 软件是长出来的,不是建造出来的

软件不是建造出来的,甚至不是设计出来的。软件是长出来的。

这个说法初看上去和我们平时的认识似乎不同,我们常常谈软件架构,架构这个词似乎蕴含了一种建造和设计的意味。然而,对于软件系统来说,我们必须认识到,架构师设计的不是软件的架构,而是软件的基因,而这些基因如何影响软件未来的形态则是难以预测,无法完全控制。

为什么这么说?所谓建造和“生长”差异在哪里?

其实,我们看今天一个复杂的软件系统,确实很像一个复杂的建筑物。但是把软件比作一栋摩天大楼却不是一个好的比喻。原因在于,一个摩天大楼无论多么复杂,都是事先可以根据设计出完整详尽的图纸,按图准确施工,保证质量就能建造出来的。然而现实中的大型软件系统,却不是这么建造出来的。

4.png

例如淘宝由一个单体 PHP 应用,经过 4、5 代架构不断演进,才到今天服务十亿人规模的电商交易平台。支付宝、Google 搜索、Netflix 微服务,都是类似的历程。

是不是一定要经过几代演进才能构建出来大型软件,就不能一次到位吗?如果一个团队离开淘宝,要拉开架势根据淘宝交易的架构重新复制一套,在现实中是不可能实现的:没有哪个创业团队能有那么多资源同时投入这么多组件的开发,也不可能有一开始就朝着超级复杂架构开发而能够成功的实现。

5.png

也就是说,软件的动态“生长”,更像是上图所画的那样,是从一个简单的“结构”生长到复杂的“结构”的过程。伴随着项目本身的发展、研发团队的壮大,系统是个逐渐生长的过程。

2. 大型软件的核心挑战是软件“生长”过程中的理解和维护成本

复杂软件系统最核心的特征是有成百上千的工程师开发和维护的系统(软件的本质是工程师之间用编程语言来沟通抽象和复杂的概念,注意软件的本质不是人和机器沟通)。

如果认同这个定义,设想一下复杂软件是如何产生的:无论最终多么复杂的软件,都要从第一行开始开发。都要从几个核心开始开发,这时架构只能是一个简单的、少量程序员可以维护的系统组成架构。随着项目的成功,再去逐渐细化功能,增加可扩展性,分布式微服务化,增加功能,业务需求也在这个过程中不断产生,系统满足这些业务需求,带来业务的增长。业务增长对于软件系统迭代带来了更多的需求,架构随着适应而演进,投入开发的人员随着业务的成功增加,这样不断迭代,才会演进出几十,几百,甚至几千人同时维护的复杂系统来。

大型软件设计核心要素是控制复杂度。这一点非常有挑战,根本原因在于软件不是机械活动的组合,不能在事先通过精心的“架构设计”规避复杂度失控的风险:相同的架构图/蓝图,可以长出完完全全不同的软件来。大型软件设计和实现的本质是大量的工程师相互通过“写作”来交流一些包含丰富细节的抽象概念并且相互不断迭代的过程。稍有差错,系统复杂度就会失控。

所以说了这么多是要停留在形而上吗?并不是。我们的结论是,软件架构师最重要的工作不是设计软件的结构,而是通过 API,团队设计准则和对细节的关注,控制软件复杂度的增长。

  • 架构师的职责不是试图画出复杂软件的大图。大图好画,靠谱的系统难做。复杂的系统是从一个个简单应用 一点点长出来的;

  • 当我们发现自己的系统问题多多,别怪“当初”设计的人,坑不是一天挖出来的。每一个设计决定都在贡献复杂度。

理解软件复杂度的维度

1. 软件复杂度的两个表现维度:认知负荷与协同成本

我们分析理解了软件复杂度快速增长的原因,下面我们自然希望能解决复杂度快速增长这一看似永恒的难题。但是在此之前,我们还是需要先分析清楚一件事情,复杂度本身是什么?又如何衡量?

代码复杂度是用行数来衡量么?是用类的个数/文件的个数么?深入思考就会意识到,这些表面上的指标并非软件复杂度的核心度量。正如前面所分析的,软件复杂度从根本上说可以说是一个主观指标(先别跳,耐心读下去),说其主观是因为软件复杂度只有在程序员需要更新、维护、排查问题的时候才有意义。一个不需要演进和维护的系统其架构、代码如何关系也就不大了(虽然现实中这种情况很少)。

6.png

既然 “软件设计和实现的本质是工程师相互通过写作来交流一些包含丰富细节的抽象概念并且不断迭代过程” (第三次强调了),那么,复杂度指的是软件中那些让人理解和修改维护的困难程度。相应的,简单性,就是让理解和维护代码更容易的要素。

“The goal of software architecture is to minimize the manpower required to build and maintain the required system.” Robert Martin, Clean Architecture.

因此我们将软件的复杂度分解为两个维度,都和人理解与维护软件的成本相关:

  • 第一,认知负荷 cognitive load :理解软件的接口、设计或者实现所需要的心智负担;

  • 第二,协同成本 Collaboration cost:团队维护软件时需要在协同上额外付出的成本。

我们看到,这两个维度有所区别,但是又相互关联。协同成本高,让软件系统演进速度变慢,效率变差,工作其中的工程师压力增大,而长期难以取得进展,工程师倾向于离开项目,最终造成质量进一步下滑的恶性循环。而认知负荷高的软件模块让程序员难以理解,从而产生两个后果:

  • 维护过程中易于出错,bug 率故障率高;
  • 更大机率 团队人员变化时被抛弃,新成员选择另起炉灶,原有投入被浪费,甚至更高糟糕的是,代码被抛弃但是又无法下线,成为定时炸弹。

2. 影响到认知负荷的因素

认知负荷又可以分解为:

  • 定义新的概念带来认知负荷,而这种认知负荷与概念和物理世界的关联程度相关;

  • 逻辑符合思维习惯程度:正反逻辑差异,逻辑嵌套和独立原子化组合。继承和组装差异。

1)不恰当的逻辑带来的认知成本

看以下案例:

A. Code with too much nesting

response = server.Call(request)if response.GetStatus() == RPC.OK:if response.GetAuthorizedUser():if response.GetEnc() == 'utf-8':if response.GetRows():vals = [ParseRow(r) for r inresponse.GetRows()]avg = sum(vals) / len(vals)return avg, valselse:raise EmptyError()else:raise AuthError('unauthorized')else:raise ValueError('wrong encoding')
else:raise RpcError(response.GetStatus())

B.  Code with less nesting

response = server.Call(request)if response.GetStatus() != RPC.OK:raise RpcError(response.GetStatus())if not response.GetAuthorizedUser():raise ValueError('wrong encoding')if response.GetEnc() != 'utf-8':raise AuthError('unauthorized')if not response.GetRows():raise EmptyError()vals = [ParseRow(r) for r inresponse.GetRows()]
avg = sum(vals) / len(vals)
return avg, vals

比较 A 和 B,逻辑是完全等价的,但是B的逻辑明显更容易理解,自然也更容易在 B 的代码基础上增加功能,且新增的功能很可能也会维持这样一个比较好的状态。

而我们看到 A 的代码,很难理解其逻辑,在维护的过程中,会有更大的概率引入 bug,代码的质量也会持续恶化。

2)模型失配:和现实世界不完全符合的模型带来高认知负荷

软件的模型设计需要符合现实物理世界的认知,否则会带来非常高的认知成本。我遇到过这样一个资源管理系统的设计,设计者从数学角度有一个非常优雅的模型,将资源账号用合约来表达(下图左侧),账户的 balance 可以由过往合约的累计获得,确保数据一致性。但是这样的设计,完全不符合用户的认知,对于用户来说,感受到的应该是账号和交易的概念,而不是带着复杂参数的合约。可以想象这样的设计,其维护成本非常之高。

7.png

3)接口设计不当

以下是一个典型的接口设计不当带来的理解成本。

class BufferBadDesign {explicit Buffer(int size);// Create a buffer with given sized slotsvoid AddSlots(int num);// Expand the slots by `num`// Add a value to the end of stack, and the caller need to// ensure that there is at least one empty slot in the stack before// calling insertvoid Insert(int value);int getNumberOfEmptySlots(); // return the number of empty slots
}

希望我们的团队不会设计出这样的模块。这个问题可以明显看到一个接口设计的不合理带来的维护成本提升:一个 Buffer 的设计暴露了内部内存管理的细节(slot 维护),从而导致在调用最常用接口 “insert” 时存在陷阱:如果不在 insert 前检查空余 slot,这个接口就会有异常行为。

但是从设计角度看,维护底层的 Slot 的逻辑,也外部可见的 buffer 的行为其实并没有关联,而只是一个底层的实现细节。因此更好的设计应该可以简化接口。把 Slot 数量的维护改为内部的实现逻辑细节,不对外暴露。这样也完全消除了因为使用不当带来问题的场景。同时也让接口更易于理解,降低了认知成本。

class Buffer {  explicit Buffer(int size); // Create a buffer with given sized slots  // Add a value to the end of buffer. New slots are added   // if necessary.   void Insert(int value);
}

事实上,当我们发现一个模块在使用时具备如下特点时,一般就是难以理解、容易出错的信号:

  • 一个模块需要调用者使用初始化接口才能正常行为:对于调用者来说,需要调用初始化接口看似不是大的问题,但是这样的模块,带来了多种后患,尤其是当存在多个参数需要设置,相互关联关系复杂时。配置问题应该单独解决(比如通过工厂模式,或者通过单独的配置系统来管理);

  • 一个模块需要调用者使用后做清理/ finalizer 才能正常退出;

  • 一个模块有多种方式让调用者实现完全相同的功能:软件在维护过程中,出现这种状况可能是因为初始设计不当后来修改设计 带来的冗余,也可能是设计原版的缺陷,无论如何这种模块,带着强烈的“坏味道”。

完全避免这些问题很难,但是我们需要在设计中尽最大努力。有时通过文档的解释来弥补这些问题是必要的,但是好的工程师/架构师,应该清醒的意识到,这些都是“坏味道”。

4)一个简单的修改需要在多处更新

简单修改涉及多处更改也是常见的软件维护复杂度因素,而且主要影响的是我们的认知负荷:维护修改代码时需要花费大量的精力确保各处需要修改的地方都被照顾到了。

最简单的情形是代码当中有重复的“常数”,为了修改这个常数,我们需要多处修改代码。程序员也知道如何解决这一问题,例如通过定义个 constant 并处处引用避免 magic number。再例如网页的风格/色彩,每个页面相同配置都重复设置同样的色彩和风格是一种模式,而采用 css 模版则是更加易于维护的架构。这在架构原则中对应了数据归一化原则(Data normalization)。

稍微复杂一些的是类似的逻辑/或者功能被 copy-paste 多次,原因往往是不同的地方需要稍微不同的使用方式,而过去的维护者没有及时 refactor 代码提取公共逻辑(这样做往往需要更多的时间精力),而是省时间情况下选择了 copy-paste。这就是常说的 Don’t repeat yourself 原则:

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

5)命名

软件中的 API、方法、变量的命名,对于理解代码的逻辑、范围非常重要,也是设计者清晰传达意图的关键。然而,在很多的项目里我们没有给 Naming /命名足够的重视。

我们的代码一般会和一些项目关联,但是需要注意的是项目是抽象的,而代码是具体的。项目或者产品可以随意一些命名,如阿里云喜欢用中国古代神话(飞天、伏羲、女娲)命名系统,K8s 也是来自于希腊神话,这些都没有问题。而代码中的 API、变量、方法不能这样命名。

一个不好的例子是前一段我们的 Cluster API 被命名为 Trident API(三叉戟),设想一下代码中的对象叫 Trident 时,我们如何理解在这个对象应该具备的行为?再对比一下 K8s 中的资源:Pod, ReplicaSet, Service, ClusterIP,我们会注意到都是清晰、简单、直接符合其对象特征的命名。名实相符可以很大程度上降低理解该对象的成本。

有人说“Naming is the most difficult part of software engineering[9][10]”,或许也不完全是个玩笑话:Naming 的难度在于对于模型的深入思考和抽象,而这往往确实是很难的。

需要注意的是:

(a)Intention vs what it is

需要避免用“是什么”来命名,要用“for what / intention”。“是什么”来命名是会很容易将实现细节。比如我们用 LeakedBarrel 做 rate limiting,这个类最好叫 RateLimiter,而不是 LeakedBarrel:前者定义了意图(做什么的),后者描述了具体实现,而具体实现可能会变化。再比如 Cache vs FixedSizeHashMap,前者也是更好的命名。

(b)命名需要符合当前抽象的层级

首先我们软件需要始终有清晰的抽象和分层。事实上我们 Naming 时遇到困难,很多就是因为软件已经缺乏明确的抽象和分层带来的表象而已。

6)不知道一个简单特性需要在哪些做修改,或者一个简单的改动会带来什么影响,即 unknown unknowns

在所有认知复杂度的表现中,这是最坏的一种,不幸的是,所有人都曾经遇到过这样的情况。

8.png

一个典型的 unknown unknowns 是一部分代码存在这样的情况:

  • 代码缺乏充分的测试覆盖,一些重要场景依赖维护者手工测试;

  • 代码有隐藏 / 不易被发现的行为或者边界条件,与文档和接口描述并不符合。

对于维护者来说,改动这样的代码(或者是改动影响到了这样代码 / 被这样代码影响到了)时,如果按照接口描述或者文档进行,没发现隐藏行为,同时代码又缺乏足够测试覆盖,那么就存在未知的风险 unknown unknowns。这时出现问题是很难避免的。最好的方式还是要尽量避免我们的系统质量劣化到这个程度。

上线时,我们最大的噩梦就是 unknown unknowns:这类风险,我们无法预知在哪里或者是否有问题,只能在软件上线后遇到问题才有可能发现。其他的问题 尚可通过努力来解决(认知成本),而 unknown unknowns 可以说已经超出了认知成本的范围。我们最希望避免的也是 unknown unknowns。

7)认知成本低要不易出错,而不是无脑“简化”

从认知成本角度来说,我们还要认识到,衡量不同方案/写法的认知成本,要考虑的是不易出错,而不是表面上的简化:表面上简化可能带来实质性的复杂度上升。

例如,为了表达时间段,可以有两种选择:

// Time period in seconds.
void someFunction(int timePeriod); 
// time period using Duration. 
void someFunction(Duration timePeriod);

在上面这个例子里面,我们都知道,应该选用第二个方案,即采用 Duration 作 time period,而不是 int:尽管 Duration 本身需要一点点学习成本,但是这个模式可以避免多个时间单位带来的常见问题。

3. 影响协同成本的因素

协同成本则是增长这块模块所需要付出的协同成本。什么样的成本是协同成本?

  • 增加一个新的特性往往需要多个工程师协同配合,甚至多个团队协同配合;
  • 测试以及上线需要协调同步。

1)系统模块拆分与团队边界

在微服务化时代,模块/服务的切分和团队对齐,更加有利于迭代效率。而模块拆分和边界的不对齐,则让代码维护的复杂度增加,因这时新的特性需要在跨多个团队的情况下进行开发、测试和迭代。

另外一个角度,则是:

Any piece of software reflects the organizational structure that produces it.

或者就是我们常说的“组织架构决定系统架构”,软件的架构最后会围绕组织的边界而变化(当然也有文化因素),当组织分工不合理时,会产生重复的建设或者冲突。

2)服务之间的依赖,Composition vs Inheritance / Plugin

软件之间的依赖模式,常见的有 Composition 和 Inheritance 模式,对于 local 模块/类之间的依赖还是远程调用,都存在类似模式。

9.png

上图左侧是 Inheritance(继承或者是扩展模式),有四个团队,其中一个是 Framework 团队负责框架实现,框架具有三个扩展点,这三个扩展点有三个不同的团队实现插件扩展,这些插件被 Framework 调用,从架构上,这是一种类似于继承的模式。

右侧是组合模式(composition):底层的系统以 API 服务的方式提供接口,而上层应用或者服务通过调用这些接口来实现业务功能。

这两种模式适用于不同的系统模型。当 Framework 偏向于底层、不涉及业务逻辑且相对非常稳定时,可以采用 inheritance 模式,也即 Framework 被集成到团队 1,2,3 的业务实现当中。例如 RPC framework 就是这样的模型:RPC 底层实现作为公共的 base 代码 / SDK 提供给业务使用,业务实现自己的 RPC 方法,被 framework 调用,业务无需关注底层 RPC 实现的细节。因为 Framework 代码被业务所依赖,因此这时业务希望 Framework 的代码非常稳定,而且尽量避免对 framework 层的感知,这时 inheritance 是一种比较合适的模型。

然而,我们要慎用 Inheritance 模式。Inheritance 模式的常见陷阱:

(a)要避免出现管理倒置

即 Framework 层负责整个系统的运维(framework 团队负责代码打包、构建、上线),那么会出现额外的协同复杂度,影响系统演进效率(设想一下如果 Dubbo 的团队要求负责所有的使用 Dubbo 的应用的打包、发布成为一个大的应用,会是多么的低效)。

(b)要避免破坏业务逻辑流程的封闭性

Inheritance 模式如果使用不当,很容易破坏上层业务的逻辑抽象完整性,也即“扩展实现1”这个模块的逻辑,依赖于其调用者的内部逻辑流程甚至是内部实现细节,这会带来危险的耦合,破坏业务的逻辑封闭性。

如果你所在的项目采用了插件 / Inheritance 模式,同时又出现上面所说的管理倒置、破坏封闭性情况,就需要反思当前的架构的合理性。

而右侧的 Composition 是更常用的模型:服务与服务之间通过 API 交互,相互解耦,业务逻辑的完整性不被破坏,同时框架 / Infra 的 encapsulation 也能保证。同时也更灵活,在这种模型下,Service 1, 2, 3 如果需要也可以产生相互调用。

另外《Effective Java》一书的 Favor composition over inheritance 有很好的分析,可以作为这个问题的补充。

3)可测试性不足带来的协同成本

交付给其他团队(包括测试团队)的代码应该包含充分的单元测试,具备良好的封装和接口描述,易于被集成测试的。然而因为 单测不足/模块测试不足,带来的集成阶段的复杂度升高、失败率和返工率的升高,都极大的增加了协同的成本。因此做好代码的充分单元测试,并提供良好的集成测试支持,是降低协同成本提升迭代效率的关键。

可测试性不足,带来协同成本升高,往往导致的破窗效应:上线越来越靠运气,unknown unknowns 越来越多。

4)文档

降低协同成本需要对接口 / API 提供清晰的、不断保持更新一致的文档,针对接口的场景、使用方式等给出清晰描述。这些工作需要投入,开发团队有时不愿意投入,但是对于每一个用户/使用方,需要依赖钉钉上的询问、或者是依靠 ATA 文章(多半有 PR 性质或者是已经过时,没有及时更新,毕竟 ATA 不是产品文档),协同成本太高,对于系统来说出现 bug / 使用不当的几率大为增加了。

最好的方式:

  • 代码都公开;
  • 文档和代码写在一起(README.md, *.md),随着代码一起提交和更新,还计算代码行数,多好。

4. 软件复杂度生命周期

10.png

复杂度的恶化到一定程度,一定进入有诸多 unknown unknowns 的程度。好的工程师一定要能识别这样的状态:可以说,如果不投入力气去做一定的重构/改造,有过多 unknown unknowns 的系统,很难避免失败的厄运了。

这张图是要表明,软件演进的过程,是一个“不由自主”就会滑向过于复杂而无法维护的深渊的过程。如何要避免失败的厄运?这篇文章的篇幅不容许我们展开讨论如何避免复杂度,但是首要的,对于真正重要的、长生命周期的软件演进,我们需要做到对于复杂度增量零容忍。

5. Good enough vs Perfect

软件领域,从效率和质量的折中,我们会提“Good enough”即可。这个理论是没错的。只不过现实中,我们极少看到“overly good”,因为过于追求 perfection 而影响效率的情况。大多数情况下,我们的系统是根本没做到 Good enough。

对复杂度增长的对策

每一份新的代码的引入,都在增加系统的复杂度:因为每一个类或者方法的创建,都会有其他代码来引用或者调用这部分代码,因而产生依赖/耦合,增加系统的复杂度(除非之前的代码过度复杂 unncessarily complex,而通过重构可以降低复杂度),如果读者都意识到了这个问题,并且那些识别增加复杂度的关键因素对于大家有所帮助,那么本文也就达到了目标。

而如何 Keep it simple,是个非常大的话题,本文不会展开。对于 API 设计,在 API 设计最佳实践思考中做了一些总结,其他的希望后续有时间能继续总结。

API 设计最佳实践思考:https://developer.aliyun.com/article/701810

有人会说,项目交付的压力才是最重要的,不要站着说话不腰疼。实际呢?我认为绝对不是这样。多数情况下,我们要对复杂度增长采用接近于“零容忍”的态度,避免“能用就行”,原因在于:

  • 复杂度增长带来的风险(unknown unknowns、不可控的失败等)往往是后知后觉的,等到问题出现时,往往 legacy 已经形成一段时间,或者坑往往是很久以前埋的;

  • 当我们在代码评审、设计评审时面临一个个选择时,每一个 Hack、每一个带来额外成本和复杂度的设计似乎都显得没那么有危害:就是增加了一点点复杂度而已,就是一点点风险而已。但是每一个失败的系统的问题都是这样一点点积累起来的;

  • 破窗效应 Broken window:一个建筑,当有了一个破窗而不及时修补,这个建筑就会被侵入住认为是无人居住的、风雨更容易进来,更多的窗户被人有意打破,很快整个建筑会加速破败。这就是破窗效应,在软件的质量控制上这个效应非常恰当。所以,Don’t live with broken windows (bad designs, wrong decisions, poor code) :有破窗尽快修。

零容忍,并不是不让复杂度增长:我们都知道这是不可能的。我们需要的是尽力控制。因为进度而临时打破窗户也能接受,但是要尽快补上。

当然文章一开始就强调了,如果所写的业务代码生命周期只有几个月,那么多半在代码变得不可维护之前就可以下线了,那可以不用关注太多,能用就行。

最后,作为 Software engineer,软件是我们的作品,希望大家都相信:

  • 真正的工程师一定在意自己的作品:我们的作品就是我们的代码。工匠精神是对每个工程师的要求;

  • 我们都可以带来改变:代码是最公平的工作场地,代码就在那里,只要我们愿意,就能带来变化。

云原生微服务框架哪家强?

近期阿里云原生团队联合 X-lab 开放实验室发布《2020 年微服务领域开源数字化报告》,通过 2020 年 1 月到 6 月的 GitHub 日志进行统计,分析微服务框架项目以及 Spring Cloud 项目的 GitHub 开发者行为日志,分析了开源微服务框架活跃度。

点击查看报告全文:https://developer.aliyun.com/article/770673

“阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. Spring学习笔记01-IOC概念及简单使用

    spring初识 1、框架 ​ 框架就是一些类和接口的集合,通过这些类和接口协调来完成一系列的程序实现。JAVA框架可以分为三层:表示层,业务层和物理层。框架又叫做开发中的半成品,它不能提供整个WEB应用程序的所有东西,但是有了框架,我们就可以集中精力进行业务逻辑的开发而…...

    2024/5/8 13:25:12
  2. 超全面的后端开发C/C++面经整理分享含详细参考答案 包括简历分享

    本文为博主2020年秋招提前批的c/c++后端开发面经整理,包括C/C++语言基础,计网,数据库,linux,操作系统,场景题,智力题和hr常问题。面试问题来自前人的工作和博主面试时遇到的值得记录的问题,其中面试题答案多为博主自行解答(并且面试的时候也基本是这样回答的),回答中…...

    2024/5/8 7:53:27
  3. 关系型数据库与非关系型数据库

    前言 你是否在为系统的数据库来一波大流量就几乎打满CPU,日常CPU居高不下烦恼?你是否在各种NoSql间纠结不定,到底该选用那种最好?今天的你就是昨天的我,这也是写这篇文章的初衷。 作为互联网从业人员,我们要知道关系型数据库(MySql、Oracle)无法满足我们对存储的所有要…...

    2024/5/8 21:33:27
  4. 服务器ftp软件,服务器ftp软件下载文件配置其运行环境的办法

    ftp软件是一种文件传输下载方式,它是TCP/IP协议栈的一部分;其中FTP又由两部分组成,一部分是FTP的服务器,另一部分是FTP的客户端!它能够高效安全地进行文件传输下载操作!可以使用服务器管理工具来作为FTP的客户端,进行FTP的操作,实现FTP的下载安装。接下来介绍服务器ftp…...

    2024/5/8 14:37:59
  5. 基于C++代码的UE4学习(四十)——为玩家角色添加噪音

    之前在AI中添加了听觉功能,还需要在主角中添加噪音,本例中完成当玩家角色跳跃的时候,产生噪音,从而可以被AI听见。在Character头文件上加入以下代码。1 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Emitter) 2 class UPawnNoiseEmitterComponent* E…...

    2024/5/8 19:43:36
  6. decorator 装饰器

    许多面向对象都有decorator(装饰器)函数,比如python中也可以用decorator函数来强化代码,decorator相当于一个高阶函数,接收一个函数,返回一个被装饰后的函数。注: javascript中也有decorator相关的提案,只是目前node以及各浏览器中均不支持。只能通过安装babel插件来转换代…...

    2024/5/6 13:38:32
  7. 服务器ftp工具,盘点一款很好用的服务器ftp工具,附上教程

    ftp工具是一种文件传输下载方式,它是TCP/IP协议栈的一部分;其中FTP又由两部分组成,一部分是FTP的服务器,另一部分是FTP的客户端!它能够高效安全地进行文件传输下载操作!可以使用服务器管理工具来作为FTP的客户端,进行FTP的操作,实现FTP的下载安装。接下来介绍服务器ftp…...

    2024/5/9 6:25:23
  8. 简信CRM:企业如何实现私有化部署CRM?

    很多企业在使用CRM系统时,都考虑过部署模式的问题,目前市面上的部署模式可以分为两种,一种是SaaS部署模式,一种是独立部署模式。 对于在局域网中办公,或是比较重视企业内部数据安全的大型企业、政府机构,更适用于独立部署模式,具有灵活的扩展性,可实现更多个性化服务。…...

    2024/5/9 4:21:49
  9. 【计算机网络】网络层 : 路由算法 ( 路由算法分类 | 静态路由算法 | 动态路由算法 | 全局性动态路由算法 | 分散性动态路由算法 | 分层次路由选择协议 )

    文章目录一、路由算法二、路由算法 分类三、静态路由算法四、动态路由算法五、动态路由算法 分类六、分层次的路由选择协议一、路由算法路由算法 : 选择数传输的 “最佳路由” , 该 “最佳” 是相对于某特定要求得出的合理选择 ;路由表 : 又称为 转发表 , 有如下条目 :目的网络…...

    2024/5/8 15:41:18
  10. nginx入门手记

    nginx入门篇1、centos安装nginx1.1 创建nginx用户,安装所需依赖(root用户)1.2安装nginx(一般用户,没给sudo权限)1.3极简配置1.3.1nginx.conf1.3.2 vhost /wwyft.cn.conf 配置文件示例2、HELLO NGINX(以echo模块为例,记录加装模块的方法)3、nginx反向代理入门3.1 locat…...

    2024/4/24 5:23:01
  11. 5G智慧医疗十大应用场景?道翰天琼认知智能机器人平台API接口大脑为您揭秘-2。

    都说5G会改变千行百业,其中,5G医疗健康就是5G技术在医疗健康行业的一个重要应用领域。随着 5G 正式商用的到来以及与大数据、互联网+、人工智能、区块链等前沿技术的充分整合和运用, 5G 医疗健康越来越呈现出强大的影响力和生命力,对推进深化医药卫生体制改革、加快“健康中…...

    2024/4/25 3:28:28
  12. 不会吧!做了这么久开发还有不会NIO的,看看BAT大佬是怎么用的吧

    前言在将NIO之前,我们必须要了解一下Java的IO部分知识。 BIO(Blocking IO) 阻塞IO,在Java中主要就是通过ServerSocket.accept()实现的。 NIO(Non-Blocking IO) 非阻塞IO,在Java主要是通过NIOSocketChannel + Seletor实现的。 AIO(Asyc IO) 异步IO,目前不做学习。BIO …...

    2024/4/17 22:52:55
  13. 2020年 第11届 蓝桥杯 C/C++ B组 省赛真题详解及小结【第1场省赛2020.7.5】

    蓝桥杯 Java B组 省赛真题详解及小结汇总【2013年(第4届)~2020年(第11届)】2013年 第04届 蓝桥杯 Java B组 省赛真题详解及小结2014年 第05届 蓝桥杯 Java B组 省赛真题详解及小结2015年 第06届 蓝桥杯 Java B组 省赛真题详解及小结2016年 第07届 蓝桥杯 Java B组 省赛真题详解…...

    2024/5/8 19:35:01
  14. 如何找到最适合您的开源项目

    如何找到最适合您的开源项目?BY 若欲莹,巴蒂尔王 ON 2019年9月17日边缘计算当前是计算行业中最普遍的主题之一。它是一项广泛的技术,几乎可以使每个行业都受益,这就是为什么出现了如此多的用例和项目的原因。本文介绍了边缘分类,描述了边缘用例的特征,概述了市场上可用的…...

    2024/4/27 18:22:41
  15. 高性能开发

    高性能开发最简单的网络通信模型:正常网络通信数据拷贝零拷贝技术I/O优化:多路复用技术线程池技术无锁编程技术wait-freelock-freeobstruction-freeLock-free CASCAS的缺点:ABA问题解决Wait-free进程间通信技术RPC && 序列化技术RPC序列化技术ProtoBufThriftAvro数据…...

    2024/5/8 17:57:25
  16. Pycharm 常用快捷键

    常用快捷键快捷键功能Ctrl + Q 快速查看文档Ctrl + F1 显示错误描述或警告信息Ctrl + / 行注释(可选中多行)Ctrl + Alt + L 代码格式化Ctrl + Alt + O 自动导入Ctrl + Alt + I 自动缩进Tab / Shift + Tab 缩进、不缩进当前行(可选中多行)Ctrl+C/Ctrl+Insert 复制当前行或选…...

    2024/4/15 5:30:08
  17. Django基础4--Shell及管理页面

    1.Django Shell打开Django的命令交互模式(django) ➜ AutoPlatform python manage.py shell Python 3.7.5 (default, Nov 29 2019, 14:32:46) [Clang 9.0.0 (clang-900.0.39.2)] on darwin Type "help", "copyright", "credits" or "lice…...

    2024/4/11 21:39:19
  18. 下载到车载u盘哪里有免费的 开车必备500首歌曲 2020车载音乐百度云 车载u盘歌曲打包下载

    我喜欢在夏日清晨在山间小林礼穿梭。开着车听着自己喜欢的歌,面朝遥远的东方,看火红的朝阳恩赐它的博爱之心,将一缕缕通透的霞光透过林子撒下来。是啊那象征着蓬勃的生命和生生不息的希望啊。那些酣睡了一夜的枝叶儿,渐渐打起精神来,沐浴在阳光里。林间精灵们又开始一天的…...

    2024/4/11 21:39:18
  19. 实验操作:shell脚本实现监控网站是否正常,异常发邮件------------------含泪写shell,写完刷皮皮虾

    监控网站是否正常,异常发邮件要求:需求分析:1、发送邮件脚本2、配置监控 要求:写一个shell脚本,通过curl -I 返回状态码来判定所访问的网站是否正常,比如当代码状态200,才算正常 写一个发邮件的脚本需求分析:1、关键问题,截取出代码状态 2、在写出该shell脚本时,应该…...

    2024/5/6 5:26:30
  20. 软考知识点——死锁

    进程管理–死锁 含义:所谓死锁,就是进程推进顺序不当或者同类资源分配不当导致无法继续运行的现象。 考点:n个进程互斥并发执行,每个进程需要r个资源,计算可以避免死锁现象的最少资源m 公式:m = n * (r - 1) + 1 举例:若在系统中有6个互斥并发进程,每个进程需要2个资源…...

    2024/4/18 5:52:09

最新文章

  1. 【神经网络】09 - 优化器 torch.optim

    09 - 优化器 torch.optim 概念 优化器是用于更新和管理模型参数以改进模型性能的一种工具。在机器学习和深度学习中,优化器的主要任务是通过调整模型的参数来最小化或最大化特定的目标函数。在许多情况下,这个目标函数是一个损失函数,我们的…...

    2024/5/9 8:12:43
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. 6.9物联网RK3399项目开发实录-驱动开发之PWM的使用(wulianjishu666)

    嵌入式实战开发例程,珍贵资料,开发必备: 链接:https://pan.baidu.com/s/1149x7q_Yg6Zb3HN6gBBAVA?pwdhs8b PWM 使用 前言 AIO-3399J 开发板上有 4 路 PWM 输出,分别为 PWM0 ~ PWM3,4 路 PWM 分别使用在…...

    2024/5/9 3:19:19
  4. Android Framework学习笔记(2)----系统启动

    Android系统的启动流程 启动过程中,用户可控部分是framework的init流程。init是系统中的第一个进程,其它进程都是它的子进程。 启动逻辑源码参照:system/core/init/main.cpp 关键调用顺序:main->FirstStageMain->SetupSel…...

    2024/5/4 10:39:30
  5. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义:dp[i][j]表示当背包容量为j,用前i个物品是否正好可以将背包填满&#xff…...

    2024/5/8 19:32:33
  6. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/5/9 7:40:42
  7. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon,直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件,我们讨论Spring负载均衡以Spring Cloud2020之后版本为主,学习Spring Cloud LoadBalance,暂不讨论Ribbon…...

    2024/5/9 2:44:26
  8. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中,周界防范意义重大,对园区的安全起到重要的作用。常规的安防方式是采用人员巡查,人力投入成本大而且效率低。周界一旦被破坏或入侵,会影响园区人员和资产安全,…...

    2024/5/8 20:33:13
  9. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时,常要分析网页Html,例如网页在加载数据时,常会显示“系统处理中,请稍候..”,我们需要在数据加载完成后才能继续下一步操作,如何抓取这个信息的网页html元素变化&…...

    2024/5/9 3:15:57
  10. 【Objective-C】Objective-C汇总

    方法定义 参考:https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/5/9 5:40:03
  11. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    👨‍💻博客主页:花无缺 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】🌏题目描述🌏输入格…...

    2024/5/9 7:40:40
  12. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/5/8 20:58:56
  13. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕,各大品牌纷纷晒出优异的成绩单,摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称,在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁,多个平台数据都表现出极度异常…...

    2024/5/9 1:35:21
  14. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令,这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/5/9 4:12:16
  15. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b,我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边, b b b 同理,则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/5/9 7:40:35
  16. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息,并安装一些有助于配置官方 NGINX 软件包仓库的软件包: apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/5/8 18:06:50
  17. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限(ROW FORMAT)配置标准HQL为: ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/5/9 7:40:34
  18. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中,传感器和控制器产生大量周…...

    2024/5/9 1:42:21
  19. --max-old-space-size=8192报错

    vue项目运行时,如果经常运行慢,崩溃停止服务,报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中,通过JavaScript使用内存时只能使用部分内存(64位系统&…...

    2024/5/9 5:02:59
  20. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞,例如可以被劫持的合法软件(例如浏览器或 Web 应用程序插件)中的错误。 恶意软件渗透可能会造成灾难性的后果,包括数据被盗、勒索或网…...

    2024/5/9 4:31:45
  21. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧! 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象…...

    2024/5/8 12:44:41
  22. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错,但存在一个缺陷:无法禁止通过实例化多个对象来创建多名总统: President One, Two, Three; 由于复制构造函数是私有的,其中每个对象都是不可复制的,但您的目…...

    2024/5/8 9:51:44
  23. python django 小程序图书借阅源码

    开发工具: PyCharm,mysql5.7,微信开发者工具 技术说明: python django html 小程序 功能介绍: 用户端: 登录注册(含授权登录) 首页显示搜索图书,轮播图&#xff0…...

    2024/5/9 6:36:49
  24. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/5/9 4:33:29
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57