如何做性能测试的问题下的答案
试着回答一下这个问题。 首先要划分系统类型:有状态还是无状态,业务系统还是存储系统。根据不同的业务场景,设立性能测试的目标:是要测 QPS,还是 TPS 还是 TPS,还是任何其他【性能】-从广义来讲,一个存储系统到底能够以多高的平均时延来管理大多的存储空间,可能也是性能的一种。 有了性能测试的目标,接下来就是拆解用例。如果把性能测试归为测试的话,测试就需要测试用例,测试用例只是用例的形式化表达。把用户的使用场景勾勒出来,把每一步拆解成的流程图或者时序图–我们已经得到了一个纸上的集成测试计划,只是没有跟性能挂上钩。 接下来就进入真正写测试用例的环节了。 我们的测试报告如果要涵盖足够立体的信息,则既要了解每一个环节/接口/API 的性能指标,又要了解整体的性能指标。 这个时候测试工具的覆盖面就很重要了。如果我们选择偏黑盒的测试工具,apache ab /JMeter,则我们的测试用例就要围绕着对外交互的 API写,也只能测到外围接口的性能。这样的测试用例写起来最简单,无需侵入任何内部代码中。 如果我们使用了 JMH 一类的工具,则可以自由编写对任何方法的测试用例。但需要对系统有非常...
log 的历史
Log:一种被低估的计算机科学基础抽象 在计算机科学中,log(日志)远不止是"打印调试信息"那么简单。从数据库的 WAL 到分布式系统的共识协议,从版本控制系统到区块链,log 作为一种 append-only 的有序记录序列,是贯穿整个计算机科学发展史的核心抽象之一。 LinkedIn 的前首席工程师 Jay Kreps 在其著名文章 “The Log: What every software engineer should know about real-time data’s unifying abstraction” 中指出:log 是一种比消息队列、数据库、文件系统更基础的抽象——后者都可以建立在 log 之上。 本文尝试梳理 log 这一抽象在不同技术领域中的演化脉络。 数据库中的 Log:WAL 与 Binlog WAL(Write-Ahead Logging) WAL 是数据库实现 ACID 特性的基石。其核心思想是:在修改数据页之前,先将修改操作写入日志。 WAL 的工作流程: 事务开始时,将修改操作(redo log entry)追加写...
JPA 的 id 生成策略
JPA 有一个@GeneratedValue注解,有一个strategy attribute,如 @GeneratedValue(strategy = GenerationType.IDENTITY)。 常见的可选策略主要有IDENTITY和SEQUENCE。 GenerationType.IDENTITY 要求底层有一个 integer 或者 bigint 类型的自增列( auto-incremented column)。自增列的赋值必须在插入操作之后发生,因为这个原因,Hibernate 无法进行各种优化(特别是 JDBC 的 batch 处理,一次 flush 操作会产生很多条insert 语句,分别执行)。如果事务回滚,自增列的值就会被丢弃。数据库在这个自增操作上有个高度优化的轻量级锁机制,性能非常棒。 MySQL 支持这种 id 生成策略, 使用 MySQL 应该尽量使用这个策略,即使它无法优化。 JPA 用它生成 id,会一条一条地插入新的 entity。 GenerationType.SEQUENCE 数据库有一个所谓的 sequence 对象,可以通过 selec...
Convention over Configuration over Programming
什么是 Convention over Configuration over Programming 在软件工程中,有一条重要的设计哲学层级: Convention over Configuration over Programming 约定优于配置,配置优于编程。 这条原则的核心思想是:能用约定解决的问题,就不要引入配置;能用配置解决的问题,就不要写代码。 它反映了软件设计中对复杂度管理的追求——越是高层次的抽象,使用成本越低,出错概率也越小。 三个层次的含义 Programming(编程) 编程是最灵活但成本最高的方式。开发者需要编写具体的代码逻辑来实现功能。每一行代码都是潜在的 bug 来源,都需要测试、维护和 review。编程适合处理那些真正需要定制化逻辑的场景。 Configuration(配置) 配置是介于约定和编程之间的中间层。通过外部化的配置文件(如 XML、YAML、properties 等),开发者可以在不修改代码的情况下改变程序行为。配置降低了修改成本,但引入了配置管理的复杂度——配置项越多,理解和维护系统的难度就越大。 Convention(约定) ...
重拾TCP/IP协议簇
TCP/IP 协议簇是互联网的基石,是每个工程师都应该掌握的知识。这篇文章将系统地回顾 TCP/IP 协议簇的核心内容。 OSI 模型与 TCP/IP 模型 OSI 模型将网络通信分为七层,而 TCP/IP 模型则将其简化为四层。虽然 OSI 模型是理论标准,但实际应用中 TCP/IP 模型更为广泛。 OSI 七层模型与 TCP/IP 四层模型对应关系 graph TB subgraph OSI七层模型 A[7. 应用层<br/>Application Layer] B[6. 表示层<br/>Presentation Layer] C[5. 会话层<br/>Session Layer] D[4. 传输层<br/>Transport Layer] E[3. 网络层<br/>Network Layer] F[2. 数据链路层<br/>Data Link Layer] G[1. 物理层<br...
Fabric 文档拾遗
基本名词解释 ledger 账本上一系列由事务驱动的状态迁移的记录。状态迁移是链码调用(调用即事务)的结果。这些记录是不可修改顺序的,因此也上抗篡改的。 每个channel有一个账本,但恐怕不只一个账本。 理论上账本是由产生它的链码的命名空间隔离开来的,不能直接被其他链码访问到。 chain 由包含一系列 transaction 的 block 通过hash-link(由散列值作为前驱指针的一种连接方式)组成的数据结构。 state database 记录各种 key 的 latest value。可以被认为上chain的indexed view,可以随时被从链上重建出来。 所以 Fabric 自己就有双层数据结构。 读写集语义 读集和写集搞不好是同一个事务里的数据结构(待查)。 12345678910111213<TxReadWriteSet> <NsReadWriteSet name="chaincode1"> <read-set> <read key="K1", versio...
Fabric 中的 peer
每个 peer 可以拥有若干个 chaincode,也可以拥有若干个 ledger,但并不是一开始就拥有的,而是逐渐被创建出来的。chaincode 一定会定义一个 asset,也就生成了 ledger。一个peer 可以拥有 ledger 而无 chaincode,可见也并不是必然由 chaincode 生成 ledger。比如同一个组织里面多个 peer,只有一个安装了 chaincode(只有这个 peer 可以当作 endorser),其它的peer一样可以拿到 ledger。 peer 的流程架构图大致上是: 为了预防有 peer 的数据不一致,有可能需要 client application 向多个 peer 进行查询。 channel 可以认为是一系列 peers 的逻辑组合,orderer 可以被认为是跨channel的。同一个 channel 的 peers 共享完全一样的账本。 不同的组织完全可以基于同样的账本copy,产生不同的 application。 Fabric 有 identity,identity 有 principal。 transactio...
Hyperledger Fabric 各个容器内环境
peer 容器 /opt/gopath/src/github.com/hyperledger/fabric/peer 虽然是WORKING_DIR,什么都没有。这个目录是/bin/bash永远的进入路径,不管在哪个目录退出,重新进入还是会进入这个路径。 /etc/hyperledger/fabric 12345678910# 原生的三个配置文件。所以修改peer的行为要通过环境变量来修改,让docker用COMMAND启动peer进程的时候吸收这几个配置文件和环境变量core.yaml# 这两个文件似乎不关peer的事情configtx.yamlorderer.yaml# 这两个文件夹要被外部的数据卷映射修改过来,实际上只能依赖于外部# 这个文件夹本质上还是 core.yaml 默认的 mspConfigPath 的值msptls /var/hyperledger/production 这个文件夹存放unix系统里面的动态程序数据。 123456# 它下面有打包好的CIP(chaincode install package)格式的链码 chaincodes/mycc.1.0。ch...
一个滚动重启的状态保存问题
很多时候滚动重启,都会导致状态丢失。比较好的设计方法是把服务本身设计成无状态的,然后在上游的服务上做好 failover,然后增加 standby server,让 sticky 数据 transmit 到 standby 机器上,让 request 失败以后可以自己由上游重传到 standby server。然后就可以滚动重启了。 这大部分场景下还要考虑幂等的问题。 这就看得出热配置热替换的重要性了。在大多数情况下,除了发布新的 feature 升级以外,都应该尽量用热配置来避免重启。
重读 Martin Fowler 的微服务论文原文
背景 Martin Fowler 和 James Lewis 于 2014 年发表的 “Microservices: a definition of this new architectural term” 是微服务架构领域最具影响力的文章之一。这篇文章并非提出微服务的概念(Netflix、Amazon 等公司早已在实践),而是对这一架构风格进行了系统性的定义和特征总结。 文章的核心论点是:微服务架构是一种将应用程序构建为 一组小型服务 的方法,每个服务运行在自己的进程中,通过轻量级机制(通常是 HTTP RESTful API)进行通信。 微服务也是面向服务的(Service-Oriented),但与传统 SOA 有本质区别。传统 SOA 倾向于将集成复杂度集中在 ESB(Enterprise Service Bus)中,试图用一个庞然大物来隐藏分布式系统的复杂性;而微服务则主张将智能放在端点(endpoint),保持通信管道的简单。 以下是对原文九个核心特征的重读和展开。 组件化(Componentization)与服务(Services) Fowler 在文中区分了两种组件...















