开发经验积累

开发经验积累。一些套路、一些开发尝试、一些开发规约。

1. 一些事情

1.1 代码优化

1.1.1 代码优化的目标

  • 减小代码的体积
  • 提高代码运行的效率

1.1.2 坏代码可特征

  • 代码可读性差,无基本编程规范;
  • 对象生成过多或生成大对象,内存泄露等;
  • IO 流操作过多,或者忘记关闭;
  • 数据库操作过多,事务过长;
  • 同步使用的场景错误;
  • 循环迭代耗时操作等。

来自 https://developer.ibm.com/zh/articles/j-lo-performance-tuning-practice/

2. 一些指标

2.1 简介

  • 同比:2020和2019对比,同比是由year-on-year翻译过来的
  • 环比:2020年8月和2020年7月对比,环比是由month-on-month翻译过来的
  • TPS(transaction per second)
  • qps
  • RT(response time)
  • SLA(Service level agreement)

2.2 详解

2.2.1 深度剖析什么是 SLI、SLO和SLA?

云计算时代,各大云服务提供商都发布有自己服务的SLA条款,比如Amazon的EC2和S3服务都有相应的SLA条款。这些大公司的SLA看上去如此的高达上,一般是怎么定义出来的呢?本文就尝试从技术角度解剖一下SLA的制定过程。

说SLA不能不提SLO,这个是众所周知的,但是还有一个概念知道的人就不多了,那就是SLI(Service Level Indicator),定义一个可执行的SLA,好的SLO和SLI是必不可少的

再有就是SLI/SLO/SLA都是和服务联系在一起的,脱离了服务这三个概念就没有什么意义了。

2.2.1.1 Service什么是服务?

简单说就是一切提供给客户的有用功能都可以称为服务。

服务一般会由服务提供者提供,提供这个有用功能的组织被称为服务提供者,通常是人加上软件,软件的运行需要计算资源,为了能对外提供有用的功能软件可能会有对其他软件系统的依赖。

客户是使用服务提供者提供的服务的人或公司。

2.2.1.2 SLI

SLI是经过仔细定义的测量指标,它根据不同系统特点确定要测量什么,SLI的确定是一个非常复杂的过程。

  • SLI的确定需要回答以下几个问题:
    • 要测量的指标是什么?
    • 测量时的系统状态?
    • 如何汇总处理测量的指标?
    • 测量指标能否准确描述服务质量?
    • 测量指标的可靠度(trustworthy)?
2.2.1.2.1 常见的测量指标有以下几个方面:
  • 性能
    • 响应时间(latency)
    • 吞吐量(throughput)
    • 请求量(qps)
    • 实效性(freshness)
  • 可用性
    • 运行时间(uptime)
    • 故障时间/频率
    • 可靠性
  • 质量
    • 准确性(accuracy)
    • 正确性(correctness)
    • 完整性(completeness)
    • 覆盖率(coverage)
    • 相关性(relevance)
  • 内部指标
    • 队列长度(queue length)
    • 内存占用(RAM usage)
  • 因素人

    • 响应时间(time to response)
    • 修复时间(time to fix)
    • 修复率(fraction fixed)
  • 下面通过一个例子来说明一下:hotmail的downtime SLI

    • 错误率(error rate)计算的是服务返回给用户的error总数
    • 如果错误率大于X%,就算是服务down了,开始计算downtime
    • 如果错误率持续超过Y分钟,这个downtime就会被计算在内
    • 间断性的小于Y分钟的downtime是不被计算在内的。
2.2.1.2.2 测量时的系统状态,在什么情况下测量会严重影响测量的结果
  • 测量异常(badly-formed)请求,还是失败(fail)请求还是超时请求(timeout)
  • 测量时的系统负载(是否最大负载)
  • 测量的发起位置,服务器端还是客户端
  • 测量的时间窗口(仅工作日、还是一周7天、是否包括计划内的维护时间段)
