总体方案–测试驱动

手把手的教你微服务的开发。

  1. 数据库设计。
  2. JPA的使用
  3. 跑起来吧
  4. 测试

引出下一篇文章。

总体方案–测试驱动

项目背景

该项目为房地产开发商开盘时,电子化的选房(抢房)系统。用于替换传统的线下排队选房,其存在客户体验差,不够公开公平等问题。该项目在大量的开发商中有广泛的需求。 其中的”抢购场景”在大量其他业务中也有广泛应用。同时,该项目对系统正确性,稳定性,大流量处理能力也有较高的要求。

测试方案的设计

  1. 性能测试方案: JMeter, 2万并发, 4万TPS+, 同时操作。一台JMeter线程数为2000, 故设定20台JMeter集群。
  2. 可用性测试方案: 在性能测试的阶段,通过kill -9 掉某个微服务的单个实例,kill网关等验证可用性。

通过Docker部署来实现部署的快速伸缩

  1. Docker部署很快
    • Docker简介 see
    • Docker-machine (与ansible功能相近,但更简单)
    • Docker集群
    • Docker的私有repository 2 网关的伸缩-nginx 3 数据层的伸缩,水平伸缩(redis集群)

#关于部署伸缩有趣的结论

  1. 数据库的性能要先优化,不然数据库性能一定是先成为瓶颈的。
  2. Zuul网关100线程并发时,就会出现异常了。我们的edge-Service 2万网关仍然不会出错。
  3. Edge-Service有默认的限流动作,这个限流动作,可以通过多个edge-service来改善。
  4. 2万并发,4W TPS,一个edge-service性能就能达标,不需要再排脂nginx.
  5. 重试配置对可用性提高立杆见影。

现代电商的特点

  • 电商也是商业,商业的本质是竞争,竞争的本质是业务模式的不断迭代着优化和创新,电子商务的迭代速度远快于传统商业,业务快速迭代的过程和结果,均让技术体系的迅速复杂化。
    • 业务复杂化举例:
      1. 需要适配更多的前端:PC网页,手机网页,IOS APP, Andriod APP, 微信公众号,微信小程序,支付宝小程序,京东,淘宝,天猫商铺 … 这个列表还可能不断增长,客户端很多时候就是渠道的代名词,渠道的多少正比与获客的多少,这个是竞争力的一部分,所以不可避免对接的客户端会越来越多。
      2. 电商业务逻辑本身越来越复杂。包括关键的运营手段:优惠活动越来越复杂,组合越来越多…这些复杂的优惠组合甚至直接催生了像”什么值得买”类似优惠爆料整理网站, 电商业务本身也在不停的复杂化,预售,抢购,拍卖等等….
      3. 物流业务处理也变得更加复杂,需要对接多个物流供应商上,多个仓储,如果是出海的电商,还会面临不同货币,关税等的问题。
      4. 售后的对接。售后也是电商业务的主战场之一,售后业务可能带来收入也极大的影响口碑。
      5. 商品采购和库存管理也日益复杂,多个销售渠道,和售后渠道的组合有时甚至让获取当前的准确的销售情况都非常困难,电商业务通常还有预测的需求,根据预测情况提前备货,为各地的仓储提前建立库存。
    • 传统单体架构遭遇日趋复杂的电商业务所面临的困难
      1. 过度的复杂性对开发者的要求大大提高,无论是开发新业务,还是bug修正。保证业务按时,按质的交付,对开发者来说变成了有极大焦虑感的事情。焦虑感的提高,会降低工作的效率和质量。复杂度还是不断累积,陷入恶性循环。
      焦虑的程序员

      开发人员是软件过程最重要的参与者。对于开发者,没有开发者能理解一个复杂的单体系统的全部,因此对问题的修复和新功能的开发变成了一件耗时,困难,焦虑,需要运气加持的一件苦差。

      1. 对于项目管理者极大增加了成本和进度风险。一方面对于要勉强维持复杂的系统,需要招聘更优秀的的开发人员。而招聘本来就是件困难且具有高度不确定性的事情。同时,即使在项目划分为多个项目组并使用scrum等 敏捷开发实践,为了保证项目集成。所有的敏捷开发团队还是需要在同样的进度节奏上做特性开发,code freeze,测试,集成测试,部署等等,任何一个团队延误会影响整个发布计划。这给项目管理带来了巨大挑战,不同子项目组之间的依赖集成关系也会给项目管理组带来巨大的负担。
        焦虑的程序员
      2. 交付的可靠性得不到保证

      3. 性能难以扩展 应用的不同部分对资源的的性能要求是非常不同的。如有些部分需要大内存,快速访问,比如应用有自己的大型缓存。有些部分需要数据的高速持久化,需要高IOPS。比如事务的提交。有些部分是CPU密集性的,需要在高CPU的性能机器上需要部署多份比如推荐系统。 对于单体应用,需要以所有部分的对资源不同属性的最高要求为标准,并且以对机器数量最高的要求为标准。对上面的例子,你需要多台大内存,高IOPS, 高cpu的机器才能部署,但面对突增的流量时,也没有办法。
      4. 重构无法进行,技术栈几乎无法更新。无法享受技术发展的红利

