分类目录归档:系统设计

The Twelve-Factor App

简介

如今,软件通常会作为一种服务来交付,它们被称为网络应用程序,或软件即服务(SaaS)。12-Factor 为构建如下的 SaaS 应用提供了方法论:

  • 使用标准化流程自动配置,从而使新的开发者花费最少的学习成本加入这个项目。
  • 和操作系统之间尽可能的划清界限,在各个系统中提供最大的可移植性。
  • 适合部署在现代的云计算平台,从而在服务器和系统管理方面节省资源。
  • 将开发环境和生产环境的差异降至最低,并使用持续交付实施敏捷开发。
  • 可以在工具、架构和开发流程不发生明显变化的前提下实现扩展。

这套理论适用于任意语言和后端服务(数据库、消息队列、缓存等)开发的应用程序。

继续阅读

Advertisements

DevOps的三种方式

前言

这篇博客中提到的“三种方式“源自 《DevOps Handbook》 及《凤凰项目》(The Phoenix Project: A Novel About IT, DevOps, and Helping Your Business Win.),这三种方式描述了构成 DevOps 的理论框架、流程、实践及价值观和哲学。

感谢《Lean IT》的作者 Mike Orzen 为此文提供宝贵建议。

三种方式

下文将介绍三种模式及在该种模式指导下的 DevOps 实践。

第一种方式: 系统思考

第一种方式强调全局优化,而非局部改进。— 大到部门职能划分(例如研发部和运维部门),小到个人(开发和系统工程师)。

这种方式将关注点放在整个业务价值流上。换句话说,整个团队应该关注在从需求被定义到开发,再到运维这个过程,直到价值被以服务的形式交付给最终用户。

将这种方式带到实践中的产出便是永远不要将已知的缺陷传递到下游工作,永远不要为了局部优化影响了整体价值流交付,总是为了增加价值流动努力,永远追求对架构的深刻理解。

涉及到这种方式的实践有:

  • 所有环境和代码使用同一个仓库,将软件包纳入版本管理
  • 团队共同决定发布流程
  • 保持 DEV、TEST、PRODUCTION 环境的一致性
  • 自动化回归测试
  • 小步提交,每日部署;而不是一次部署大量变更
  • 更快、更频繁发布

第二种方式:经过放大的反馈回路

第二种方式是创建从开发过程下游至上游的反馈环。几乎所有的流程改进都是为了从时间上缩短和从覆盖面上放大反馈循环,从而可以不断地进行必要的改正。

第二种方式的产出是关注到价值流中所有涉及到的用户,包括价值流内部和外部的,缩短和放大反馈回路,并且可以随时定位到需要改进的地方。

涉及到这种方式的实践有:

  • 代码审查及配置变更检查
  • 有纪律的自动化测试,使许多同时的小型敏捷团队能够有效地工作
  • 尽早设置监控预警
  • 修复 bug 为团队最高优先级
  • 团队成员之间高度互相信任
  • 团队之间保持沟通和良好合作

第三种方式:持续做试验和学习的文化

第三种方式提倡持续做试验,承担风险、从失败中学习;通过反复实践来达到精通

我们需要实验和冒着失败的风险,及时不断地尝试将我们置于一个危险的境地,我们要通过反复试错来掌握使我们远离危险的技能。

第三种方式的输出为为改善日常工作分配时间、奖励团队冒险精神,将错误人工引入系统以提高系统健壮性。

最具有代表性的就是 Netfilx 的 Chaos monkey ,Netflix 在他们的生产环境搭建一个服务用于定时随机关闭服务器,用以模拟服务器正常损坏或服务异常,他们的系统长期在这种环境下运行,“服务器故障”成为系统每日都要面临的问题,因此当服务器真的以外故障时不会对系统整体造成任何的影响。

译者后记

全局优化、快速反馈、鼓励失败。我们发现其实敏捷、精益、持续交付、DevOps中间有很多相似的东西。

参考资料: https://es.slideshare.net/SonatypeCorp/devops-connect-josh-corman-and-gene-kim-discuss-devopssec

