1。领域驱动设计微服务开发的主要挑战:将大型、复杂的应用程序拆分为小型、自治且可独立部署的模块。如果没有正确的拆分,那么结果就是一堆糊,既有单体结构的缺点,又有微服务结构的复杂性,可以称之为分布式单体。幸运的是,EricEvans提出了很多领域驱动设计的最佳实践和经验技巧。有3个核心思想:开发团队要与业务部门和业务领域专家紧密合作。架构师、开发人员和领域专家首先应该进行战略设计:找出边界上下文、核心域、子域和上下文映射关系。架构师和开发人员根据战略设计梳理出一组核心构建块:实体、值对象、聚合等。将一个大系统划分为核心域和子域,然后将核心域和子域映射为微服务,这样我们就可以得到一个理想的松耦合微服务系统。2.每个微服务一个数据库。设计了微服务模块结构。下一个重要的问题是如何与数据库打交道。微服务是否共享数据库?如果共享,会导致微服务之间紧耦合,违背了微服务松耦合的原则。数据库中的一个小改动需要所有团队同时修改。如果每个微服务都有自己的数据库,微服务之间的数据交互会很麻烦,就像打开了潘多拉魔盒,跑出来一堆问题,比如在多个服务中管理事务。因此,很多人提倡共享数据库。但是,微服务是持续的、长期的软件开发,每个微服务都应该有自己的数据库。3、微前端很多后端开发人员看不起前端,认为它太简单了。大部分架构师也是后端出身,在架构设计上对前端的重视不够。结果现在的情况是,后端的模块化做得很好,前端还是一堆。前端单体结构与后端单体存在同样的问题,因此前端也需要现代化。现在的网络技术简单而强大,比如网络组件、Angular/React。4、持续交付每个微服务都可以独立部署,这是微服务架构的核心优势之一。比如你的系统有100个微服务,现在需要更新一个,那么你只需要发布这个,其他99个不用动。这需要CI/CD和DevOps,没有这个自动化过程,就像拉着手刹开法拉利一样。5.可观测微服务架构简化了开发,却复杂了运维。单体架构非常容易监控,但是在微服务架构中,服务很多,而且通常运行在容器中,所以整个系统的监控变得非常复杂。需要聚合所有容器和机器中的日志。好在已经有成熟的解决方案,比如用ELK/Splunk来处理日志,用Prometheus/AppDynamics来处理监控。还有另一个更重要的方面:呼叫跟踪。微服务之间会有级联调用。为了分析系统延迟,有必要测量每个服务的延迟。Zipkin/Jaeger提供了这种能力。6、在统一的技术栈微服务体系中,不同的服务有不同的特点。比如有些服务是CPU密集型操作,用C++/Rust比较合适;有些服务是做机器学习的,用Python比较合适。因此,可以使用不同的技术来处理相应的需求,但一定要注意合理性,不要无缘无故地混合使用不同的技术。想象一下,在一个系统中,有的微服务使用SpringBoot+Kotlin+React+MySQL,有的使用JakartaEE+Java+Angular+PostgreSQL,有的使用Scala+PlayFramework+VueJS+Oracle。这样会不会让人很崩溃,维护起来太难了。7、异步通信服务之间的通信问题是微服务架构的一个重要挑战,比是否共享数据库的问题更麻烦。为了实现业务需求,需要多个微服务协同工作,服务之间需要进行数据交换,需要一个服务触发其他服务。最简单的方式就是直接通过REST接口调用,但是这种同步调用的方式问题比较大。比如A->B->C->D,这种多级调用主要存在三个问题:系统延迟增加。每个服务都可能失败,从而产生级联错误。服务紧密耦合。最好使用异步通信方式,比如通过消息队列(如kafka)、异步REST(ATOM)、CQRS。8、微服务优先。很多人认为新项目应该使用单体结构,比微服务启动更快,也更简单。等开发长大了,再转成微服务。然而,这种转变非常困难,因为单体中模块的耦合度太高。而且,产品成熟后,对在线可用性的要求非常高。如果到时候重建,产品的运行肯定会中断。9.基础设施优于类库。早期Netflix开发微服务时,主要使用java开发。Netflix开发了很多优秀的库,比如Hystrix和Zuul,很多公司都在使用它们。后来包括Netflix在内的很多公司都发现java其实不擅长微服务开发,比如java太大了。Netflix转向Polyglot并停止维护这些库,这让许多公司处于被动状态。因此,与其过度依赖特定语言的类库,不如使用更底层的基础架构框架,例如ServiceMeshes。10.组织方面的考虑五十年前,MelvinConway发现一家公司的软件架构受其组织结构的限制。事实上,这种观点在今天仍然是正确的。如果一个组织想要使用微服务架构,那么团队规模应该进行调整。两个披萨规则:如果两个披萨不足以养活一个项目团队,那么这个团队可能太大了。而且团队成员要多元化,包括前端、后端、测试、运维。微服务架构只有在高级领导者的思维方式发生转变时才有可能发挥作用。
