微服务的设计原则与⽣态系统 - 王磊微服务的设计原则 与⽣生态系统 王磊磊 华为公司技术专家 ThoughtWorks⾸首席咨询师 Sybase Tech Leader • 《微服务架构与实践》作者 • 《DevOps Handbook》中⽂文译者之⼀一 • 国内较早倡导和实践微服务的先⾏行行者 • 对于⾃自动化测试、持续交付、DevOps有丰富的实践经验 • ⻄西安DevOps Meetup 联合发起⼈人 联合发起⼈人 关于我 议题 • 微服务架构的核⼼心 • 微服务架构设计原则 • 微服务架构⽣生态系统 Are you using microservices? Are you using microservices? https://www.nginx.com/resources/library/app-dev-survey/ 什什么是微服务架构? • 微服务架构是⼀一种架构模式, https://www.supinfo.com/articles/single/3652-what-is-devops 架构⼀一旦确定,很难改变 什什么是演进式架构? ⽀支持增量量式变更更作为第⼀一原则 什什么是演进式架构? • 演进是动态平衡 • 痛苦的事情提前做 • 运维意识是关键 演进式架构 拥抱变化 动态平衡 业务 技术 团队 架构的演进基于业务、技术和团队的平衡 - 动态的平衡0 码力 | 62 页 | 6.65 MB | 1 年前3
Golang 101(Go语言101 中文版) v1.21.astruct { 2| elements unsafe.Pointer // 引用着底层的元素 3| len int // 当前的元素个数 4| cap int // 切片的容量 5| } 从这个定义可以看出来,一个切片类型在内部可以看作是一个指针包裹类型。 每个非零切片值包含着一个底层间接部分用来存储此切片的元素。 片值的容量 有实际意义。 我们可以调用内置函数len来获取一个容器值的长度,或者调用内置函数cap 来获取一个容器值的容量。 这两个函数都返回一个int类型确定结果值或者一 个默认类型为int的类型不确定结果,具体取决于传递给它们的实参是否为常 量表达式。 因为非零映射值的容量是无限大,所以cap并不适用于映射值。 一个数组值的长度和容量永不改变。同一个数组类型的所有值的长度和容量都 总是和此数组类型的长度相等。 Println(len(a), cap(a)) // 5 5 8| var s []int 9| fmt.Println(len(s), cap(s)) // 0 0 10 | s, s2 := []int{2, 3, 5}, []bool{} 11 | fmt.Println(len(s), cap(s), len(s2), cap(s2)) // 3 3 0 00 码力 | 821 页 | 956.82 KB | 1 年前3
Golang 101(Go语言101 中文版) v1.21.atype _slice struct { elements unsafe.Pointer // 引用着底层的元素 len int // 当前的元素个数 cap int // 切片的容量 } 从这个定义可以看出来,一个切片类型在内部可以看作是一个指针包裹类型。 每个非零切片值包含着一个底层间接部分用来存储此切片的元素。 一个切片值 切片值的容量有实 际意义。 我们可以调用内置函数len来获取一个容器值的长度,或者调用内置函数cap来 获取一个容器值的容量。 这两个函数都返回一个int类型确定结果值或者一个 默认类型为int的类型不确定结果,具体取决于传递给它们的实参是否为常量表 达式。 因为非零映射值的容量是无限大,所以cap并不适用于映射值。 一个数组值的长度和容量永不改变。同一个数组类型的所有值的长度和容量都 总是和此数组类型的长度相等。 [5]int fmt.Println(len(a), cap(a)) // 5 5 var s []int fmt.Println(len(s), cap(s)) // 0 0 s, s2 := []int{2, 3, 5}, []bool{} fmt.Println(len(s), cap(s), len(s2), cap(s2)) // 3 3 0 0 var m map[int]bool0 码力 | 608 页 | 1.08 MB | 1 年前3
Golang 101(Go语言101 中文版) v1.21.astruct { 2| elements unsafe.Pointer // 引用着底层的元素 3| len int // 当前的元素个数 4| cap int // 切片的容量 5| } 第17章:值部 139 从这个定义可以看出来,一个切片类型在内部可以看作是一个指针包裹类型。 每个 非零切片值包含 切片值的容量有实际意义。 我们可以调用内置函数len来获取一个容器值的长度,或者调用内置函数cap来获 取一个容器值的容量。 这两个函数都返回一个int类型确定结果值或者一个默认类 型为int的类型不确定结果,具体取决于传递给它们的实参是否为常量表达式。 因 为非零映射值的容量是无限大,所以cap并不适用于映射值。 一个数组值的长度和容量永不改变。同一个数组类型的所有值的长度和容量都总是 Println(len(a), cap(a)) // 5 5 8| var s []int 9| fmt.Println(len(s), cap(s)) // 0 0 10| s, s2 := []int{2, 3, 5}, []bool{} 11| fmt.Println(len(s), cap(s), len(s2), cap(s2)) // 3 3 0 00 码力 | 591 页 | 21.40 MB | 1 年前3
Hello 算法 1.0.0b4 Java版为两步:首先统计操作数量,然后判断渐近上界。 第一步:统计操作数量 针对代码,逐行从上到下计算即可。然而,由于上述 ? ⋅ ?(?) 中的常数项 ? 可以取任意大小,因此操作数量 ?(?) 中的各种系数、常数项都可以被忽略。根据此原则,可以总结出以下计数简化技巧: 1. 忽略与 ? 无关的操作。因为它们都是 ?(?) 中的常数项,对时间复杂度不产生影响。 2. 省略所有系数。例如,循环 2? 次、5? + 1 次等,都可以简化记为 对数字的引用。因此,我们会发现两个数组中的相同数字拥有同一个 id ,并且这些数字的内 存地址是无需连续的。 68 5. 栈与队列 5.1. 栈 「栈 Stack」是一种遵循先入后出(First In, Last Out)原则的线性数据结构。 我们可以将栈类比为桌面上的一摞盘子,如果需要拿出底部的盘子,则需要先将上面的盘子依次取出。我们 将盘子替换为各种类型的元素(如整数、字符、对象等),就得到了栈数据结构。 在栈 /* 判断是否为空 */ boolean isEmpty = stack.isEmpty(); 5.1.2. 栈的实现 为了深入了解栈的运行机制,我们来尝试自己实现一个栈类。 栈遵循先入后出的原则,因此我们只能在栈顶添加或删除元素。然而,数组和链表都可以在任意位置添加和 删除元素,因此栈可以被视为一种受限制的数组或链表。换句话说,我们可以“屏蔽”数组或链表的部分无 关操作,使其对外表现的逻辑符合栈的特性。0 码力 | 342 页 | 27.39 MB | 1 年前3
Hello 算法 1.0.0b4 Python版为两步:首先统计操作数量,然后判断渐近上界。 第一步:统计操作数量 针对代码,逐行从上到下计算即可。然而,由于上述 ? ⋅ ?(?) 中的常数项 ? 可以取任意大小,因此操作数量 ?(?) 中的各种系数、常数项都可以被忽略。根据此原则,可以总结出以下计数简化技巧: 1. 忽略与 ? 无关的操作。因为它们都是 ?(?) 中的常数项,对时间复杂度不产生影响。 2. 复杂度 hello‑algo.com 18 2. 省略所有系数。例如,循环 对数字的引用。因此,我们会发现两个数组中的相同数字拥有同一个 id ,并且这些数字的内 存地址是无需连续的。 66 5. 栈与队列 5.1. 栈 「栈 Stack」是一种遵循先入后出(First In, Last Out)原则的线性数据结构。 我们可以将栈类比为桌面上的一摞盘子,如果需要拿出底部的盘子,则需要先将上面的盘子依次取出。我们 将盘子替换为各种类型的元素(如整数、字符、对象等),就得到了栈数据结构。 在栈 len(stack) # 判断是否为空 is_empty: bool = len(stack) == 0 5.1.2. 栈的实现 为了深入了解栈的运行机制,我们来尝试自己实现一个栈类。 栈遵循先入后出的原则,因此我们只能在栈顶添加或删除元素。然而,数组和链表都可以在任意位置添加和 删除元素,因此栈可以被视为一种受限制的数组或链表。换句话说,我们可以“屏蔽”数组或链表的部分无 关操作,使其对外表现的逻辑符合栈的特性。0 码力 | 329 页 | 27.34 MB | 1 年前3
Hello 算法 1.0.0b4 C#版为两步:首先统计操作数量,然后判断渐近上界。 第一步:统计操作数量 针对代码,逐行从上到下计算即可。然而,由于上述 ? ⋅ ?(?) 中的常数项 ? 可以取任意大小,因此操作数量 ?(?) 中的各种系数、常数项都可以被忽略。根据此原则,可以总结出以下计数简化技巧: 1. 忽略与 ? 无关的操作。因为它们都是 ?(?) 中的常数项,对时间复杂度不产生影响。 2. 省略所有系数。例如,循环 2? 次、5? + 1 次等,都可以简化记为 对数字的引用。因此,我们会发现两个数组中的相同数字拥有同一个 id ,并且这些数字的内 存地址是无需连续的。 68 5. 栈与队列 5.1. 栈 「栈 Stack」是一种遵循先入后出(First In, Last Out)原则的线性数据结构。 我们可以将栈类比为桌面上的一摞盘子,如果需要拿出底部的盘子,则需要先将上面的盘子依次取出。我们 将盘子替换为各种类型的元素(如整数、字符、对象等),就得到了栈数据结构。 在栈 /* 判断是否为空 */ bool isEmpty = stack.Count == 0; 5.1.2. 栈的实现 为了深入了解栈的运行机制,我们来尝试自己实现一个栈类。 栈遵循先入后出的原则,因此我们只能在栈顶添加或删除元素。然而,数组和链表都可以在任意位置添加和 删除元素,因此栈可以被视为一种受限制的数组或链表。换句话说,我们可以“屏蔽”数组或链表的部分无 关操作,使其对外表现的逻辑符合栈的特性。0 码力 | 341 页 | 27.39 MB | 1 年前3
Hello 算法 1.0.0b4 C++版为两步:首先统计操作数量,然后判断渐近上界。 第一步:统计操作数量 针对代码,逐行从上到下计算即可。然而,由于上述 ? ⋅ ?(?) 中的常数项 ? 可以取任意大小,因此操作数量 ?(?) 中的各种系数、常数项都可以被忽略。根据此原则,可以总结出以下计数简化技巧: 1. 忽略与 ? 无关的操作。因为它们都是 ?(?) 中的常数项,对时间复杂度不产生影响。 2. 省略所有系数。例如,循环 2? 次、5? + 1 次等,都可以简化记为 对数字的引用。因此,我们会发现两个数组中的相同数字拥有同一个 id ,并且这些数字的内 存地址是无需连续的。 68 5. 栈与队列 5.1. 栈 「栈 Stack」是一种遵循先入后出(First In, Last Out)原则的线性数据结构。 我们可以将栈类比为桌面上的一摞盘子,如果需要拿出底部的盘子,则需要先将上面的盘子依次取出。我们 将盘子替换为各种类型的元素(如整数、字符、对象等),就得到了栈数据结构。 在栈 size(); /* 判断是否为空 */ bool empty = stack.empty(); 5.1.2. 栈的实现 为了深入了解栈的运行机制,我们来尝试自己实现一个栈类。 栈遵循先入后出的原则,因此我们只能在栈顶添加或删除元素。然而,数组和链表都可以在任意位置添加和 删除元素,因此栈可以被视为一种受限制的数组或链表。换句话说,我们可以“屏蔽”数组或链表的部分无 关操作,使其对外表现的逻辑符合栈的特性。0 码力 | 343 页 | 27.39 MB | 1 年前3
Hello 算法 1.0.0b4 Golang版为两步:首先统计操作数量,然后判断渐近上界。 第一步:统计操作数量 针对代码,逐行从上到下计算即可。然而,由于上述 ? ⋅ ?(?) 中的常数项 ? 可以取任意大小,因此操作数量 ?(?) 中的各种系数、常数项都可以被忽略。根据此原则,可以总结出以下计数简化技巧: 1. 忽略与 ? 无关的操作。因为它们都是 ?(?) 中的常数项,对时间复杂度不产生影响。 2. 省略所有系数。例如,循环 2? 次、5? + 1 次等,都可以简化记为 对数字的引用。因此,我们会发现两个数组中的相同数字拥有同一个 id ,并且这些数字的内 存地址是无需连续的。 70 5. 栈与队列 5.1. 栈 「栈 Stack」是一种遵循先入后出(First In, Last Out)原则的线性数据结构。 我们可以将栈类比为桌面上的一摞盘子,如果需要拿出底部的盘子,则需要先将上面的盘子依次取出。我们 将盘子替换为各种类型的元素(如整数、字符、对象等),就得到了栈数据结构。 在栈 len(stack) /* 判断是否为空 */ isEmpty := len(stack) == 0 5.1.2. 栈的实现 为了深入了解栈的运行机制,我们来尝试自己实现一个栈类。 栈遵循先入后出的原则,因此我们只能在栈顶添加或删除元素。然而,数组和链表都可以在任意位置添加和 删除元素,因此栈可以被视为一种受限制的数组或链表。换句话说,我们可以“屏蔽”数组或链表的部分无 关操作,使其对外表现的逻辑符合栈的特性。0 码力 | 347 页 | 27.40 MB | 1 年前3
Hello 算法 1.2.0 简体中文 Ruby 版”章节后再来复习。 那么,迭代和递归具有什么内在联系呢?以上述递归函数为例,求和操作在递归的“归”阶段进行。这意味 着最初被调用的函数实际上是最后完成其求和操作的,这种工作机制与栈的“先入后出”原则异曲同工。 事实上,“调用栈”和“栈帧空间”这类递归术语已经暗示了递归与栈之间的密切关系。 1. 递:当函数被调用时,系统会在“调用栈”上为该函数分配新的栈帧,用于存储函数的局部变量、参数、 返回地址等数据。 界。 1. 第一步:统计操作数量 针对代码,逐行从上到下计算即可。然而,由于上述 ? ⋅ ?(?) 中的常数项 ? 可以取任意大小,因此操作数量 ?(?) 中的各种系数、常数项都可以忽略。根据此原则,可以总结出以下计数简化技巧。 1. 忽略 ?(?) 中的常数项。因为它们都与 ? 无关,所以对时间复杂度不产生影响。 2. 省略所有系数。例如,循环 2? 次、5? + 1 次等,都可以简化记为 = stack.length # 判断是否为空 is_empty = stack.empty? 5.1.2 栈的实现 为了深入了解栈的运行机制,我们来尝试自己实现一个栈类。 栈遵循先入后出的原则,因此我们只能在栈顶添加或删除元素。然而,数组和链表都可以在任意位置添加和 删除元素,因此栈可以视为一种受限制的数组或链表。换句话说,我们可以“屏蔽”数组或链表的部分无关 操作,使其对外表现的逻辑符合栈的特性。0 码力 | 372 页 | 18.44 MB | 10 月前3
共 1000 条
- 1
- 2
- 3
- 4
- 5
- 6
- 100