http://itrevolution.com/the-three-ways-principles-underpinning-devops/

转发自:@duyidong

系统权限控制体系

在 Web 应用开发中,安全一直是非常重要的一个方面。安全虽然属于应用的非功能性需求,但是应该在应用开发的初期就考虑进来。比如我们开放的功能页面需要登录授权之后才能访问,一些功能需要具备特定权限的人才能操作;再比如我们开放了数据API接口,如果不做访问控制,那么任何人都可以调用,当被不法分子操作时将给我们带来巨大的麻烦。那么在Java 整个体系中访问控制是否有一套理论技术支撑呢,我们是否可以做一个通用性的访问控制系统来完成分布式系统架构下的复杂的权限控制?接下来会一一介绍。

访问控制的本质:

系统权限控制 本质上是访问控制(Access Control),那访问控制的本质又是什么呢?其实就是合法的访问受保护的资源,通俗的解释就是“【谁】是否有可以对某个【资源】进行某种【操作】”;可以看出访问控制的三个基本要素:主体(请求实体)、客体(资源实体)、控制策略(属性集合);

访问控制需要完成的两个任务:

  1. 识别和确认访问系统的用户;
  2. 决定该用户可以对某一系统资源进行何种类型的访问;

继续阅读

应用架构设计原则

软件系统架构设计原则就是把我们在各种场景下的架构设计进行抽选化提取公共特征形成过一定的方法论,这些方法论是经过严格推敲并具备移植性的,我们在设计系统时遵从这些设计规则可以为我们的体统提供更高的扩展性、稳定性。

抽象原则

各平台(含基础设施、中间件技术服务、各层业务服务等)需要通过合理地抽象,将内部信息、处理与扩展能力聚合成标准的服务于扩展接口,并通过统一的形式提供给使用者,屏蔽内部的实现与运行细节。

继续阅读

商品打标签设计踩过的坑

问题一:同步操作,导致批量处理过慢,锁超时

现象:在批量打标过程中,由于之前设计的是同步操作,一次打标的商品数过多时,导致执行时间较长,运营以为操作失败,多次重新导入和点击,导致系统出现不可预知情况。
原因:之前为了数据的一致性,对打标过程使用了事务处理,所以当批量打标的时候,相当于对这批数据都进行了行锁,其它操作这些数据的请求都会等待事务的提交,当等待超时,就报错了,“Lock wait timeout exceeded; try restarting transaction”(排查过程)。
代码:5F6F0B52-DC6D-4208-810B-596151DDB267
解决方案:分析业务非强一致性,允许出错,故将事务去掉,将任务修改为异步任务,引入了自动重试机制,并将出错的任务加入到异常队列,用户可以看到那些是失败的任务,并主动进行重试(一般失败原因为商品主图太大,比如20~30M,导致打标失败)。
总结:
  • 系统设计前缺乏整体性思考,明知道同步操作会导致业务处理缓慢,但未进行主动改进。
  • 对项目编写完整的技术方案还是有必要的,有助于梳理现有业务的特性,并为之提供特定的解决方案。

继续阅读

高并发系统 之 降级特技

高并发场景三把利器保护系统:缓存、降级、限流。当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。本文将介绍一些笔者在实际工作中遇到的或见到过的一些降级方案供大家参考。

降级按自动化程度分类:

  1. 系统根据关键数据自动降级;
  2. 人工通过配置进行手工降级;

自动开关降级指标:

  1. 超时降级;
  2. 故障降级;
  3. 限流降级;

超时降级:

当访问的数据库/http服务/远程调用响应慢或者超时(比如dubbo客户端超时),且该服务不是核心服务的话可以在超时后自动降级;比如商品详情页上有推荐内容/评价,但是推荐内容/评价暂时不展示对用户购物流程不会产生很大的影响;对于这种服务是可以超时降级的。如果是调用别人的远程服务,和对方定义一个服务响应最大时间,如果超时了则自动降级。

故障降级:

