原文:https://aws.amazon.com/cn/blogs/china/spring-clouds-cloud-native-migration-hybrid-deployment-architecture-on-aws-part-1/?nc1=b_rp

简介

微服务是一种软件开发的组织和架构方法,它可以加快软件交付周期、增强创新和自主性,提高软件的可维护性和可伸缩、可扩展性,同时也提高了企业开发和发布软件服务的能力。使用微服务架构,软件产品将由多个独立的、可通过API进行交互的服务组成。这些服务将由各个小团队独自负责。

Spring Cloud是一个基于Spring Boot实现的微服务架构开发工具。它为微服务架构中涉及的配置管理、服务治理、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等操作提供了一种简单的开发方式。
由于Spring生态在Java开发者中具有广泛的影响力,Spring Cloud基于Spring Boot对大型项目开发难度的简化,对开发微服务所需的组件进行了简单高效的封装,Spring Cloud已成为Java领域开发微服务的实际标准。由于Spring Cloud技术已有较长的应用时间,用户把原有的虚拟机部署应用往更云原生的技术(如:容器)迁移可能会遇到各种问题,本系列将使用AWS EC2及EKS服务作为混合架构的样例基础设施(即虚拟机与容器混合),在AWS上部署Spring Cloud应用,以给在AWS上部署及迁移Spring Cloud应用遇到难题的开发者提供参考。

架构设计

Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图1

  • 注册发现中心Eureka的高可用为软件实现,需要在配置文件里配置所有Eureka server信息,Eureka server间进行信息同步。因此,架构方案选择在每个可用区创建独立的EC2部署Eureka server,同时使用独立的ELB以固定每个Eureka server的DNS,及独立的Auto scaling group以保证每个可用区内Eureka server的正常工作。
  • API gateway是微服务架构中另一个重要设施。API gateway本身为无状态服务,有了Eureka注册发现中心的保障,每个API gateway server都可以自动发现需要调用的服务。在架构方案中,使用一个统一的ELB,以暴露对外服务的URL;同时使用一个Auto scaling group保证API gateway的高可用及可扩展性。示例架构中,使用Spring Cloud 中的Zuul作为示例API gateway组件。
  • 使用AWS托管的Kubernetes服务EKS部署实际业务的工作负载,可实现业务负载的快速扩展、灵活调度,同时降低Kubernetes群集的运维难度。
  • S3和ECR作为应用部署包以及Docker镜像的仓库,可方便地对接微服务架构中CI/CD各种不同方案。
  • 对于系统中各种公共变量,使用System Manager中的Parameter Store进行存储。可实现公共变量的动态调整,和应用部署时进行动态注入。

    为什么使用混合架构进行部署

    虚拟化技术特点考量

    随着虚拟化技术的演进,计算服务经历了从物理服务器,到虚拟机、容器化,最后到无服务器服务的过程。随着抽象级别的提高,除了用户可以更专注于业务逻辑以外;不同级别的虚拟化技术带来的,是应用启动及期望持续运行时间量级的不同;用户可以根据具体应用的特征,选择合适的虚拟化技术层级。通常,虚拟机(如:EC2)的启动时间为分钟级,期望持续运行时间为数周至数月;容器化(如:Docker)的启动时间为秒级,期望持续运行时间为数十分钟至数周;无服务器服务(如:Lambda)的启动时间为毫秒级,期望持续运行时间为数秒至最多15分钟。

在Spring Cloud的使用场景中,Eureka、API gateway等微服务基础设施需要长久不间断地运行,通常还希望能独占计算资源,以保障其高可靠性。虚拟机技术满足以上要求,同时为保障技术前后兼容性,示例架构中仍使用EC2部署相关工作负载。而具体业务功能模块,通常需要更灵活的调度,以及更快的启动速度以应对突发流量。因此,选择容器化技术率先对相关工作负载进行迁移。Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图2

系统技术兼容性考量

由于Spring Cloud已经流行多年,在实际项目中,会有更多兼容性的考虑。如:已有的项目都是使用EC2进行应用部署,由于容器技术带来的好处,新的业务模块使用容器化部署,或旧的模块需要进行容器化改造,甚至在一个微服务系统中,存在多个群集,多种容器管理平台。这些情况下,把微服务的基础设施进行独立部署,不依赖于特定的容器管理平台,将使新旧项目的衔接更平滑,带来更好的向前兼容和向后扩展性。

