温故而知新,每次静下心来回头深刻反思过去都会有新的认识和收获。相较多年前更具商业气味和务虚的SOA,随着领域驱动设计、持续交付、容器技术、自动化运维、云计算等渐渐成熟,微服务的落地让人们逐渐感受到它真实的存在。要想做好微服务的架构工作,首先需要站在「上帝视角」好好审视微服务的方方面面。
所谓微服务是指一些协同工作的小而自治的服务,可以独立部署,支持异构系统,服务间松散耦合,它将软件的重用提升到了一个新的层面。微服务的拆分通常基于领域模型,对业务抽象进而划分出服务边界,实际应用中还可能根据性能要求等具体使用情况做进一步的拆分。
微服务架构旨在解决大规模团队并行开发效率的问题,以支持业务的快速迭代和产品交付。但没有银弹,微服务同样需要面对一系列的挑战,分布式事务、测试复杂性、运维复杂性、代码重复等。因此微服务架构并不适合小规模团队和业务比较简单应用,太早投入可能会影响到业务的正常开展,复杂的技术基础设施也会把团队拖垮,单块应用更适合初创团队。随着业务规模的不断扩张和变得越来越复杂,研发团队达到一定的规模,架构师对业务领域也越来越清晰,可以考虑由单块应用架构逐步演化到微服务架构。单块应用拆分需要找到合适的剥离点,依次将数据库等依赖剥离,最终将应用程序拆分出来。
落地微服务架构首先需要完成组织架构的重组,即要符合康威定律,系统架构与团队组织架构保持一致。传统的根据职能划分团队的方式,沟通协调成本高,反馈周期较长,研发效率低,对业务的支持较慢。新型的基于微服务的跨职能组织模式,每条业务线都有各自产品、研发、测试的专家,形成端到端的闭环,可以更快速的迭代以响应业务的需求。围绕微服务组织团队,团队规模Amazon提出了两个披萨的原则,建议12个人左右,完成从架构、设计、开发、测试、部署、支持,再到架构的闭环。构建系统的组织松耦合,其构建的系统则倾向于更加模块化,耦合度也越低。
如何规划微服务的技术架构体系,我们从一个微服务API的调用说起。服务端需要通过负载均衡(F5或Nginx)将请求路由到微服务网关,微服务网关(Zuul或Kong)完成反向路由、限流熔断、认证安全、日志监控等工作。微服务网关调用聚合服务,聚合服务调用基础服务,基础服务和聚合服务属于业务服务,通常说的开发人员开发微服务就是指开发这两种服务。微服务依赖一些基础服务,包括服务注册中心(Consul或Eureka)、配置中心(Consul或Spring Cloud Config)、数据库、缓存、消息队列、定时任务等。上述提到的服务最终都跑在Iaas云平台上,由运维人员统一管理和监控计算、网络、存储、安全、IDC等资源。
Java技术栈以Spring Cloud或Netflix OSS为基础,可以定制一个archetype模版作为规范,并将微服务的通用能力(客户端负载均衡、Hystrix限流熔断、监控、安全、日志、异常处理、Swagger文档、Restful)封装进jar包,以保证开发的速度和质量。
为了保证系统稳定和可靠地运行,需要在多个层面上对系统进行端到端全方位的监控。客户端使用听云或友盟等第三方服务对返回码、性能、城市、运营商、系统版本等进行统计,业务层面对注册、支付等核心指标进行监控和大屏实时展示,应用层面对延迟、QPS、响应时间、缓存命中率、慢sql等进行监控,系统层面对网络、CPU、内存、磁盘等进行监控。log日志通过ELK进行监控,metrics通过Influx DB和Grafana进行监控,Spring Boot和Consul都提供了相应的健康检查机制,网络监控使用Nagios,微服务调用达到一定规模还可以使用Zipkin或CAT等进行调用链监控,此外还要根据业务和性能需求设置相应的告警以便及时发现和解决问题。
大规模的微服务如果依赖手工处理故障和扩缩容等工作是无法想象的,因此管理规模化的微服务依赖自动化运维技术的完善,利用Jekins、Gitlab、Nexus、Docker容器(解决环境一致性和镜像部署问题)、Docker Registry容器镜像治理、Kubernetes资源调度平台等技术建立一条持续交付流水线,结合蓝绿部署、金丝雀部署等方式保证微服务快速可靠的发布。
微服务涵盖的内容实在太多无法一一细数,服务通信、安全、测试等,每个点都可以展开成文。上面可以看出微服务架构依然遵循着很多通用的设计原则,分而治之、高内聚低耦合等。落地微服务架构我们需要学会两条腿走路,组织架构转型和技术平台搭建缺一不可。
作为微服务架构师,需要做很多平衡取舍,引领技术和协调团队以达成客户需求;需要专注于大方向,有限的情况参与到具体的实现细节;需要设计合理的技术框架以满足当前需求,还要保证扩展性以应对将来的变化,逐渐演化出正确的系统。微服务架构带给我们更多的选择,但也需要我们做更多的决策。