解决方案–微服务架构

  • 微服务架构的解决上述实践问题方法实质上就是我们一直在说的”高内聚,低耦合”的策略进一步实现。微服务是进程级别的解耦合,把应用再划分成更小的能独立开发部署的子应用,是最高级别的接耦。
  • 理解”独立子应用”,最高级别,这两个关键词非常重要,你可以回答这样的问题,在微服务架构中,是一个微服务对应一个数据库,还是多个微服务对应一个数据库。
  • 微服务架构能解决的问题总结:
    1. 通过架构影响习惯,解决复杂性问题
    2. 解决项目质量属性里面的非功能性属性:包括可维护性,可扩展性,可测试性,低成本,快速交付。

      电商抢购场景的分析

      1. 电商抢购场景是复杂的,既要保证抢购时,系统的响应速度,和吞吐速度。所以需要对抢购的业务代码做大量的优化,改动。同时如果在改动中引入了BUG,因为抢购场景成交巨大,所以Bug的影响巨大。 这样的特性微服务架构,可以让抢购的微服务,和系统的其他部分更彻底的隔离。所以微服务架构,对这样的场景减少了风险的情况。
      2. 抢购场景对性能的要求较高,通常需要对抢购的模块使用更高性能的硬件。通过微服务将其隔离出来。可以尽量节省成本。
      3. 抢购场景对性嫩的伸缩性要求较高,通常的场景是,平时用较少的硬件基础设置,等到快要举行抢购的前期,扩容。

微服务和数据库的关系是怎么样的?

  • n个微服务对应对应1个数据库?
    • 坏处
      1. 破坏了封装性,微服务之间希望只经由”一个单纯的”的接口界面相互。这样跟方便管理。
      2. 封装性的破坏导致不容易做出”高内聚,低耦合“的设计。
      3. 封装性的破坏还可以衍生出其他的坏处,这里不一一列举。….等。
      4. 数据库性能上没有水平扩展。数据库的配置和硬件无法根据不同部分数据的不同访问的特性进行分别调优。
    • 好处
      1. 可以利用数据库本地事务,避免复杂的分布式事务处理。编程简单。
      2. 无状态的服务至少做了拆分(进程级别的解耦合)。所以服务层能享受进程接耦的好处。(适配不同的硬件,更好的容错)
  • 1个微服务对应n个数据库?
    • 坏处
      1. 少一个数据库性能没有水平扩展。
    • 好处
      1. 少一个可以利用数据库本地事务。
  • 1个微服务对应1个数据库?(或0个)
    • 坏处
      1. 再少了一个破坏了封装性。
    • 好处 没有变化。

关于贯彻微服务间的低耦合?有什么模式和技术?

  • 原则:耦合就发生在一层,一般应该是代码层。杜绝在数据层,其他层面发生耦合。好处:进一步减少耦合的复杂度,方便测试。代码的接口这些语言构建也比较容易描述清晰的耦合关系。
  • 微观层面:耦合就是自己有哪些接口会被其他微服务调用, 自己会调用其他微服务的哪些接口。至少放在各自同一个包下。配图。

我们对微服务间(进程间)通讯的要求是是什么?

  • 可靠。大部分微服务的消息通信都有这个要求,极少部分没有。
    • 重试机制。幂等性。
    • 降级措施: 隔离, 熔断, 容错。
  • 快速。不是说有的RPC都有快速的要求,比如某些事件订阅式的。
    • 降级措施:
    • 超时机制.

微服务间异步通信

  • 好处
    • 异步通信,批量处理,更有效率。
    • 异步通信本省节省了线程资源,效率也更高。你能想象没有中断的CPU吗?
    • 异步通信可靠性更高。
  • 坏处:
    • 编程更复杂。
    • 可能响应事件会变长。
    • 经过的进程更多,协议栈更深,也影响效率。

ES-5 学习总结

Javascript 原型链