部署Spring Cloud的基础服务模块

前置条件

eureka.instance.hostname=${eureka_server_1} eureka.client.service-url.defaultZone=http://${eureka_server_2}:${eureka_server_port}/eureka,http://${eureka_server_3}:${eureka_server_port}/eureka

  1. **4.应用Jar包的存放**<br />创建S3桶作为应用Jar包的存放地,并上传应用Jar包。![](https://cdn.nlark.com/yuque/0/2021/png/1471554/1620962612495-43d6c987-67d1-473a-8f36-e860954eb327.png#clientId=u0ab939ef-8d50-4&from=paste&height=440&id=u479ec572&margin=%5Bobject%20Object%5D&originHeight=880&originWidth=2626&originalType=url&status=done&style=shadow&taskId=u2a9100bf-9fc2-4689-a0b8-7ed099d1411&width=1313)<br />**5.创建IAM角色**<br />创建IAM角色,附加托管策略AmazonS3ReadOnlyAccess及AmazonSSMReadOnlyAccess,使附加该角色的server可以访问S3及Parameter Store中的资源。![](https://cdn.nlark.com/yuque/0/2021/png/1471554/1620962612535-12874619-762d-4655-8793-06d426af04d3.png#clientId=u0ab939ef-8d50-4&from=paste&height=603&id=u34b6a893&margin=%5Bobject%20Object%5D&originHeight=1206&originWidth=2270&originalType=url&status=done&style=shadow&taskId=u6b00528c-b3fe-4f7d-86e1-2fd0a255c59&width=1135)<br />**6.创建启动模板**<br />选择所需的AMI及实例类型![](https://cdn.nlark.com/yuque/0/2021/png/1471554/1620962612636-dbb07828-650b-4c36-84d6-839e52ff717e.png#clientId=u0ab939ef-8d50-4&from=paste&height=454&id=u3a9f7a98&margin=%5Bobject%20Object%5D&originHeight=908&originWidth=1634&originalType=url&status=done&style=shadow&taskId=u925d290d-7673-40ec-abdd-51174b4fc4c&width=817)配置网络及安全组![](https://cdn.nlark.com/yuque/0/2021/png/1471554/1620962612613-f68156d6-1424-4a50-bbe3-0e4dfffac834.png#clientId=u0ab939ef-8d50-4&from=paste&height=351&id=uf668a1fc&margin=%5Bobject%20Object%5D&originHeight=702&originWidth=1630&originalType=url&status=done&style=shadow&taskId=ufa60fe6a-b4c4-452f-9a66-9c9d093d3ac&width=815)配置IAM实例配置文件**_(重要)_**,选择步骤5中创建的AMI角色配置文件。![](https://cdn.nlark.com/yuque/0/2021/png/1471554/1620962613256-2ce294fd-d897-467e-b630-ddcdffc8bbf9.png#clientId=u0ab939ef-8d50-4&from=paste&height=253&id=u3e6e8324&margin=%5Bobject%20Object%5D&originHeight=506&originWidth=1638&originalType=url&status=done&style=shadow&taskId=udb9d9987-be05-4f5f-8a7e-937b054ff20&width=819)配置用户数据**_(重要)_**,以在EC2实例启动时配置所需的环境变量及启动Java应用。如下为配置示例:
  2. ```shell
  3. #!/bin/bash
  4. yum update -y
  5. yum install -y java-1.8.0-openjdk.x86_64 jq.x86_64
  6. mkdir /opt/spring_cloud
  7. mkdir /var/log/spring_cloud
  8. aws configure set region us-east-2
  9. # Download Java package from S3
  10. aws s3 cp s3://spring-cloud-test/test-eureka-server-0.0.1-SNAPSHOT.jar /opt/spring_cloud/
  11. # Set env variable
  12. export eureka_server_port=$(aws ssm get-parameter --name='/Spring/Eureka/Server/port' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  13. export eureka_server_1=$(aws ssm get-parameter --name='/Spring/Eureka/Server/URL_1' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  14. export eureka_server_2=$(aws ssm get-parameter --name='/Spring/Eureka/Server/URL_2' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  15. export eureka_server_3=$(aws ssm get-parameter --name='/Spring/Eureka/Server/URL_3' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  16. # Start Eureka server
  17. java -jar /opt/spring_cloud/test-eureka-server-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1 &

7.创建Auto Scaling Group
选择步骤6中创建的启动模板Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图7网络配置。选择只在单一可用区启动。Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图8启用负载均衡器及目标组Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图9配置组大小和扩展策略。3个Eureka server的Auto scaling group作用为保持每一个可用区中都只有一个Eureka server,无需扩展。配置如下。Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图10
8.确认Eureka server配置及工作正常
在Auto Scaling Group正确设置后,位于三个不同可用区的EC2实例将被自动创建。Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图11访问Eureka Serve的ELB DNS,显示三个Eureka Serve已经相互注册则表示功能运行正常。Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图12

部署API Gateway (Zuul)

1.创建NLB for API Gateway
为API Gateway创建一个跨3可用区的ELB,作为对外服务的唯一入口。示例中,使用Network Load Balancer作为组件。分布于3个可用区的无状态API Gateway server将均匀接受访问流量。Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图13
2.API Gateway应用中的配置
如下为API Gateway的Spring Cloud项目application.properties文件的配置示例。

  1. spring.application.name=api-gateway
  2. server.port=8081
  3. eureka.client.service-url.defaultZone=http://${eureka_server_1}:${eureka_server_port}/eureka,http://${eureka_server_2}:${eureka_server_port}/eureka,http://${eureka_server_3}:${eureka_server_port}/eureka
  4. zuul.routes.api-hello-service.path=/api-hello-service/**
  5. zuul.routes.api-hello-service.service-id=hello-service

3.应用Jar包上传至S3桶Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图14
4.创建启动模板
选择所需的AMI及实例类型Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图15
配置网络及安全组Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图16
配置IAM实例配置文件(重要),选择Eureka部署中创建的公用AMI角色配置文件。Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图17
配置用户数据(重要),以在EC2实例启动时配置所需的环境变量及启动Java应用。如下为配置示例:

  1. #!/bin/bash
  2. yum update -y
  3. yum install -y java-1.8.0-openjdk.x86_64 jq.x86_64
  4. mkdir /opt/spring_cloud
  5. mkdir /var/log/spring_cloud
  6. aws configure set region us-east-2
  7. aws s3 cp s3://spring-cloud-test/api-gateway-0.0.1-SNAPSHOT.jar /opt/spring_cloud/
  8. export eureka_server_port=$(aws ssm get-parameter --name='/Spring/Eureka/Server/port' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  9. export eureka_server_1=$(aws ssm get-parameter --name='/Spring/Eureka/Server/URL_1' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  10. export eureka_server_2=$(aws ssm get-parameter --name='/Spring/Eureka/Server/URL_2' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  11. export eureka_server_3=$(aws ssm get-parameter --name='/Spring/Eureka/Server/URL_3' --region us-east-2 | jq '.Parameter | .Value ' | sed 's/\"//g' )
  12. java -jar /opt/spring_cloud/api-gateway-0.0.1-SNAPSHOT.jar &

5.创建Auto Scaling Group
选择步骤4中创建的启动模板Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图18
网络配置。选择在三个可用区启动。Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图19
启用负载均衡器及目标组Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图20按需配置组大小。不添加扩展策略,待Auto Scaling Group创建完成后添加。配置如下。Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图21
添加扩展策略Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图22
Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图23
6.确认API Gateway配置及工作正常
在Auto Scaling Group正确设置后,位于三个不同可用区的EC2实例将被自动创建。Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图24访问Eureka Serve的ELB DNS,显示三个API Gateway已经注册则表示功能运行正常。Spring Cloud 的云原生迁移 – AWS 上的混合部署架构(上篇) - 图25

总结

微服务架构是现代大型系统设计开发中最流行的模式,Spring Cloud则是Java生态中微服务开发的实际标准。本文探讨了在AWS上如何规划Spring Cloud的部署,提出了架构的整体思路,最后提供了在EC2上部署Spring Cloud基础服务的具体实践。通过本文的介绍,希望能给Spring Cloud的使用者带来一点在AWS上进行部署的思路,从而更快更好地利用AWS提供的基础设施,快速实现业务价值。

参考资料

[1]https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html
[2]https://docs.aws.amazon.com/AmazonS3/latest/dev/Welcome.html
[3]https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html
[4]https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html
[5]翟永超.Spring Cloud 微服务实战[M].电子工业出版社:北京,2017:1.