编程系统产品(Programming Systems Product)开发的工作量是供个人使用的、 独立开发的构件程序的九倍。我估计软件构件产品化引起了 3 倍工作量,将软件构件整合成 完整系统所需要的设计、集成和测试又强加了 3 倍的工作量,这些高成本的构件在根本上是 相互独立的。
编程行业“满足我们内心深处的创造渴望和愉悦所有人的共有情感”,提供了五种乐趣
苦恼
交流
项目工作手册
项目工作手册
化学工程师已经认识到无法一步将实验室工作台上的反应过程移到工厂中,需要一个实验性工厂(pilot planet)来为提高产量和在缺乏保护的环境下运作提供宝贵经验。
对于编程产品而言,这样的中间步骤是同样必要的,但是软件工程师在着手发 布产品之前,却并不会常规地进行试验性系统的现场测试。[现在,这已经成为了一项普遍 的实践,beta 版本。它不同于有限功能的原型,alpha 版本,后者同样是我所倡导的实践。]
对于大多数项目,第一个开发的系统并不合用。它可能太慢、太大,而且难以 使用,或者三者兼而有之。
系统的丢弃和重新设计可以一步完成,也可以一块块地实现。这是个必须完成 的步骤。
将开发的第一个系统——丢弃原型——发布给用户,可以获得时间,但是它的 代价高昂——对于用户,使用极度痛苦;对于重新开发的人员,分散了精力;对于产品,影 响了声誉,即使最好的再设计也难以挽回名声。
因此,为舍弃而计划,无论如何,你一定要这样做。
开发人员交付的是用户满意程度,而不仅仅是实际的产品。”(Cosgrove)
用户的实际需要和用户感觉会随着程序的构建、测试和使用而变化。
软件产品易于掌握的特性和不可见性,导致了它的构建人员(特别容易)面临 着永恒的需求变更。
目标上(和开发策略上)的一些正常变化无可避免,事先为它们做准备总比假 设它们不会出现要好得多。
为变更计划软件产品的技术,特别是细致的模块接口文档——非常地广为人 知,但并没有相同规模的实践。尽可能地使用表驱动技术同样是有所帮助的。[现在内存的 成本和规模使这项技术越来越出众。]
高级语言的使用、编译时操作、通过引用的声明整合和自文档技术能减少变更 引起的错误。
采用定义良好的数字化版本将变更量子(阶段)化。[当今的标准实践。]
为变更计划组织架构
程序员不愿意为设计书写文档的原因,不仅仅是由于惰性。更多的是源于设计
人员的踌躇——要为自己尝试性的设计决策进行辩解。(Cosgrove)
为变更组建团队比为变更进行设计更加困难。
只要管理人员和技术人才的天赋允许,老板必须对他们的能力培养给予极大的 关注,使管理人员和技术人才具有互换性;特别是希望能在技术和管理角色之间自由地分配 人手的时候。
具有两条晋升线的高效组织机构,存在着一些社会性的障碍,人们必须警惕和 积极地同它做持续的斗争。
很容易为不同的晋升线建立相互一致的薪水级别,但要同等威信的建立需要一 些强烈的心理措施:相同的办公室、一样的支持和技术调动的优先补偿。
组建外科手术队伍式的软件开发团队是对上述问题所有方面的彻底冲击。对于 灵活组织架构问题,这的确是一个长期行之有效的解决方案。
前进两步,后退一步——程序维护
前进一步,后退一步——系统熵随时间增加
高级语言
交互式编程
某些应用上,批处理系统决不会被交互式系统所替代。[依然成立。]
调试是系统编程中很慢和较困难的部分,而漫长的调试周转时间是调试的祸 根。
有限的数据表明了系统软件开发中,交互式编程的生产率至少是原来的两倍
第 4、5、6 章所意味的煞费苦心、详尽体系结构工作不但使产品更加易于使用,而且使开发更容易进行以及 bug 更不容易产生。
V.A.Vyssotsky 提出,“许许多多的失败完全源于那些产品未精确定义的地
方。”
在编写任何代码之前,规格说明必须提交给测试小组,以详细地检查说明的完 整性和明确性。开发人员自己不会完成这项工作。(Vyssotsky)
十年内[1965~1975],Wirth 的自顶向下进行设计[逐步细化]将会是最重要
的新型形式化软件开发方法
Wirth 主张在每个步骤中,尽可能使用级别较高的表达方法
好的自顶向下设计从四个方面避免了 bug。
有时必须回退,推翻顶层设计,重新开始
结构化编程中,程序的控制结构仅由支配代码块(相对于任意的跳转)的给定 集合所组成。这种方法出色地避免了 bug,是一种正确的思考方式
Gold 结果显示了,在交互式调试过程中,第一次交互取得的工作进展是后续 交互的三倍。这实际上获益于在调试开始之前仔细地调试计划。[我认为在 1995 年依然如 此。]
我发现对良好终端系统的正确使用,往往要求每两小时的终端会话对应于两小 时的桌面工作:1 小时会话后的清理和文档工作;1 小时为下一次计划变更和测试。
系统调试(相对于单元测试)花费的时间会比预料的更长
系统调试的困难程度证明了需要一种完备系统化和可计划的方法。
系统调试仅仅应该在所有部件能够运作之后开始。(这既不同于为了查出接口 bug 所采取 “合在一起尝试” 的方法;也不同于在所有构件单元的 bug 已知,但未修复的 情况下,即开始系统调试的做法。)[对于多个团队尤其如此。
开发大量的辅助调试平台(scaffolding 脚手架)和测试代码是很值得的,代码量甚至可能会有测试对象的一半。
必须有人对变更进行控制和文档化,团队成员应使用开发库的各种受控拷贝来 工作。
系统测试期间,一次只添加一个构件。
Lehman 和 Belady 出示了证据,变更的阶段(量子)要么很大,间隔很宽;要 么小和频繁。后者很容易变得不稳定。[Microsoft 的一个团队使用了非常小的阶段(量子)。 结果是每天晚上需要重新编译生成增长中的系统。]
项目是怎样延迟了整整一年的时间?⋯一次一天
一天一天的进度落后比起重大灾难,更难以识别、更不容易防范和更加难以弥 补。
根据一个严格的进度表来控制项目的第一个步骤是制订进度表,进度表由里程 碑和日期组成。
里程碑必须是具体的、特定的、可度量的事件,能进行清晰能定义。
如果里程碑定义得非常明确,以致于无法自欺欺人时,程序员很少会就里程碑
的进展弄虚作假。
对于大型开发项目中的估计行为,政府的承包商所做的研究显示:每两周进行 仔细修订的活动时间估计,随着开始时间的临近不会有太大的变化;期间内对时间长短的过 高估计,会随着活动的进行持续下降;过低估计直到计划的结束日期之前大约三周左右,才 有所变化。
慢性进度偏离是士气杀手。[Microsoft 的 Jim McCarthy 说:“如果你错过了 一个最终期限(deadline),确保制订下一条 deadline。2”]
进取对于杰出的软件开发团队,同优秀的棒球队伍一样,是不可缺少的必要品 德。
不存在关键路径进度的替代品,使人们能够辨别计划偏移的情况。
PERT 的准备工作是 PERT 图使用中最有价值的部分。它包括了整个网状结构的 展开、任务之间依赖关系的识别、各个任务链的估计。这些都要求在项目早期进行非常专业 的计划。
第一份 PERT 图总是很恐怖的,不过人们总是不断进行努力,运用才智制订下 一份 PERT 图。
PERT 图为前面那个泄气的借口,“其他的部分反正会落后”,提供了答案。
每个老板同时需要采取行动的异常信息以及用来进行分析和早期预警的状态
数据。
状态的获取是困难的,因为下属经理有充分的理由不提供信息共享。
老板的不良反应肯定会对信息的完全公开造成压制;相反,仔细区分状态报告、
毫无惊慌地接收报告、决不越俎代庖,将能鼓励诚实的汇报。
必须有评审的机制,从而所有成员可以通过它了解真正的状态。出于这个目的, 里程碑的计划和完成文档是关键。
Vyssotsky:我发现在里程碑报告中很容易记录“计划(老板的日期)”和“估 计(最基层经理的日期)”的日期。项目经理必须停止对这些日期的怀疑。”
对于大型项目,一个对里程碑报告进行维护的计划和控制(Plan and Control) 小组是非常可贵的。
对于软件编程产品来说,程序向用户所呈现的面貌与提供给机器识别的内容同
样重要。
即使对于完全开发给自己使用的程序,描述性文字也是必须的,因为它们会被 用户-作者所遗忘。
培训和管理人员基本上没有能向编程人员成功地灌输对待文档的积极态度——文档能在整个生命周期对克服懒惰和进度的压力起促进激励作用。
这样的失败并不都是因为缺乏热情或者说服力,而是没能正确地展示如何有效 和经济地编制文档。
大多数文档只提供了很少的总结性内容。必须放慢脚步,稳妥地进行。
由于关键的用户文档包含了跟软件相关的基本决策,所以它的绝大部分需要在 程序编制之前书写,它包括了 9 项内容(参见相应章节)。
每一份发布的程序拷贝应该包括一些测试用例,其中一部分用于校验输入数据,一部分用于边界输入数据,另一部分用于无效的输入数据
对于必须修改程序的人而言,他们所需要程序内部结构文档,同样要求一份清
晰明了的概述,它包括了 5 项内容(参见相应章节)。
流程图是被吹捧得最过分的一种程序文档。详细逐一记录的流程图是一件令人
生厌的事情,而且高级语言的出现使它显得陈旧过时。(流程图是图形化的高级语言。)
如果这样,很少有程序需要一页纸以上的流程图。[在这一点上,MILSPEC 军
用标准实在错得很厉害。]
即使的确需要一张程序结构图,也并不需要遵照 ANSI 的流程图标准。
为了使文档易于维护,将它们合并至源程序是至关重要的,而不是作为独立文 档进行保存。
最小化文档负担的 3 个关键思路:
程序修改人员所使用的文档中,除了描述事情如何以外,还应阐述它为什么那 样。对于加深理解,目的是非常关键的,但即使是高级语言的语法,也不能表达目的
在线系统的高级语言(应该使用的工具)中,自文档化技术发现了它的绝佳应 用和强大功能。
C4 模型由一系列分层的软件架构图组成,这些架构图用于描述上下文、容器、组件和代码。C4 图的层次结构提供了不同的抽象级别,每种抽象级别都与不同的受众有关。
上下文(Context)
容器(Container)
组件(Component)
代码(Code)
Pandas 是 Python 语言的一个扩展程序库,用于数据分析。
Pandas 是一个开放源码、BSD 许可的库,提供高性能、易于使用的数据结构和数据分析工具。
Pandas 名字衍生自术语 “panel data”(面板数据)和 “Python data analysis”(Python 数据分析)。
Pandas 一个强大的分析结构化数据的工具集,基础是 Numpy(提供高性能的矩阵运算)。
Pandas 可以从各种文件格式比如 CSV、JSON、SQL、Microsoft Excel 导入数据。
Pandas 可以对各种数据进行运算操作,比如归并、再成形、选择,还有数据清洗和数据加工特征。
Pandas 广泛应用在学术、金融、统计学等各个数据分析领域。
Pandas 的主要数据结构是 Series (一维数据)与 DataFrame(二维数据),这两种数据结构足以处理金融、统计、社会科学、工程等领域里的大多数典型用例。
Series 是一种类似于一维数组的对象,它由一组数据(各种Numpy数据类型)以及一组与之相关的数据标签(即索引)组成。
DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共同用一个索引)。
安装 pandas 需要基础环境是 Python,开始前我们假定你已经安装了 Python 和 Pip。
使用 pip 安装 pandas:
1 | pip install pandas |
安装成功后,我们就可以导入 pandas 包使用:
1 | import pandas |
实例 - 查看 pandas 版本
1 | >>> import pandas |
导入 pandas 一般使用别名 pd 来代替:
1 | >>> import pandas |
导入 pandas 一般使用别名 pd 来代替:
1 | import pandas as pd |
实例 - 查看 pandas 版本
1 | >>> import pandas as pd |
一个简单的 pandas 实例:
1 | import pandas as pd |
Pandas Series 类似表格中的一个列(column),类似于一维数组,可以保存任何数据类型。
Series 由索引(index)和列组成,函数如下:
1 | pandas.Series(data, index, dtype, name, copy) |
参数说明
创建一个简单的 Series 实例:
1 | import pandas as pd |
输出结果如下
1 | 0 1 |
从结果可知,如果没有指定索引,索引值就从 0 开始,我们可以根据索引值读取数据:
1 | import pandas as pd |
输出结果如下:
1 | 2 |
我们可以指定索引值,如下实例:
1 | import pandas as pd |
输出结果如下:
1 | x Google |
根据索引值读取数据:
1 | import pandas as pd |
输出结果如下:
1 | Runoob |
我们也可以使用 key/value 对象,类似字典来创建 Series:
1 | import pandas as pd |
输出结果如下:
1 | 1 Google |
从上图可知,字典的 key 变成了索引值。
如果我们只需要字典中的一部分数据,只需要指定需要数据的索引即可,如下实例:
1 | import pandas as pd |
输出结果如下:
1 | 1 Google |
设置 Series 名称参数:
1 | import pandas as pd |
输出结果如下:
1 | 1 Google |
DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔类型)。DataFrame已有行索引也有列索引,它可以被看做由Series组成的字典(共同用一个索引)。
DataFrame构造方法如下:
1 | pandas.DataFrame(data, index, columns, dtype, copy) |
参数说明
Pandas DataFrame是一个二维的数组结构,类似二维数组。
1 | import pandas as pd |
输出结果如下:
1 | Site Age |
以下实例使用 ndarrays 创建,ndarray 的长度必须相同, 如果传递了 index,则索引的长度应等于数组的长度。如果没有传递索引,则默认情况下,索引将是range(n),其中n是数组长度。
1 | import pandas as pd |
输出结果如下:
1 | 0 Google 10 |
还可以使用字典(key/value),其中字典的 key 为列名:
1 | import pandas as pd |
输出结果如下:
1 | a b c |
没有对应的部分数据为 NaN。
1 | import pandas as pd |
输出结果如下:
1 | calories 420 |
注意:返回结果其实就是一个 Pandas Series 数据。
1 | import pandas as pd |
输出结果如下:
1 | calories duration |
注意:返回结果其实就是一个 Pandas DataFrame 数据。
1 | import pandas as pd |
输出结果如下:
1 | calories duration |
1 | import pandas as pd |
输出结果如下:
1 | calories 380 |
/api
开头GET
、POST
、PUT
、DELETE
等,所有写操作不允许为GET
请求正面示例:具体做了什么交待清楚(时间与用户名可不写)
反面示例:具体做了什么从提交记录中无法体现(如:修改注册接口,修改了什么,不知道。可修改为:修改注册接口,同步标签服务,增加默认标签功能)
1、命令行实现方式
2、maven插件形式
3、项目启动没问题
正面示例:
正面示例:
代码格式符合代码格式标准
代码中不可出现无用引用包
反面示例:
阿里规约不可扫描出现问题
每个类上的注释说明要写清楚
正面示例:
反面示例
方法上的描述注释要写清楚,出参、入参、返回值(接口实现方法上的注释可不写)
正面示例:
反面示例:
统一返回值HttpResult的返回类型在方法声明中必须有
正面示例:
反面示例:
入口方法controller的请求实体不可公用(一个实体对应一个请求入口)
反面示例:
1、项目技术负责人负责自己所属项目代码审查
2、代码审查总负责人负责抽查项目
3、项目总负责人每周汇总每个人的代码不规范之处代码及数量,以Showdoc形式公示
]]>最近在学习现代市场调研,自己整理了电子版。
要实现真正的消费者导向,首先,企业必须建立能够发现消费者需求并识别市场机会的系统。
这句真的点题。
使我想起了在分布式系统中的康威定律,组织架构一定要适配系统架构。
回想清末洋务运动,学其表,妄图治已根。
生产力与成产关系一定得统一。
]]>1-3月份:已翻译
4月份:寒窑赋
5月份:围炉夜话
6月份:钱本草
7月份:风赋
8月份:长门赋
9月份:洛神赋
10月份:侠客行、放言
11月份:素书
12月份:前赤壁赋
下面为已完成
3月份《小王子》 已读完
4月份微信听书《资治通鉴白话篇》
QPS Queries Per Second 是每秒查询率 ,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。即每秒的响应请求数,也即是最大吞吐能力。
简单的说,QPS = req/sec = 请求数/秒。它代表的是服务器的机器的性能最大吞吐能力。
可以理解为:每秒处理的request 数量
通常QPS作用:表达和衡量当前系统的负载。
形容当前系统的运行状态时,例如可以说:当前QPS已经达到多少了
QPS = 并发量 / 平均响应时间
并发量 = QPS * 平均响应时间
一个OA签到系统,某公司假设有600个人进行上班打卡,8:00为签到时间。
从7:50至8:00这10分钟之内,600个人访问此系统,假设每人访问签到一次为1分钟。
请问:此OA系统的QPS是多少?并发数为多少?
TPS Transactions Per Second 也就是事务数/秒。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数,最终利用这些信息作出的评估分。
TPS 的过程包括:客户端请求服务端、服务端内部处理、服务端返回客户端。
联系:都是性能指标,都是以秒为单位进行计算。
吞吐量是数据层的指标,指单位时间内系统传输的数据量,以MB/GB等为单位
TPS是网络协议层的指标,指一秒内成功完成的事务数。通常只在Loadrunner工具中使用。
吞吐量 = 一次性能测试过程中网络上传输的数据量的总和。
1、Tps即每秒处理事务数,包括了
用户请求服务器
服务器自己的内部处理
服务器返回给用户
这三个过程,每秒能够完成N个这三个过程,Tps也就是N;
2、Qps基本类似于Tps,但是不同的是,对于一个页面的一次访问,形成一个Tps;但一次页面请求,可能产生多次对服务器的请求,服务器对这些请求,就可计入“Qps”之中。
例子:
例如:访问一个页面会请求服务器3次,一次放,产生一个“T”,产生3个“Q”
例如:一个大胃王一秒能吃10个包子,一个女孩子0.1秒能吃1个包子,那么他们是不是一样的呢?答案是否定的,因为这个女孩子不可能在一秒钟吃下10个包子,她可能要吃很久。这个时候这个大胃王就相当于TPS,而这个女孩子则是QPS。虽然很相似,但其实是不同的。
并发数(并发度):指系统同时能处理的请求数量,同样反应了系统的负载能力。这个数值可以分析机器1s内的访问日志数量来得到
代表吞吐率,即 Requests Per Second 的缩写。吞吐率是服务器并发处理能力的量化描述,单位是 reqs/s,指的是某个并发用户数下单位时间内处理的请求数。
某个并发用户数下单位时间内能处理的最大的请求数,称之为最大吞吐率。
有人把 RPS 说等效于 QPS。其实可以看作同一个统计方式,只是叫法不同而已。RPS/QPS,可以使用 apche ab 工具进行测量。
吞吐量是指系统在单位时间内处理请求的数量,TPS、QPS都是吞吐量的常用量化指标。
系统吞吐量要素
一个系统的吞吐量(承压能力)与request(请求)对cpu的消耗,外部接口,IO等等紧密关联。
单个request 对cpu消耗越高,外部系统接口,IO影响速度越慢,系统吞吐能力越低,反之越高。
QPS(TPS),并发数,响应时间
QPS(TPS):每秒钟request/事务 数量
并发数:系统同时处理的request/事务数
响应时间:一般取平均响应时间
QPS(TPS)=并发数/平均响应时间
一个系统吞吐量通常有QPS(TPS),并发数两个因素决定,每套系统这个两个值都有一个相对极限值,在应用场景访问压力下,只要某一项达到系统最高值,系统吞吐量就上不去了,如果压力继续增大,系统的吞吐量反而会下降,原因是系统超负荷工作,上下文切换,内存等等其他消耗导致系统性能下降。
PV(Page View):页面访问量,即页面浏览量或点击量,用户每次刷新即被计算一次。可以统计服务一天的访问日志得到。
UV(Unique Visitor):独立访客,统计1天内访问某站点的用户数。可以统计服务一天的访问日志并根据用户的唯一标识去重得到。响应时间(RT):响应时间是指系统对请求作出响应的时间,一般取平均响应时间。可以通过Nginx、Apache之类的Web Server得到。
DAU(Daily Active User),日活跃用户数量。常用于反映网站、互联网应用或网络游戏的运营情况。DAU通常统计一日(统计日)之内,登录或使用了某个产品的用户数(去除重复登录的用户),与UV概念相似
MAU(Month Active User):月活跃用户数量,指网站、app等去重后的月活跃用户数量
我们在做系统设计的时候就需要考虑CPU运算,IO,外部系统响应因素造成的影响以及对系统性能的初步预估。
而通常情况下,我们面对需求,我们评估出来的出来QPS,并发数之外,还有另外一个维度:日pv。
通过观察系统的访问日志发现,在用户量很大的情况下,各个时间周期内的同一时间段的访问流量几乎一样。比如工作日的每天早上。只要能拿到日流量图和QPS我们就可以推算日流量。
通常的技术方法:
1、找出系统的最高TPS和日PV,这两个要素有相对比较稳定的关系(除了放假、季节性因素影响之外)
2、通过压力测试或者经验预估,得出最高TPS,然后跟进1的关系,计算出系统最高的日吞吐量。B2B中文和淘宝面对的客户群不一样,这两个客户群的网络行为不应用,他们之间的TPS和PV关系比例也不一样。
软件做性能测试时需要关注哪些性能呢?
首先,开发软件的目的是为了让用户使用,我们先站在用户的角度分析一下,用户需要关注哪些性能。
对于用户来说,当点击一个按钮、链接或发出一条指令开始,到系统把结果已用户感知的形式展现出来为止,这个过程所消耗的时间是用户对这个软件性能的直观印 象。也就是我们所说的响应时间,当相应时间较小时,用户体验是很好的,当然用户体验的响应时间包括个人主观因素和客观响应时间,在设计软件时,我们就需要 考虑到如何更好地结合这两部分达到用户最佳的体验。如:用户在大数据量查询时,我们可以将先提取出来的数据展示给用户,在用户看的过程中继续进行数据检 索,这时用户并不知道我们后台在做什么。
用户关注的是用户操作的相应时间。
其次,我们站在管理员的角度考虑需要关注的性能点。
1、 响应时间
2、 服务器资源使用情况是否合理
3、 应用服务器和数据库资源使用是否合理
4、 系统能否实现扩展
5、 系统最多支持多少用户访问、系统最大业务处理量是多少
6、 系统性能可能存在的瓶颈在哪里
7、 更换那些设备可以提高性能
8、 系统能否支持7×24小时的业务访问
再次,站在开发(设计)人员角度去考虑。
1、 架构设计是否合理
2、 数据库设计是否合理
3、 代码是否存在性能方面的问题
4、 系统中是否有不合理的内存使用方式
5、 系统中是否存在不合理的线程同步方式
6、 系统中是否存在不合理的资源竞争
JMH 即Java Microbenchmark Harness,这是专门用于进行代码的微基准测试的一套工具API。
JMH由OpenJDK/Oracle里面那群开发了Java编译器的大牛们所开发。何谓Micro Benchmark呢?简单地说就是在method层面上的benchmark,精度可以精确到微妙级。
死码消除
所谓死码,是指注释的代码,不可达的代码块,可达但不被使用的代码等等。
常量折叠与常量传播
常量折叠 (Constant folding)是一个在编译时期简化常数的一个过程,常数在表示式中仅仅代表一个简单的数值,就像是整数2,若是一个变数从未被修改也可作为常数,或者直接将一个变数被明确地标注为常数。
当你已经找出了热点函数,而需要对热点函数进行进一步的优化时,就可以使用JMH对优化的效果进行定量的分析。
想定量地知道某个函数需要执行多长时间,以及执行时间和输入n的相关性。
一个函数有两种不同实现(例如JSON序列化/反序列化有Jackson和Gson实现),不知道哪种实现性能更好
Iteration
- iteration 是JMH进行测试的最小单位,包含一组 invocations 。Invocation
-一次 benchmark 方法调用。Operation
- benchmark 方法中,被测量操作的执行。如果被测试的操作在 benchmark 方法中循环执行,可以使用@OperationsPerInvocation
表明循环次数,使测试结果为单次 operatrion 的性能。Warmup
-在实际进行 benchmark 前先进行预热。因为某个函数被调用多次之后, JIT 会对其进行编译,通过预热可以使测量结果更加接近真实情况。 1 | <dependency> |
1 | import org.openjdk.jmh.annotations.*; |
命令行
1 | mvn archetype:generate \ |
1 | cd test/ |
1 | java -jar target/benchmarks.jar |
执行 main 方法,耐心等待测试结果,最终会生成一个测试报告,内容大致如下;
1 | # JMH version: 1.22 |
下面来了解一下 jmh 常用 API
基准测试类型。这里选择的是Throughput
也就是吞吐量。根据源码点进去,每种类型后面都有对应的解释,比较好理解,吞吐量会得到单位时间内可以进行的操作数。
Throughput
-整体吞吐量,例如”1秒内可以执行多少次调用”。AverageTime
-调用的平均时间,例如”每次调用平均耗时xxx毫秒”。SampleTime
-随机取样,最后输出取样结果的分布,例如”99%的调用在xxx毫秒以内,99.99%的调用在xxx毫秒以内”SingleShotTime
-以上模式都是默认一次iteration是ls,唯有SingleShotTime是只运行一次。往往同时把warmup次数设为0,用于测试冷启动时的性能。All
- 所有模式上面我们提到了,进行基准测试前需要进行预热。一般我们前几次进行程序测试的时候会比较慢,所以要让程序进行几轮预热,保证测试的准确性
度量,其实就是一些基本的测试参数。
iterations
-进行测试的轮次time
-每轮进行的时长timeUnit
-时长单位都是一些基本的参数,可以根据具体情况调整。一般比较重的东西可以进行大量的测试,放到服务器上运行。
每个进程中的测试线程,这个非常好理解,根据具体情况选择,一般为cpu乘以2。
进行fork的次数。如果fork数是2的话,则JMH会fork出两个进程来进行测试。
这个比较简单了,基准测试结果的时间类型。一般选择秒、毫秒、微妙。
方法级注解,表示该方法是需要进行benchmark的对象,用法和JUnit的@Test类似。
属性级注解,@Param可以用来指定某项参数的多种情况。特别适合用来测试一个函数在不同的参数输入的情况下的性能。
方法级注解,这个注解的作用就是我们需要在测试之前进行一些准备工作,比如对一些数据的初始化之类的。
方法级注解,这个注解的作用就是我们需要在测试之后进行一些结束工作,比如关闭线程池,数据库连接等的,主要用于资源的回收等。
当使用@Setup参数的时候,必须在类上加上这个参数,不然会提示无法运行。
State用于声明某个类时一个”状态”,然后接受一个Scope参数用来表示该状态的共享范围。因为很多benchmark会需要一些表示状态的类,JMH允许你把这些类以依赖注入的方式注入到benchmark的函数里。Scope主要分为三种。
Thread
- 该状态为每个线程独享。Group
- 该状态为同一个组里面所有线程共享。Benchmark
- 该状态在所有线程间共享。关于 State 的用法,官方的 code sample 里有比较好的例子 。
compiler -> Annotation Processors -> Enable Annotation Processing
api很棒,但它们也非常难设计。在从头创建API时,需要正确地获取许多细节。从基本的安全考虑到使用正确的HTTP方法,实现身份验证,决定应该接受和返回哪些请求和响应,……这样的例子不胜枚举。
在这篇文章中,我尽我最大的努力压缩我所知道的所有关于什么是好的API的东西。一个你的消费者会喜欢使用的API。所有技巧都与语言无关,因此它们适用于任何框架或技术。
我知道这听起来很合理,但这很难做到正确。我所知道的最好的api都是可预测的。当使用者使用并理解一个端点时,他们可以期望另一个端点以同样的方式工作。这对于整个API来说非常重要,也是判断API是否设计良好、是否适合使用的关键指标之一。
对字段、资源和参数使用相同的大小写(我更喜欢使用snake_case)
使用复数或单数资源名(我更喜欢复数)
对所有端点使用相同的身份验证和授权方法
在整个API中使用相同的HTTP头
API-key
用于传递API键根据响应的类型使用相同的HTTP状态码
对相同类型的操作使用相同的HTTP方法
在处理日期和时间时,api应该总是返回ISO 8601格式的字符串。在特定时区显示日期通常是客户端应用程序关心的问题。
1 | { |
默认情况下,每个端点都需要授权。大多数端点都需要调用经过身份验证的用户,因此将此设置为缺省值是有意义的。如果需要公开调用某个端点,则显式地将该端点设置为允许未经授权的请求。
提供一个端点(例如GET健康状况)来确定服务是否健康。这个端点可以被负载均衡器等其他应用程序调用,以便在服务中断时采取行动。
确保对API进行版本控制,并在每次请求时传递该版本,这样消费者就不会受到对另一个版本的任何更改的影响。API版本可以通过HTTP头或querypath参数传递。即使是API的第一个版本(1.0)也应该显式地进行版本控制。
Some examples:
如果一个API需要由第三方调用,那么允许通过API密钥进行身份验证是有意义的。API键应该使用自定义的HTTP头(例如API - key)传递。它们应该有一个过期日期,并且必须能够撤销活动密钥,以便在它们被破坏时能够失效。避免将API键检查到源代码控制中(改为使用环境变量)。
使用常规的HTTP状态码来指示请求的成功或失败。不要使用太多,在整个API中使用相同的状态码来实现相同的结果。一些例子:
HTTP方法有很多,但最重要的是:
大多数端点都是面向资源的,应该这样命名。不要添加从别处可以推断出来的不必要的信息。这也适用于字段名。
✅ GOOD
❌ BAD
除了使用HTTP状态码来指示请求的结果(成功或错误)外,在返回错误时,始终使用一个标准化的错误响应,其中包含出错原因的更详细信息。消费者总是可以期待相同的结构,并采取相应的行动。
1 | // Request => GET /users/4TL011ax |
1 | // Request => POST /users |
使用POST请求创建资源后,最好返回已创建的资源。这是最重要的,因为返回的、创建的资源将反映基础数据源的当前状态,并将包含更近期的信息(例如生成的ID)。
1 | // Request: POST /users |
如前所述,PATCH请求应该对资源应用部分更新,而PUT则完全替换现有资源。围绕PATCH请求设计更新通常是个好主意,因为:
当使用PUT仅更新一个资源的字段子集时,仍然需要传递整个资源,这使得它的网络密集性更强,也更容易出错
允许任何字段不受任何限制地更新也是相当危险的
从我的经验来看,在实践中几乎没有任何用例能够让资源的完整更新变得有意义
假设一个订单资源有一个id和一个状态
允许消费者更新订单的状态是非常危险的
状态更改更有可能由另一个端点触发(如订单{id}履行)
如前一节所述,在设计端点、命名字段和决定接受哪些请求和响应时,最好尽可能具体。如果PATCH请求只接受两个字段(名称和描述),则不会有错误使用它和损坏数据的危险。
对所有返回资源集合并使用相同响应结构的请求进行分页。使用page_number和page_size(或类似的)来控制要检索的数据块。
1 | // Response <= 200 OK |
1 | // Response <= 200 OK |
能力有限,好多翻译不妥之处,望大家指正。
]]>数据库版本管理工具
1 | <dependency> |
1 | cd 你的目录/resources |
1 | spring: |
1 | $PREFIX$VERSION__$REMARK.$SUBFIX |
示例:
1 | V1.1.__description.sql |
prefix:可配置,前缀标识,默认值 V 表示 Versioned,R 表示 Repeatable;
Version:标识版本号,由一个或多个数字构成,数字之间的分隔符可用点.或单下划线_;
separator:分隔符,默认是双下划线;
description:描述信息,文字之间可以用单下划线或空格分隔
suffix:可配置,后续标识,后续标识,默认为 .sql;
Versioned migration 用于版本升级,每个版本都有唯一的版本号并只能 apply 依次。(也就是V开头的)
Repeatable migration 是指可重复加载的 migration,可以重复修改内容使用一旦脚本的 checkksum 有变动,flyway 就会重新应用该脚本,它并不用于版本更新,这类的 migration 总是在 versioned migration 执行之后才被执行(R开头的)
1 | flyway: |
坑一:命名SQL文件问题
没有按标准命名,导致执行不成功
坑二:执行失败的文件,再次启动时执行不了,可以删除数据库中flyway_schema_history
表最后一条数据,然后再重启
坑三:云家园装配后不生效,但maven可以生效,目前还在解决中。
nextep(开源)
http://www.nextep-softwares.com/
dbdeploy(开源)
http://dbdeploy.com/
Liquibase(开源)
http://www.liquibase.org/
Post Facto(开源)
http://www.post-facto.org/
下面是red gate公司的商业软件
SQL Source Control (商业软件)
http://www.red-gate.com/products/SQL_Source_Control/index.htm
其中创建型模式又分为5种
结构型模式分为7种
行为型模式分为11种
追 MM 少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是 MM 爱吃的东西,虽然口味有所不同,但不管你带 MM 去麦当劳或肯德基,只管向服务员说「来四个鸡翅」就行了。麦当劳和肯德基就是生产鸡翅的 Factory 工厂模式:客户类和工厂类分开。
消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。
MM 最爱听的就是「我爱你」这句话了,见到不同地方的 MM,要能够用她们的方言跟她说这句话哦,我有一个多种语言翻译机,上面每种语言都有一个按键,见到 MM 我只要按对应的键,它就能够用相应的语言说出「我爱你」这句话了,国外的 MM 也可以轻松搞掂,这就是我的「我爱你」builder。
建造模式:将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
请 MM 去麦当劳吃汉堡,不同的 MM 有不同的口味,要每个都记住是一件烦人的事情,我一般采用 Factory Method 模式,带着 MM 到服务员那儿,说「要一个汉堡」,具体要什么样的汉堡呢,让 MM 直接跟服务员说就行了。
工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
跟 MM 用 QQ 聊天,一定要说些深情的话语了,我搜集了好多肉麻的情话,需要时只要 copy 出来放到 QQ 里面就行了,这就是我的情话 prototype 了。(100 块钱一份,你要不要)
原始模型模式:通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。
俺有 6 个漂亮的老婆,她们的老公都是我,我就是我们家里的老公 Sigleton,她们只要说道「老公」,都是指的同一个人,那就是我 (刚才做了个梦啦,哪有这么好的事)
单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的 “单一实例” 的需求时才可使用。
在朋友聚会上碰到了一个美女 Sarah,从香港来的,可我不会说粤语,她不会说普通话,只好求助于我的朋友 kent 了,他作为我和 Sarah 之间的 Adapter,让我和 Sarah 可以相互交谈了 (也不知道他会不会耍我)
适配器(变压器)模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。
早上碰到 MM,要说早上好,晚上碰到 MM,要说晚上好;碰到 MM 穿了件新衣服,要说你的衣服好漂亮哦,碰到 MM 新做的发型,要说你的头发好漂亮哦。不要问我 “早上碰到 MM 新做了个发型怎么说” 这种问题,自己用 BRIDGE 组合一下不就行了
桥梁模式:将抽象化与实现化脱耦,使得二者可以独立的变化,也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化之间使用组合 / 聚合关系而不是继承关系,从而使两者可以独立的变化。
定义俩接口再通过一个接口将这两个接口连接起来
Mary 今天过生日。“我过生日,你要送我一件礼物。”“嗯,好吧,去商店,你自己挑。”“这件 T 恤挺漂亮,买,这条裙子好看,买,这个包也不错,买。”“喂,买了三件了呀,我只答应送一件礼物的哦。”“什么呀,T 恤加裙子加包包,正好配成一套呀,小姐,麻烦你包起来。”“……”,MM 都会用 Composite 模式了,你会了没有?
合成模式:合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。
Mary 过完轮到 Sarly 过生日,还是不要叫她自己挑了,不然这个月伙食费肯定玩完,拿出我去年在华山顶上照的照片,在背面写上 “最好的的礼物,就是爱你的 Fita”,再到街上礼品店买了个像框(卖礼品的 MM 也很漂亮哦),再找隔壁搞美术设计的 Mike 设计了一个漂亮的盒子装起来……,我们都是 Decorator,最终都在修饰我这个人呀,怎么样,看懂了吗?
装饰模式:装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。
我有一个专业的 Nikon 相机,我就喜欢自己手动调光圈、快门,这样照出来的照片才专业,但 MM 可不懂这些,教了半天也不会。幸好相机有 Facade 设计模式,把相机调整到自动档,只要对准目标按快门就行了,一切由相机自动调整,这样 MM 也可以用这个相机给我拍张照片了。门面模式:外部与一个子系统的通信必须通过一个统一的门面对象进行。
门面模式提供一个高层次的接口,使得子系统更易于使用。每一个子系统只有一个门面类,而且此门面类只有一个实例,也就是说它是一个单例模式。但整个系统可以有多个门面类。
每天跟 MM 发短信,手指都累死了,最近买了个新手机,可以把一些常用的句子存在手机里,要用的时候,直接拿出来,在前面加上 MM 的名字就可以发送了,再不用一个字一个字敲了。共享的句子就是 Flyweight,MM 的名字就是提取出来的外部特征,根据上下文情况使用。享元模式:FLYWEIGHT 在拳击比赛中指最轻量级。
享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态,它们是相互独立的。
将可以共享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象,而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。
跟 MM 在网上聊天,一开头总是 “hi, 你好”,“你从哪儿来呀?”“你多大了?”“身高多少呀?” 这些话,真烦人,写个程序做为我的 Proxy 吧,凡是接收到这些话都设置好了自己的回答,接收到其他的话时再通知我回答,怎么样,酷吧。
代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。
客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入。
晚上去上英语课,为了好开溜坐到了最后一排,哇,前面坐了好几个漂亮的 MM 哎,找张纸条,写上 “Hi, 可以做我的女朋友吗?如果不愿意请向前传”,纸条就一个接一个的传上去了,糟糕,传到第一排的 MM 把纸条传给老师了,听说是个老处女呀,快跑!
责任链模式:在责任链模式中,很多对象由每一个对象对其下家的引用而接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求,系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择:承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。
俺有一个 MM 家里管得特别严,没法见面,只好借助于她弟弟在我们俩之间传送信息,她对我有什么指示,就写一张纸条让她弟弟带给我。这不,她弟弟又传送过来一个 COMMAND,为了感谢他,我请他吃了碗杂酱面,哪知道他说:“我同时给我姐姐三个男朋友送 COMMAND,就数你最小气,才请我吃面。”
命令模式:命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。命令模式允许请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否执行,何时被执行以及是怎么被执行的。系统支持命令的撤消。
俺有一个《泡 MM 真经》,上面有各种泡 MM 的攻略,比如说去吃西餐的步骤、去看电影的方法等等,跟 MM 约会时,只要做一个 Interpreter,照着上面的脚本执行就可以了。
解释器模式:给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。解释器模式将描述怎样在有了一个简单的文法后,使用模式设计解释这些语句。
在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。在解释器模式中需要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则。每一个命令对象都有一个解释方法,代表对命令对象的解释。命令对象的等级结构中的对象的任何排列组合都是一个语言。
我爱上了 Mary,不顾一切的向她求婚。Mary:“想要我跟你结婚,得答应我的条件” 我:“什么条件我都答应,你说吧” Mary:“我看上了那个一克拉的钻石” 我:“我买,我买,还有吗?” Mary:“我看上了湖边的那栋别墅” 我:“我买,我买,还有吗?” Mary:“我看上那辆法拉利跑车” 我脑袋嗡的一声,坐在椅子上,一咬牙:“我买,我买,还有吗?”
迭代模式:迭代模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中,从而与聚集本身隔开。
迭代模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。
四个 MM 打麻将,相互之间谁应该给谁多少钱算不清楚了,幸亏当时我在旁边,按照各自的筹码数算钱,赚了钱的从我这里拿,赔了钱的也付给我,一切就 OK 啦,俺得到了四个 MM 的电话。调停者模式:调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以松散偶合。
当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。调停者模式将对象的行为和协作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理。
同时跟几个 MM 聊天时,一定要记清楚刚才跟 MM 说了些什么话,不然 MM 发现了会不高兴的哦,幸亏我有个备忘录,刚才与哪个 MM 说了什么话我都拷贝一份放到备忘录里面保存,这样可以随时察看以前的记录啦。
备忘录模式:备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
想知道咱们公司最新 MM 情报吗?加入公司的 MM 情报邮件组就行了,tom 负责搜集情报,他发现的新情报不用一个一个通知我们,直接发布给邮件组,我们作为订阅者(观察者)就可以及时收到情报啦。
观察者模式:观察者模式定义了一种一队多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。关注微信订阅号码匠笔记回复设计模式还有视频版本哦
跟 MM 交往时,一定要注意她的状态哦,在不同的状态时她的行为会有不同,比如你约她今天晚上去看电影,对你没兴趣的 MM 就会说 “有事情啦”,对你不讨厌但还没喜欢上的 MM 就会说 “好啊,不过可以带上我同事么?”,已经喜欢上你的 MM 就会说 “几点钟?看完电影再去泡吧怎么样?”,当然你看电影过程中表现良好的话,也可以把 MM 的状态从不讨厌不喜欢变成喜欢哦。
状态模式:状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。
状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。
跟不同类型的 MM 约会,要用不同的策略,有的请电影比较好,有的则去吃小吃效果不错,有的去海边浪漫最合适,单目的都是为了得到 MM 的芳心,我的追 MM 锦囊中有好多 Strategy 哦。策略模式:策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。
策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开来,算法的增减,修改都不会影响到环境和客户端。
看过《如何说服女生上床》这部经典文章吗?女生从认识到上床的不变的步骤分为巧遇、打破僵局、展开追求、接吻、前戏、动手、爱抚、进去八大步骤 (Template method),但每个步骤针对不同的情况,都有不一样的做法,这就要看你随机应变啦 (具体实现);
模板方法模式:模板方法模式准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。
情人节到了,要给每个 MM 送一束鲜花和一张卡片,可是每个 MM 送的花都要针对她个人的特点,每张卡片也要根据个人的特点来挑,我一个人哪搞得清楚,还是找花店老板和礼品店老板做一下 Visitor,让花店老板根据 MM 的特点选一束花,让礼品店老板也根据每个人特点选一张卡,这样就轻松多了;
访问者模式:访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对稳定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。
访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时,要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。
]]>作者: [英] 爱德华•德•博诺 (Edward De Bono)
最近在读六顶思考帽这本书。很早之前就听过这本书,一直也没看,最近公司读书会形式有所改变,不再是大家通读一本书,说实话原来那种形式我不是太喜欢,每天往群里发几页,遇见想看的吧嫌发的太少,大多数时候都是不喜欢读,从书的选择和读形式我都是很抵触的,本来自我感觉还是喜欢看书的人,但读书会的这种形式,我看还是算了吧!
别把我好不容易来的读书兴趣给抹杀了!
现在信息爆炸,每天被各种垃圾信息包围,读书也是:如果不经过认真挑选,你就会被垃圾环绕。
作为一个挑食(精神食粮)的人,初看到这本书,扫了眼豆瓣,评分好像是6点多,属实不高。用什么6个颜色来表达6种思考方式,我觉得很欠妥。本来就有见文知意的字来形容这6种思维模式。愣是自造概念整了6种颜色。好吧——在我创造的世界里我就是上帝。
以上吐槽告一段落。说点积极的,书中还是有一些积极意义的:
6中思维模式
颜色 | 解释 |
---|---|
蓝色 | 框架思维 |
白色 | 事实思维 |
绿色 | 创造性思维 |
黄色 | 积极思维 |
黑色 | 危机思维 |
红色 | 情绪思维 |
咋用呢?
书中说可以单独用,也可以顺序都用,也可以定时用,注意纪律性。好吧貌似都是说给开会使用的。
说到开会,想起了一句话:”评价一个人领导力水平高低就是看这人会不会开会”
书中说到了一句话我很喜欢,在此记录:”思考最大的敌人是复杂性,因为那会导致混乱。当思考过程清晰简单,它本身就很愉快,也更有效。”
]]>AI 技术
人工智能大模型
深度学习框架
NLP
智能语音
col1 | col2 | col3 |
---|---|---|
自动驾驶
知识图谱
去年,GPT-3 横空出世,这个具有 1750 亿参数规模的预训练模型所表现出来的零样本与小样本学习能力刷新了人们的认知,也引爆了 2021 年 AI 大模型研究的热潮。
2021 年 1 月,Google 推出的 Switch Transformer 模型以高达 1.6 万亿的参数量打 破了 GPT-3 作为最大 AI 模型的统治地位,成为史上首个万亿级语言模型。
国内研究机构也不甘示弱。今年 6 月,北京智源人工智能研究院发布了超大规模智能 模型“悟道 2.0”,达到 1.75 万亿参数,超过 Switch Transformer 成为全球最大的预训 练模型。
Gartner Hype Cycle 把整个发展周期分成 5 个部分
新技术
客户分层
头部互联网技术公司,以 Top30-50 一线互联网公司为代表。技术栈上,以自建平台为主,且大部分公司采用以开源为基础的自建方式(其中少数 Top10 头部厂商会投资 0 到 1 自研)。
中腰部技术公司,其中又可以细分为两类:
中腰部互联网公司,这类型公司大多数诞生于云时代(近 8 年),通常处于成 长期并聚焦自身业务发展,对基础设施投资有限,同时追求更低的 TCO(包含 硬件和人力的总成本),倾向直接采用公共云平台架构并购买 PaaS 服务。(注:这类型客户是 SnowFlake 的典型客户)。
有技术能力的非互联网公司,以银行/通信等领域企业为主。因监管或者资管要 求,通常采用专有云或者混合云模式,企业具备数据开发人员,能够在数据平 台上完成数据应用/解决方案的开发。这类型客户通常负责关键业务,对平台的 企业级能力(包括稳定性、安全性、免运维能力)要求很高。
纯甲方应用型客户,以线下大型非技术型企业为主。这类型客户通常没有数据开发 和应用建设的经验和团队,对数据类应用的需求多通过与合作伙伴(ISV)合作或 者外包方式完成。对技术栈和技术选型通常不敏感,但对稳定性要求很高。
对比维度 | 数据湖 | 数据仓库 |
---|---|---|
方法论 | 事后建模 | 事前建模 |
存储类型 | 结构化、半结构化、非结构化 | 结构化、半结构化 |
计算引擎 | 向所有引擎开放 各引擎有限优化 | 向特定引擎开放 |
成本 | 难运维管理 | 难启动 |
数据治理 | 质量低 难管理使用 | 质量高 易管理使用 |
发展趋势:湖仓一体
实际上湖仓一体有两个流派:数据仓库到数据湖,数据湖到数据仓库
第一个流派是以数仓这种方式诞生的,它是一个左右派,左边是一个数据仓库,右边是一个数据湖,中间以高速网络相连形成一个反对式的联动;
第二个流派是从数据湖向数仓演进,整体架构是在数据湖上搭建数据仓库。
这两个流派的代表分别是 AWS Redshift/阿里云 MaxCompute,以及 Databricks,目前这两个流派都还在发展中。
数据分析和 BI 更侧重于历史数据的总结
而算法/AI 具备越来越好的面向未来做预测,给大家带来更多决策支撑
第一个 1,代表存储和资源的统一。
中间的 N 指代的是多种运算引擎和模式,例如批处理、流处理、机器学习、图计算等等,不同的计算引擎共享底层的数据和资源池。
最后一个 1,是指统一的接入层和数据开发应用层,这个层次是可选的。有些企业选择统一入口管理的架构,做更好的权限管理等。有些企业和厂商选择不再收敛了,引擎可以被各种团队或者各种用户独立使用。
Apache Delta、Hudi为代表的近实时化技术
Data Freshness、Resource Costs 和 Query Performance
云边端协同的计算模式会成为热点,统称 IoT。
数据安全不仅仅是一个权限问题,还涉及很复杂的系统架构包括:
DBA 以人为轴的数据管理和优化方式不再胜任
机器学习、深度学习的自动化技术
通过机器学习自动进行数据分层:
当作业量达到百万量级时,这些决策应该由机器来自动完成,而不应该由人来完成。
自建系统:
这个答案可能需要结合客户分层来看
一个简单的经验公式是:
对于百台规模的平台,基于开源软件自建的总 TCO=物理硬件成本+开发和维护人力成本=物理硬件成本*2
主流的计算范式就是二维关系表达
图计算是目前最被看好的方向,它是点边模型。
图学习 GraphEmbedding 技术
]]>本文摘抄自infoQ《2021年技术盘点与展望》
2021 年度技术盘点
2022年度技术展望
你知道,为了搜索(和分析)
Elasticsearch 是位于 Elastic Stack 核心的分布式搜索和分析引擎。Logstash 和 Beats 有助于收集、聚合和丰富您的数据并将其存储在 Elasticsearch 中。Kibana
使您能够以交互方式探索、可视化和共享对数据的洞察,并管理和监控堆栈。Elasticsearch 是索引、搜索和分析魔法发生的地方。
Elasticsearch 为所有类型的数据提供近乎实时的搜索和分析。无论您拥有结构化或非结构化文本、数值数据还是地理空间数据,Elasticsearch
都可以以支持快速搜索的方式高效地存储和索引它。您可以超越简单的数据检索和聚合信息来发现数据中的趋势和模式。随着您的数据和查询量的增长,Elasticsearch 的分布式特性使您的部署能够随之无缝增长。
虽然并非所有问题都是搜索问题,但 Elasticsearch 提供了在各种用例中处理数据的速度和灵活性:
我们不断对人们使用搜索的新颖方式感到惊讶。但是,无论您的用例是否与其中之一类似,或者您正在使用 Elasticsearch 来解决新问题,您在 Elasticsearch 中处理数据、文档和索引的方式都是相同的。
Elasticsearch 是一个分布式文档存储。Elasticsearch 不是将信息存储为列状数据的行,而是存储已序列化为 JSON 文档的复杂数据结构。当集群中有多个 Elasticsearch
节点时,存储的文档分布在整个集群中,并且可以从任何节点立即访问。
存储文档后,它会被编入索引,并且可以近乎实时地在1 秒内完全搜索。Elasticsearch 使用一种称为倒排索引的数据结构,它支持非常快速的全文搜索。倒排索引列出出现在任何文档中的每个唯一单词,并标识每个单词出现的所有文档。
可以将索引视为文档的优化集合,每个文档都是字段的集合,这些字段是包含您的数据的键值对。默认情况下,Elasticsearch
索引每个字段中的所有数据,每个索引字段都有一个专用的、优化的数据结构。例如,文本字段存储在倒排索引中,数值和地理字段存储在 BKD 树中。使用每个字段的数据结构来组合和返回搜索结果的能力使 Elasticsearch 如此之快。
Elasticsearch 还具有无模式的能力,这意味着可以在不明确指定如何处理文档中可能出现的每个不同字段的情况下为文档编制索引。启用动态映射后,Elasticsearch
会自动检测并将新字段添加到索引中。这种默认行为使索引和探索数据变得容易——只需开始索引文档,Elasticsearch 就会检测并将布尔值、浮点和整数值、日期和字符串映射到适当的 Elasticsearch 数据类型。
但是,归根结底,您比 Elasticsearch 更了解您的数据以及您希望如何使用它。您可以定义规则来控制动态映射并显式定义映射以完全控制字段的存储和索引方式。
定义您自己的映射使您能够:
在索引期间应用于全文字段的分析链也在搜索时使用。当您查询全文字段时,在索引中查找术语之前,查询文本会经过相同的分析。
虽然您可以将 Elasticsearch 用作文档存储并检索文档及其元数据,但真正的强大之处在于能够轻松访问构建在 Apache Lucene 搜索引擎库上的全套搜索功能。
Elasticsearch 提供了一个简单、一致的 REST API 来管理您的集群以及索引和搜索您的数据。出于测试目的,您可以直接从命令行或通过 Kibana 中的开发人员控制台轻松提交请求。在您的应用程序中,您可以将
Elasticsearch 客户端 用于您选择的语言:Java、JavaScript、Go、.NET、PHP、Perl、Python 或 Ruby。
搜索您的数据
Elasticsearch REST API 支持结构化查询、全文查询和将两者结合的复杂查询。结构化查询类似于您可以在 SQL
中构造的查询类型。例如,您可以搜索索引中的gender和age字段并按字段employee对匹配项进行排序hire_date。全文查询查找与查询字符串匹配的所有文档,并按相关性排序返回它们——它们与您的搜索词的匹配程度。
除了搜索单个术语外,您还可以执行短语搜索、相似性搜索和前缀搜索,并获得自动完成建议。
有要搜索的地理空间数据或其他数字数据吗?Elasticsearch 在支持高性能地理和数值查询的优化数据结构中索引非文本数据。
您可以使用 Elasticsearch 的综合 JSON 样式查询语言 ( Query DSL )访问所有这些搜索功能。您还可以构建SQL 样式的查询以在 Elasticsearch 内部搜索和聚合数据,JDBC 和 ODBC
驱动程序使广泛的第三方应用程序能够通过 SQL 与 Elasticsearch 交互。
分析您的数据编辑 Elasticsearch 聚合使您能够构建复杂的数据摘要并深入了解关键指标、模式和趋势。聚合不仅可以找到众所周知的“大海捞针”,还可以让您回答以下问题:
您还可以使用聚合来回答更微妙的问题,例如:
因为聚合利用了用于搜索的相同数据结构,所以它们也非常快。这使您能够实时分析和可视化数据。您的报告和仪表板会随着数据的变化而更新,以便您可以根据最新信息采取行动。
更重要的是,聚合与搜索请求一起运行。您可以在单个请求中对相同数据同时搜索文档、过滤结果和执行分析。并且因为聚合是在特定搜索的上下文中计算的,所以您不仅会显示所有 70 号针的计数,还显示了与用户搜索条件匹配的 70
号针的计数——例如,所有尺寸 70不粘绣花针。
但是等等,还有更多编辑
想要自动化时间序列数据的分析吗?您可以使用 机器学习功能创建数据中正常行为的准确基线并识别异常模式。通过机器学习,您可以检测:
最好的部分是?您无需指定算法、模型或其他与数据科学相关的配置即可执行此操作。
Elasticsearch 旨在始终可用并根据您的需求进行扩展。它通过自然分布来做到这一点。您可以将服务器(节点)添加到集群以增加容量,Elasticsearch
会自动在所有可用节点之间分配您的数据和查询负载。无需大修您的应用程序,Elasticsearch 知道如何平衡多节点集群以提供可扩展性和高可用性。节点越多越好。
这是如何运作的?在幕后,Elasticsearch 索引实际上只是一个或多个物理分片的逻辑分组,其中每个分片实际上是一个独立的索引。通过将索引中的文档分布在多个分片中,并将这些分片分布在多个节点上,Elasticsearch
可以确保冗余,这既可以防止硬件故障,又可以在将节点添加到集群时增加查询容量。随着集群的增长(或缩小),Elasticsearch 会自动迁移分片以重新平衡集群。
有两种类型的分片:主分片和副本。索引中的每个文档都属于一个主分片。副本分片是主分片的副本。副本提供数据的冗余副本,以防止硬件故障并增加处理读取请求(如搜索或检索文档)的容量。
索引中的主分片数量在创建索引时是固定的,但副本分片的数量可以随时更改,而不会中断索引或查询操作。
这取决于……
关于分片大小和为索引配置的主分片数量,有许多性能考虑和权衡。分片越多,维护这些索引的开销就越大。分片大小越大,当 Elasticsearch 需要重新平衡集群时,移动分片所需的时间就越长。
查询大量小分片会使每个分片的处理速度更快,但更多查询意味着更多开销,因此查询较少数量的较大分片可能会更快。简而言之……视情况而定。
作为起点:
为您的用例确定最佳配置的最佳方法是 使用您自己的数据和查询进行测试。
发生灾害时
集群节点之间需要良好、可靠的连接。为了提供更好的连接,您通常将节点放在同一数据中心或附近的数据中心。但是,为了保持高可用性,您还需要避免任何单点故障。在一个位置发生重大中断的情况下,另一个位置的服务器需要能够接管。答案?跨集群复制 (
CCR)。
CCR 提供了一种将索引从主集群自动同步到可用作热备份的辅助远程集群的方法。如果主集群出现故障,辅助集群可以接管。您还可以使用 CCR 创建辅助集群,以便为您的用户提供地理位置邻近的读取请求。
跨集群复制是主动-被动的。主集群上的索引是活动的领导者索引,处理所有写请求。复制到辅助集群的索引是只读的跟随者。
护理和喂养
与任何企业系统一样,您需要工具来保护、管理和监控您的 Elasticsearch 集群。集成到 Elasticsearch 中的安全、监控和管理功能使您能够将Kibana 用作管理集群的控制中心。类似的特征数据汇总和指标生命周期管理
可帮助您明智随着时间的推移管理您的数据。
以下是 Elasticsearch 7.15 中新增和改进的亮点!
有关此版本的详细信息,请参阅发行说明和 迁移指南。
其他版本: 7.14 | 7.13 | 7.12 | 7.11 | 7.10 | 7.9 | 7.8 | 7.7 | 7.6 | 7.5 | 7.4 | 7.3 | 7.2 | 7.1 | 7.0
索引磁盘使用API编辑
有一个新的 API 支持分析索引的每个字段的磁盘使用情况,包括整个索引本身。API 通过迭代字段的内容并跟踪读取的字节数来估计字段的磁盘使用情况。请参阅分析索引磁盘使用情况 API。
搜索矢量切片 API编辑
有一个新端点可用于从存储在 Elasticsearch 中的地理空间数据生成矢量切片。此功能对于想要在地图上呈现存储在 Elasticsearch 中的地理空间信息的任何应用程序都很有用。请参阅搜索矢量切片 API。
复合运行时字段编辑
运行时字段支持 grok 和 dissect 模式,但之前仅针对单个字段发出值。您现在可以使用composite运行时字段从单个字段发出多个值。请参阅定义复合运行时字段。
本指南帮助初学者学习如何:
设置 Elasticsearch 的最简单方法是在 Elastic Cloud 上使用 Elasticsearch Service 创建托管部署。如果您更喜欢管理自己的测试环境,可以使用 Docker 安装和运行
Elasticsearch。
弹性搜索服务
- 获得免费试用。
- 登录Elastic Cloud。
- 单击创建部署。
- 选择一个解决方案并为您的部署命名。
- 单击创建部署并下载elastic用户的密码。
docker 安装
安装并运行 Elasticsearch
1.安装并启动Docker 桌面。
2.运行:
1
2
3 docker network create elastic
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.15.2
docker run --name es01-test --net elastic -p 127.0.0.1:9200:9200 -p 127.0.0.1:9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.15.2安装并运行 Kibana
要使用直观的 UI 分析、可视化和管理 Elasticsearch 数据,请安装 Kibana。
1.在新的终端会话中,运行:
1
2
3 >docker pull docker.elastic.co/kibana/kibana:7.15.2
>docker run --name kib01-test --net elastic -p 127.0.0.1:5601:5601 -e "ELASTICSEARCH_HOSTS=http://es01-test:9200" docker.elastic.co/kibana/kibana:7.15.22.要访问 Kibana,请转到http://localhost:5601
您使用 REST API 向 Elasticsearch 发送数据和其他请求。这使您可以使用任何发送 HTTP 请求的客户端(例如curl )与 Elasticsearch 进行交互 。您还可以使用 Kibana 的控制台向
Elasticsearch 发送请求。
弹性搜索服务
使用卷曲1.要使用 curl 或其他客户端与 Elasticsearch 通信,您需要集群的端点。进入Elasticsearch页面,点击Copy endpoint。
2.要提交示例 API 请求,请在新的终端会话中运行以下 curl 命令。替换为elastic用户的密码。替换 为您的端点。
1 curl - u elastic :<密码> < elasticsearch_endpoint >/使用 Kibana
1.转到Kibana页面并单击Launch。
2.打开 Kibana 的主菜单并转到Dev Tools > Console。
在控制台中运行以下示例 API 请求:
Add dataedit
You add data to Elasticsearch as JSON objects called documents. Elasticsearch stores these documents in searchable indices.
For time series data, such as logs and metrics, you typically add documents to a data stream made up of multiple auto-generated backing indices.
A data stream requires an index template that matches its name. Elasticsearch uses this template to configure the stream’s backing indices. Documents sent to a data stream must have a @timestamp field.
Add a single documentedit
Submit the following indexing request to add a single log entry to the logs-my_app-default data stream. Since logs-my_app-default doesn’t exist, the request automatically creates it using the built-in logs-- index template.
1 | curl -X POST "localhost:9200/logs-my_app-default/_doc?pretty" -H 'Content-Type: application/json' -d' |
The response includes metadata that Elasticsearch generates for the document:
1 | { |
Use the _bulk endpoint to add multiple documents in one request. Bulk data must be newline-delimited JSON (NDJSON). Each line must end in a newline character (\n), including the last line.
1 | curl -X PUT "localhost:9200/logs-my_app-default/_bulk?pretty" -H 'Content-Type: application/json' -d' |
Indexed documents are available for search in near real-time. The following search matches all log entries in logs-my_app-default and sorts them by @timestamp in descending order.
1 | curl -X GET "localhost:9200/logs-my_app-default/_search?pretty" -H 'Content-Type: application/json' -d' |
By default, the hits section of the response includes up to the first 10 documents that match the search. The _source of each hit contains the original JSON object submitted during indexing.
1 | { |
Parsing the entire _source is unwieldy for large documents. To exclude it from the response, set the _source parameter to false. Instead, use the fields parameter to retrieve the fields you want.
1 | curl -X GET "localhost:9200/logs-my_app-default/_search?pretty" -H 'Content-Type: application/json' -d' |
The response contains each hit’s fields values as a flat array.
1 | { |
To search across a specific time or IP range, use a range query.
1 | curl -X GET "localhost:9200/logs-my_app-default/_search?pretty" -H 'Content-Type: application/json' -d' |
You can use date math to define relative time ranges. The following query searches for data from the past day, which won’t match any log entries in logs-my_app-default.
1 | curl -X GET "localhost:9200/logs-my_app-default/_search?pretty" -H 'Content-Type: application/json' -d' |
You can extract runtime fields from unstructured content, such as log messages, during a search.
Use the following search to extract the source.ip runtime field from event.original. To include it in the response, add source.ip to the fields parameter.
1 | curl -X GET "localhost:9200/logs-my_app-default/_search?pretty" -H 'Content-Type: application/json' -d' |
You can use the bool query to combine multiple queries. The following search combines two range queries: one on @timestamp and one on the source.ip runtime field.
1 | curl -X GET "localhost:9200/logs-my_app-default/_search?pretty" -H 'Content-Type: application/json' -d' |
Use aggregations to summarize data as metrics, statistics, or other analytics.
The following search uses an aggregation to calculate the average_response_size using the http.response.body.bytes runtime field. The aggregation only runs on documents that match the query.
1 | curl -X GET "localhost:9200/logs-my_app-default/_search?pretty" -H 'Content-Type: application/json' -d' |
The response’s aggregations object contains aggregation results.
1 | { |
Explore more search optionsedit
To keep exploring, index more data to your data stream and check out Common search options.
When you’re done, delete your test data stream and its backing indices.
1 | curl -X DELETE "localhost:9200/_data_stream/logs-my_app-default?pretty" |
You can also delete your test deployment.
Elasticsearch Service
Click Delete deployment from the deployment overview page and follow the prompts.
Self-managed
To stop your Elasticsearch and Kibana Docker containers, run:
1
2 docker stop es01-test
docker stop kib01-testTo remove the containers and their network, run:
1
2
3 >docker network rm elastic
docker rm es01-test
docker rm kib01-test
What’s next?edit
This section includes information on how to setup Elasticsearch and get it running, including:
The matrix of officially supported operating systems and JVMs is available here: Support Matrix. Elasticsearch is tested on the listed platforms, but it is possible that it will work on other platforms too.
Elasticsearch is built using Java, and includes a bundled version of OpenJDK from the JDK maintainers (GPLv2+CE) within each distribution. The bundled JVM is the recommended JVM and is located within the jdk directory of the Elasticsearch home directory.
To use your own version of Java, set the ES_JAVA_HOME environment variable. If you must use a version of Java that is different from the bundled JVM, we recommend using a supported LTS version of Java. Elasticsearch will refuse to start if a known-bad version of Java is used. The bundled JVM directory may be removed when using your own JVM.
In production, we recommend you run Elasticsearch on a dedicated host or as a primary service. Several Elasticsearch features, such as automatic JVM heap sizing, assume it’s the only resource-intensive application on the host or container. For example, you might run Metricbeat alongside Elasticsearch for cluster statistics, but a resource-heavy Logstash deployment should be on its own host.
You can run Elasticsearch on your own hardware or use our hosted Elasticsearch Service that is available on AWS, GCP, and Azure. Try the Elasticsearch Service for free.
Elasticsearch is provided in the following package formats:
系统 | 描述 |
---|---|
Linux and MacOS tar.gz archives | The tar.gz archives are available for installation on any Linux distribution and MacOS. |
Windows .zip archive | The zip archive is suitable for installation on Windows. |
deb | The deb package is suitable for Debian, Ubuntu, and other Debian-based systems. Debian packages may be downloaded from the Elasticsearch website or from our Debian repository. |
rpm | The rpm package is suitable for installation on Red Hat, Centos, SLES, OpenSuSE and other RPM-based systems. RPMs may be downloaded from the Elasticsearch website or from our RPM repository. |
msi | [beta] This functionality is in beta and is subject to change. The design and code is less mature than official GA features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA features.The msi package is suitable for installation on Windows 64-bit systems with at least .NET 4.5 framework installed, and is the easiest choice for getting started with Elasticsearch on Windows. MSIs may be downloaded from the Elasticsearch website. |
docker | Images are available for running Elasticsearch as Docker containers. They may be downloaded from the Elastic Docker Registry. Install Elasticsearch with Docker |
brew | Formulae are available from the Elastic Homebrew tap for installing Elasticsearch on macOS with the Homebrew package manager. |
We also provide the following configuration management tools to help with large deployments:
tool | url |
---|---|
Puppet | puppet-elasticsearch |
Chef | cookbook-elasticsearch |
Ansible | ansible-elasticsearch |
Elasticsearch ships with good defaults and requires very little configuration. Most settings can be changed on a running cluster using the Cluster update settings API.
The configuration files should contain settings which are node-specific (such as node.name and paths), or settings which a node requires in order to be able to join a cluster, such as cluster.name and network.host.
Elasticsearch has three configuration files:
These files are located in the config directory, whose default location depends on whether or not the installation is from an archive distribution (tar.gz or zip) or a package distribution (Debian or RPM packages).
For the archive distributions, the config directory location defaults to $ES_HOME/config. The location of the config directory can be changed via the ES_PATH_CONF environment variable as follows:
1 | ES_PATH_CONF=/path/to/my/config ./bin/elasticsearch |
Alternatively, you can export the ES_PATH_CONF environment variable via the command line or via your shell profile.
For the package distributions, the config directory location defaults to /etc/elasticsearch. The location of the config directory can also be changed via the ES_PATH_CONF environment variable, but note that setting this in your shell is not sufficient. Instead, this variable is sourced from /etc/default/elasticsearch (for the Debian package) and /etc/sysconfig/elasticsearch (for the RPM package). You will need to edit the ES_PATH_CONF=/etc/elasticsearch entry in one of these files accordingly to change the config directory location.
]]>Mermaid支持多种图表的方向,语法如下:
1 | graph 方向描述 |
方向描述 | 含义 |
---|---|
TB | 从上到下 |
BT | 从下到上 |
RL | 从右到左 |
LR | 从左到右 |
即流程图中每个文本块,包括开始、结束、处理、判断等。Mermaid中每个节点都有一个id,以及节点的文字。
表述 | 说明 |
---|---|
id[文字] | 矩形节点 |
id(文字) | 圆角矩形节点 |
id((文字)) | 圆形节点 |
id>文字} | 右向旗帜状节点 |
id{文字} | 菱形节点 |
需要注意的是,如果节点的文字中包含标点符号,需要时用双引号包裹起来。 |
希望在文字中换行,请使用
替换换行
表述 | 说明 |
---|---|
> | 添加尾部箭头 |
- | 不添加尾部箭头 |
– | 单线 |
–text– | 单线上加文字 |
== | 粗线 |
==text== | 粗线加文字 |
-.- | 虚线 |
-.text.- | 虚线上加文字 |
使用以下语法添加子图表
1 | subgraph 子图表名称 |
使用fa: #图表名称#
的语法添加fontawesome
1 | graph TD; |
1 | graph TB |
1 | graph TD |
1 | graph BT |
1 | graph RL |
1 | graph LR |
1 | graph LR |
1 | graph LR |
1 | graph LR |
1 | graph LR |
1 | graph LR |
1 | graph LR |
1 | graph LR |
1 | graph LR |
前面两个-
,后面三个-
1 | graph LR |
或
1 | graph LR |
1 | graph LR |
或
1 | graph LR |
1 | graph LR |
1 | graph LR |
1 | graph LR |
文字里用引号避免一些特殊字符的错误。比如矩形节点里有()时就无法渲染,所以加上引号。
1 | graph LR |
可以使用 HTML 中的实体字符。
1 | graph LR |
1 | graph TB |
1 | graph TD; |
1 | graph LR |
1 | graph LR |
1 | classDef default fill:#f9f,stroke:#333,stroke-width:4px; |
定义一个名为 default 的类,节点没有指定特定样式类时,将都会应用这个样式类。
可以使用 Font Awesome 图标。语法 fa:icon class name。
1 | graph TD |
1 | sequenceDiagram |
如果不显示声明,参与者将根据第一次出现的顺序排列,如:
1 | sequenceDiagram |
第一条语句出现了两个参与者角色,而在这条语句中,Alice 在 John 之前,所以图中也是这个顺序。如果不想根据第一次出现的顺序来排,可以主动声明以定义顺序:
1 | sequenceDiagram |
可以给角色写一个简短的别名以方便书写。
1 | sequenceDiagram |
消息连线有六种样式。
有一个-
是实线,两个-
是虚线。
1 | sequenceDiagram |
1 | sequenceDiagram |
使用 +/-
的更方便的写法:
1 | sequenceDiagram |
可以嵌套:
1 | sequenceDiagram |
语法:Note [ right of | left of | over ] [Actor]。
表述 | 含义 |
---|---|
right of | 右侧 |
left of | 左侧 |
over | 在当中,可以横跨多个参与者 |
1 | sequenceDiagram |
over 可用于单独一个角色上,也可以用于相邻两个角色间:
1 | sequenceDiagram |
语法:
1 | loop Loop text |
语法:
1 | alt Describing text |
可选条件,比如在没有 else 分支的情况下使用,有点类似 java 中的 switch 的 default 分支,代表剩下所有情况。
1 | opt Describing text |
符号 | 含义 |
---|---|
start | 开始(圆角矩形) |
end | 结束(圆角矩形) |
condition | 判断(菱形) |
operation | 操作(直角矩形) |
inputoutput | 输入输出(平行四边形) |
** note:可以对符号自定义命名,如
1 | st=> start: 输入数据 |
注意: 冒号后一定要加一个空格!!!
下面表示各个图形和流程的串联,一个简单的->符号就好:
1 | # 下面是赋值语句 |
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|