随着系统复杂度的提高,一个迫切渴望的需求就是整个IT系统可以被分隔成多个小的,松散耦合的组件。这意味着整个IT系统应该在设计时就减少依赖,当一个组件发生变化或错误时,其他组件不应该受到影响或者导致别的组件不可用。

设计优良的接口

减少系统依赖的一个途径就是仅允许组件之间通过特定的跨平台接口交互,比如RESTful API。这种方式隐藏了技术实现的细节,这样团队就可以在不影响别的组件的情况下修改接口的具体实现。只要这些接口保持向下兼容,各个接口之间就是解耦的。

优良接口的实现方式

Amazon API Gateway提供完整的服务,让开发者可以轻易地在任何维度创建、发布、运维和监控API,它能解决海量API请求的所有相关工作,包括流量管理,认证和授权管理,监控管理以及API版本管理等。

服务发现 Service Discovery

微服务之间会有相互依赖关系,因为每个服务都可能会运行在多个实例上,所以需要想办法保证他们能够被定位到。在传统的架构中,前端可以通过写死后端服务的IP来实现服务发现,在云服务架构中,虽然这种方式也还能用,但是如果想要实现低耦合,那就应该要保证这些服务能够在无需预知技术实现细节的情况下被发现。暂且不谈隐藏技术细节,这样做的好处还包括随时可以调整架构的细节。如果你想充分利用云计算架构的弹性,那低耦合是非常必要的,云计算的弹性可以让你随时启动或者关闭实例。

服务发现的实现方式

部署在EC2上的服务很容易通过ELB实现负载均衡。因为每个负载均衡器都有自己的域名,这样你就可以把服务请求指向到一台稳定的终端上。结合DNS和Amazon Route53就可以在任何时刻修改任意节点

另一个实现途径就是利用“服务注册和发现中心”,这样就可以随时查询到服务的IP和端口号。因为这个中心成为组件之间的黏着剂,那么他就必须要保证高可用性和可信赖性。如果不使用负载均衡器,那么服务发现还需要负担起来诸如健康检查之类的工作。这种途径可以通过自己编程来实现,页可以使用开源工具比如Netflix Eureka, Airbnb Synapse, or HashiCorp Consul

异步

异步通信是服务间解耦的另一种方式,。这种模型使用在所有不需要实时响应的交互场合,它需要两个组件,一个是事件的生产者,另一个是事件的消费者,这两个组件之间不直接地点对点交互,而是通常通过一些持续存储的中间层来交互,常见的有消息组件SQS queue或者数据流组件Amazon Kinesis

这种方式不仅可以解耦组件,还可以增加系统的抗压能力和可用性。比如有一个组件从队尾读取消息,当系统重启时,消息依然能被重新恢复到队列中。这种方式还可以在前端访问的高峰期保护缺乏伸缩弹性的后台,并且可以找出消费者与生产者的平衡点。比如可以通过异步延迟处理,来避免在数据库很偶然的读写高峰期就得增加数据库性能,当然,也可以通过消息堆积情况来找出并提升整个请求链的薄弱环节,最终可以提高终端用户的使用体验。

异步的实现方式

  • 前端应用在SQS队列中插入消息,后端队列按照自己的节奏取出并处理这些消息。
  • 一个API生产事件,并将它加入到Amazon Kinesis streams,后端应用批量处理这些事件并再数据库中存入聚合数据。
  • 各种各样的系统都可以使用SWF来实现流程化的工作交互,这样可以避免他们之间的直接交互。
  • AWS Lambda fuctions可以消费来自各种aws资源的消息事件(比如Amazon DynamoDB update streams, Amazon S3 event notifications),在这些案例中,开发者甚至都不用操心队列和异步通信的具体实现,因为这些服务已经自带解决了。

容错 Graceful Failure

松散耦合的另一个方式是提升应用的组建件容错能力。通过增加系统宕机甚至组件通信失败等情况的容错能力,可以提升用户的体验。

容错的实现方式

当一个请求失败时,可以通过指数补偿(exponential backoff)或者Jitter strategy等策略来重试,也可以把他们存进队列稍后重试。对于前端交互,当请求失败的时候,当数据库服务不可用的时候,可以提供备用站点或者缓存内容,而不是完全的就请求失败。另外Amazon Route 53 DNS 的故障转移功能(failover feature)也可以检测你的网站服务器,并且可以在你的主站不可用的时候自动地将用户引导到备用服务器上。还可以通过拷贝一个静态的网站到S3上来实现容错。