业务服务建模经验

概述

此处的“服务”主要指业务服务,中间件服务的设计大体一致,但是侧重点会稍有不同。我们将从以下几点描述一个规范的业务服务设计需要包含的内容:

  • 业务场景分析;

  • 业务领域分析;

  • 业务领域建模;

  • 系统间交互链路设计;

  • 系统内处理流程设计;

  • 系统内关键算法设计;

  • 系统接口设计;

  • 系统数据表设计;

  • 系统非功能设计:高可用性、高性能、安全性、伸缩性、弹性、可扩展性、可测试性、可观测性等;

服务设计原则

原则一:端到端业务场景驱动

解释:

按照端到端的业务场景进行产品逻辑梳理,确保业务场景形成闭环,按照闭环思维来识别出功能缺失点,及增强点。这些缺失点或增强点,就是服务设计中需要重要考虑的部分,服务设计必须要给出具体的方案来解决这些问题,方案可以是长期方案,也可能是短期方案。

实践经验1:深入理解自己所负责的业务领域,并且尽量多的了解电商各大业务领域

我们所处的行业属于电商行业,在电商领域中,有一系列常规的业务领域,如:商品、价格、库存、交易、履约、支付、账户账务、用户、商户、清结算、用户通知等,业务发展到今天这些领域基本都已经涉及,且有一定的历史积累,那么我们是否需要每次服务功能设计,都需要完整的从头到尾梳理一次这些领域呢?答案是没有标准答案,这取决于你所负责的产品需求大小及类型,我们希望每个领域负责人除了深入理解自己所负责的领域外,也需要理解整个电商系统中的其他领域,至少要知道其他领域的职责,及领域间的大概边界。这样有利于我们快速识别新业务需求支持需要影响的领域或服务模块。在这个“屁股决定脑袋”的时代,你所处的位置,决定了你的思维或处事方式。我们通常会只考虑自己职责内的事情,这并没有错,但是希望大家都形成大局观,哪怕不是自己职责内的事情,也有提醒及告知其他负责人的责任。

实践经验2:培养产品思维,站在产品逻辑、商业逻辑的角度换位思考产品需求背后的业务本质,更好的理解问题本质后,才能更好的设计系统逻辑

平时业务开发的需求通常来自于产品或运营,产品会设计产品逻辑及交互原型,与技术团队进行需求评审后,便由技术接手开发实现。在这个过程中,我们技术同学要养成尝试理解每一个需求解决的问题本质的习惯,在理解问题本质后,我们才能更好的设计出合理的系统逻辑。这也将直接影响我们后面做领域边界识别,领域模型设计,系统调用链路设计的合理性及扩展性。同时,在充分理解了业务本质后,还可以反向从技术角度判断产品逻辑的合理性。

原则二:先模型,再接口

业务服务通常最关键的两个东西就是:模型+接口。模型设计又是一个业务服务的重中之重,好的模型设计可以减少大量的开发工作,同时让代码的逻辑清晰度、可维护性大大提高,因此,我们总是要求大家花更多的时间先把领域模型分析和设计好,然后再定义系统接口。

可以做一个这样的类比,如果整个服务是一个人体结构的话,模型是人体的骨架,接口则是眼睛和嘴巴,逻辑则是血和肉。模型决定了系统的稳定性和扩展性,接口决定了沟通效率及准确性。

实践经验1:设计完领域模型后,再定义接口,尤其是面向UI的接口,定义完接口后可以直接与UI开发的同学一起评审并同步开发

先设计模型是为了让接口的定义更加准确和精炼,先定义接口再开发,是为了与UI开发同学一起理解需求并同步设计思路,同时还能同步进行开发,避免互相等待。

原则三:先功能,再非功能