比如要调用的远程服务挂掉了(网络故障、DNS故障、http服务返回错误的状态码、rpc服务抛出异常),则可以直接降级。降级后的处理方案有:默认值(比如库存服务挂了,返回默认现货)、兜底数据(比如广告挂了,返回提前准备好的一些静态页面)、缓存(之前暂存的一些缓存数据)。

限流降级:

当我们去秒杀或者抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时开发者会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)。

手动开关降级:

在大促期间通过监控发现线上的一些服务存在问题,这个时候需要暂时将这些服务摘掉;还有有时候通过任务系统调用一些服务,但是服务依赖的数据库可能存在:网卡被打满了、挂掉了或者很多慢查询,此时需要暂停下任务系统让服务方进行处理;还有发现突然调用量太大,可能需要改变处理方式(比如同步转换为异步);此时就可以使用开关来完成降级。

 

 

降级按照功能分类:

  1. 读服务降级;
  2. 写服务降级;

读服务降级的思路:

1、开关集中化管理:通过推送机制把开关推送到各个应用(比如我们使用Diamond实现动态配置变更);
2、后端读缓存降级(降级到读缓存、降级到走静态化):比如只读本地缓存、只读分布式缓存、或者只读一个默认的降级数据;
3、前段Nginx请求降级:将开关前置到nginx的接入层,从nginx直接返回一些数据请求,请求打不到后端应用。
举例:
①我们的详情页静态HTML数据默认缓存时间是6min,超过6min就会查询DB进行刷新缓存,如果后端构造详情页的服务挂了,此时缓存又都失效了,就会导致页面出不来,所以我们可以在这里做一个缓存降级策略,如果后端服务挂了,我们是允许使用缓存数据的;用户浏览已经过期的详情页的静态数据比不能浏览要好。
②当一些页面请求量非常大时,一些请求直接在Nginx上做了开关拦截,返回固定数据,让主流程可以不受到影响。
③订单列表页中不同状态订单数查询,流量较大的时候降级为只走缓存;
fengqu-orderlist-count

写服务降级的思路:

写服务在大多数场景下是不可降级的,不过可以通过一些迂回战术来解决问题。比如将同步操作转换为异步操作,或者限制写的量/比例。
举例:
①正常情况可以同步扣减库存,在性能扛不住时降级为异步;另外如果是秒杀场景可以直接降级为异步,从而保护系统。

 

参考:

商品系统 之 类目及其属性

背景:为了构建以供应链为中心的可售商品中心和已供应商后台为中心的原始商品池体系,需要将商品、类目、属性、品牌纳入供应链体系之中;在商品运营中,类目和类目属性的运营尤为重要,对引导用户成交有非常大影响,所以为了丰富商品类目&属性,进行商品类目、属性的构建;在丰富了商品类目属性后,一些技术数据就可以落在类目上,比如商品的描述属性、规格属性、管理属性(毛利率等),可以通过这部分数据快速创建标准化的SPU、SKU数据。

一、了解类目属性在运营中的地位与发展:

淘宝类目的发展历史:

二、淘宝商品类目属性体系结构:

taobao-category-history

三、类目设计:

类目在一般电商系统中会分为前台类目和后台类目,前台类目可以关联到任何一级的后台类目中,前台类目主要用于有利于前段销售,变动频率比后台类目高,后台类目就像标准化的商品分类,一般定义之后不会进行变更。
后台类目的结构设计:
 category-table-design
后台类目表设计需要做到灵活的可扩展性都会做到无限层级,所以会使用parent_id、parent_name 、root_id、root_name的方式。
增加minimum_scope 和 maximum_scope字段是为了快速查找出节点类目。
增加 leaf_node 字段是因为一些类目或属性在一些场景下需要区分是否是叶子类目。
后台类目主要需要解决的技术问题是 快速的查询性能,通过子类目查询所有上游类目可以通过parentId去查询,如果期望通过父类目查询所有的子类目,一个简单sql是无法完成的,这个时候就需要通过scope实现,在每个类目上计算最小值和最大值,这样就可以通过最小值和最大值这个范围区间查出所有的子类目了。结构如下:
category-scope