2.2.1.2.3 如何汇总处理测量的指标?
  • 计算的时间区间是什么:是一个滚动时间窗口,还是简单的按照月份计算
  • 使用平均值还是百分位值,比如:某服务X的ticket处理响应时间SLI的
  • 测量指标:统计所有成功解决请求,从用户创建ticket到问题被解决的时间
  • 怎么测量:用ticket自带的时间戳,统计所有用户创建的ticket
  • 什么情况下的测量:只包括工作时间,不包含法定假日
  • 用于SLI的数据指标:以一周为滑动窗口,95%分位的解决时间
2.2.1.2.4 测量指标能否准确描述服务质量?
  • 性能:时效性、是否有偏差
  • 准确性:精度、覆盖率、数据稳定性
  • 完整性:数据丢失、无效数据、异常(outlier)数据
2.2.1.2.5 测量指标的可靠度
  • 是否服务提供者和客户都认可
  • 是否可被独立验证,比如三方机构
  • 客户端还是服务器端测量,取样间隔
  • 错误请求是如何计算的

2.2.1.3 SLO

SLO(服务等级目标)指定了服务所提供功能的一种期望状态。SLO里面应该包含什么呢?所有能够描述服务应该提供什么样功能的信息。

服务提供者用它来指定系统的预期状态;开发人员编写代码来实现;客户依赖于SLO进行商业判断。SLO里没有提到,如果目标达不到会怎么样。

2.2.1.3.1 SLO是用SLI来描述的,一般描述

比如以下SLO:

  • 每分钟平均qps > 100k/s
  • 99% 访问延迟 < 500ms
  • 99% 每分钟带宽 > 200MB/s
2.2.1.3.2 设置SLO时的几个最佳实践
  • 指定计算的时间窗口
  • 使用一致的时间窗口(XX小时滚动窗口、季度滚动窗口)
  • 要有一个免责条款,比如:95%的时间要能够达到SLO

如果Service是第一次设置SLO,可以遵循以下原则

  • 测量系统当前状态
    • 设置预期(expectations),而不是保证(guarantees)
    • 初期的SLO不适合作为服务质量的强化工具
  • 改进SLO
    • 设置更低的响应时间、更改的吞吐量等
    • 保持一定的安全缓冲
    • 内部用的SLO要高于对外宣称的SLO
  • 不要超额完成
  • 定期的downtime来使SLO不超额完成

设置SLO时的目标依赖于系统的不同状态(conditions),根据不同状态设置不同的SLO:总SLO = service1.SLO1 weight1 + service2.SLO2 weight2 + …

2.2.1.3.4 为什么要有SLO,设置SLO的好处是什么呢?
  • 对于客户而言,是可预期的服务质量,可以简化客户端的系统设计
  • 对于服务提供者而言
    • 可预期的服务质量
    • 更好的取舍成本/收益
    • 更好的风险控制(当资源受限的时候)
    • 故障时更快的反应,采取正确措施
2.2.1.3.5 SLO设好了,怎么保证能够达到目标呢?

需要一个控制系统来:

  • 监控/测量SLIs
  • 对比检测到的SLIs值是否达到目标
  • 如果需要,修证目标或者修正系统以满足目标需要
  • 实施目标的修改或者系统的修改

该控制系统需要重复的执行以上动作,以形成一个标准的反馈环路,不断的衡量和改进SLO/服务本身。

我们讨论了目标以及目标是怎么测量的,还讨论了控制机制来达到设置的目标,但是如果因为某些原因,设置的目标达不到该怎么办呢?

也许是因为大量的新增负载;也许是因为底层依赖不能达到标称的SLO而影响上次服务的SLO。这就需要SLA出场了。

2.2.1.4 SLA

SLA是一个涉及2方的合约,双方必须都要同意并遵守这个合约。当需要对外提供服务时,SLA是非常重要的一个服务质量信号,需要产品和法务部门的同时介入。

SLA用一个简单的公式来描述就是: SLA = SLO + 后果

  • SLO不能满足的一系列动作,可以是部分不能达到
  • 比如:达到响应时间SLO+未达到可用性SLO
  • 对动作的具体实施
  • 需要一个通用的货币来奖励/惩罚,比如:钱