这里的功能主要指业务功能,只有在满足了业务需求的情况下,考虑性能、可扩展、可伸缩等非功能才有意义,因为我们通常以功能需求首要目标进行设计。当然,非功能也是非常重要的,通常我们在做完功能设计后,还需要继续思考非功能设计,主要考虑的非功能点有:

  • 高性能:在固定硬件配置的条件下,系统设计的单机性能基线是多少(QPS、TPS、Latency、并发量),性能瓶颈在哪里,是否需要通过缓存、异步调用、算法优化、JVM调优等手段来优化性能、升级硬件配置等手段来提升性能,而因为性能优化带来的其他问题又有何种解决方案等都需要考虑。例如:使用了缓存来优化性能后,缓存和数据库中的数据一致性如何保证。

  • 高可用性:当一台服务宕机后,服务还可用吗,允许多少台同时宕机等。服务客户端如何做服务的Failover、Fallback、Failfast等,通常服务框架会帮我解决这些问题,例如,我们使用的spring cloud已经提供了Eureka、Hystrix、Ribbon等组件来完成服务的注册发现,负载均衡,失败超时重试,熔断降级等高可用功能。但是在引入其他中间件时,同样需要考虑这个问题,确保所有服务组件没有单点故障(SPOF)。

  • 伸缩性:分布式微服务架构的核心思维之一就是采用横向扩容的方式提升整个服务的吞吐能力,避免使用通过提升硬件资源的纵向扩容方式,因此,我们在服务设计时就需要考虑这点。伸缩性简单点来理解就是,当一台服务实例承担不了访问吞吐量后,通过多部署一到多台来支持。那么典型的方法就是:1)服务本身不要有状态,任何一台实例都可以接手服务请求处理;2)服务本身可以伸缩的同时,还需要数据库、缓存、磁盘等组件支持伸缩,因为最后这些访问压力到了下层存储层后可能还有伸缩的瓶颈;

  • 可观测性:服务的运维监控是日常运维非常重要的工作,目前我们主要的监控手段有:1)日志监控;2)性能监控;3)调用链监控;4)指标监控。采用的技术栈包括:Graylog、SkyWalking、Grafana、Prometheus、Spring Boot Actuator等。在设计过程中,只要按照标准的方式进行开发,就默认支持了可观测的能力。但是引入的第三方中间件,则需要考虑监控能力是否提供,或者能否被集成到现有监控体系中;

  • 可测试性:服务的测试包含单元测试和集成测试两种,后期服务都需要具备自动化回归测试的能力,以满足持续集成、持续发布的需求,这也就要求服务的依赖关系清晰简单,对于定时任务等具有灵活触发点等;

  • 安全性:服务接口及数据的安全性是一个很重要的考虑点,需要确保接口的授权控制;目前,我们希望通过服务的业务网关来统一控制外部接口的认证与授权,服务内的RPC调用则根据需求进行授权控制。在服务设计中,我们只要按照标准的认证授权方案实施通常都不会有问题;

  • 高扩展性:在设计服务内部实现时,需要尽可能的对业务概念、层级进行抽象,常规的做法有:1)通过SPI的方式支持未来可能的Service Provider,例如:支付通道对接、通知渠道对接等;2)通过Request、Response、Param、Info等DTO对象定义接口,同时支持可放置扩展参数的Map属性,采用“动静结合”的方式定义接口的输入参保证可扩展性;3)通过识别概念来定义枚举属性,扩展枚举的方式来支持更多概念的引入;4)通过固定逻辑与动态逻辑相结合的模式支持不同业务端的业务诉求,动态逻辑如:有限状态机定义、工作流定义、规则定义、脚本语言等方式实现;

  • 容量规划:通常数据存储都需要考虑容量规划,如:数据库、Elasticsearch、Redis、磁盘等,需要在理解了技术特点、业务现状,增长预期等前提下配置合理的硬件及软件容量,还需要考虑当容量不足时的扩容方案;

原则四:不做重复的事(DRY)

此原则为《The Pragmatic Programmer》书中描述的三大原则之一,对我们做系统设计同样适用。我们的解读是:

1)组件级别:要有组件复用的意识,通常对于常规的第三方中间件、工具包等都具备重用的价值,此时,我们在设计时首选使用已经有的组件或中间件,如果功能不满足,可以考虑升级或扩展。

2)代码级别:同样需要有组件复用意识,且有持续重构的意识和勇气,尽量将可以重用的工具方法、算法、实现逻辑等抽取成共享代码,便于重用避免多次重复开发,以提供代码的可维护性。

原则五:保持简单直接(KISS)

简单理解就是,用最简洁的方式实现某个功能。

实践经验1:只有真正理解了问题本质后,你才能抽象出合理的领域模型,在好的模型下实现逻辑通常会更简洁易懂;

原则六:你不需要它(YAGNI)

简单理解就是,不要过度设计,尽量只做明确要做的功能。对于那些“未来可能需要”的功能,如果不是特别明确的,都采用留下扩展空间的方式暂时不实现。真需要支持的时候,再评估工作量支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值