SLA是一个很好的工具,可以用来帮助合理配置资源。一个有明确SLA的服务最理想的运行状态是:增加额外资源来改进系统所带来的收益小于把该资源投给其他服务所带来的收益。一个简单的例子就是某服务可用性从99.9%提高到99.99%所需要的资源和带来的收益之比,是决定该服务是否应该提供4个9的重要依据。

3. 一些术语

3.1 简介

  • 恢复&逃逸
  • CAP:根据CAP(Consistency一致性、Availability可用性、Partition tolerance分区容错性)定理,在一个分布式系统中,CAP三者不能兼得。
  • Sticky Session
  • Data Locality
  • CAP Theorem
  • AP/CP System
  • Cluster Membership
  • Consensus Protocol
  • Gossip protocols
  • Consistent Hashing
  • Back Pressure
  • DHT(Distributed Hashtable)
  • StopTheWorld(Garbage Collection)
  • Site Reliability Engineering站点可靠性/稳定性工程师
  • SPI ,全称为 Service Provider Interface,是一种服务发现机制

3.2 详解

4. 工程相关

4.1 领域模型

领域模型分为4类:VO、DO、PO、DTO

  • VO(View Object):视图对象,用于展示层,它的作用是把某个指定界面(或组件)的所有数据都封装起来。
  • DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的逻辑实体。
  • PO(Persistent Object):持久化对象,它跟数据库持久化(通常是关系数据库)的数据结构形成一一对应的映射关系,如果持久层是关系数据库,那么数据表中的每个字段(或若干个)都对应PO的一个(或若干个)属性。
  • DTO(Data Transfer Object):数据传输对象,其概念来源于J2EE的设计模式,原来是为 EJB 的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载。

4.2 幂等性

接口幂等性是指用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。解决思路:

  • insert前先select:该方案不适用于并发场景
  • 加悲观锁
  • 加乐观锁
1
2
3
select id,amount,version from user id=123;
-- 假设查到的version等于1
update user set amount=amount+100,version=version+1 where id=123 and version=1;
  • 加唯一索引
  • 建防重表:有时候表中并非所有的场景都不允许产生重复的数据,只有某些特定场景才不允许。写表的时候在同一个事务中向防重表中也写入。
  • 根据状态机判断
  • 加分布式锁
1
2
3
4
-- 目前主要有三种方式实现redis的分布式锁:
-- setNx命令
-- set命令
-- Redission框架
  • 获取token:第一次请求获取token,第二次请求带着这个token,完成业务操作。

5. 编程思想

  • justifiability 和 affordability 没想出来怎么翻译。Justifiability 不完全是”必要性“,还带有一点“合理性”的味道,比如我们会说 “one wrong doesn’t justify another”,别人做错了,不等于你就可以做错。Affordability翻译成 ”可行性“也不太贴切。”可行性“ 更应该翻译成 feasibility、viability 或者 practical,affordable 带着一层“我买得起” 的味道。

  • “Write code that is easy to delete”。增加代码的复用其实也在增加代码的依赖。如果有一段代码,它被很多代码依赖,那么要修改这段代码的风险是非常高的,“牵一发而动全身”。而且,不仅仅当我是一个QA的时候我持这个观点,后来我做开发了我也持这个态度。我copy/paste一段代码到我自己的模块里面来,别人如果改了他那里的代码,我肯定不会受到影响,这样也节省了我自己的工作量。

  • “Duplication is far cheaper than the wrong abstraction”。正确的抽象/封装的确不是件容易的事,做的不好的抽象/封装反而用起来更辛苦。程序员往往比较自信,总觉得自己设计出来的封装、抽象、对象模型是很优秀的,所以我觉得的确需要用“Duplication is far cheaper than the wrong abstraction”这样一句话来counter-balance一下。
-------------本文结束感谢您的阅读-------------
我知道是不会有人点的,但万一有人想不开呢?