超越点对点连接对于比较简单的应用程序,为依存项的地址使用外部配置就已足够。然而对于任何规模的应用程序,我们需要的可能不仅仅是简单的点对点连接,可能还希望实现某种形式的负载平衡。
如果每个服务都直接依赖某一下游服务实例,下游出现的任何故障都可能造成最终用户遇到严重问题。同理,如果下游服务超载,用户将会面临响应时间延长的问题。此时我们需要的是负载平衡。
与其直接依赖一个下游实例,我们更希望通过一组下游服务实例分摊负载。如果这些实例中有一个故障或超载,其他实例可以接手处理任务。为这种体系结构实现负载平衡的最简单方法是使用负载平衡代理。下图展示了在Amazon Web Services部署中使用Elastic Load Balancing实现这种方式的具体做法:
为排行榜应用ELB
这种情况下无需让logbook服务直接与leaderboard服务通信,而是可以使用ELB对每个请求进行路由。ELB会将每个请求路由至某一后端leaderboard服务。通过让ELB充当中介,可将负载分摊到多个leaderboard实例,这有助于减少每个实例的负担。
ELB的负载平衡是动态的,运行过程中可以给后端添加新的实例,因此如果传入流量激增,即可启动更多leaderboard实例加以应对。
Spring Boot应用程序可使用 暴露供ELB定期监控的/health端点。能够响应此类运行状况检查操作的实例会保留在ELB的活跃集(Active set)中,如果多次检查均未响应,相应的实例会从服务中移除。
在我们的系统中,leaderboard服务不是唯一能通过负载平衡获益的服务。logbook服务以及前端UI均能借助负载平衡机制实现更好的可扩展性和弹性。
动态重配置无论使用AWS ELB、 ,或者使用HAProxy或NGINX自行搭建负载平衡代理,都需要将服务与负载平衡器相互连接。
此时一种方法是为每个负载平衡器提供一个「众所周知」的DNS名称,例如leaderboard.repmax.local,并使用上文提到的静态连接方式将其硬编码至应用程序中。由于DNS系统本身的灵活性,这种方法已经可以做到相当灵活。然而使用硬编码的名称意味着要在运行服务的每个环境中配置一台DNS服务器。在开发过程中,由于需要为多种多样的操作系统提供支持,提供定制化DNS的操作就显得尤为麻烦。此时更好的做法是使用类似上文leaderboard.url的例子那样,将负载平衡器的地址自然地注入服务。
在AWS和GCP等云环境中,负载平衡器(及其地址)会频繁变动。当负载平衡器被删除并重建后,通常会使用一个新的地址。如果将负载平衡器的地址硬编码到程序中,为了应对地址的变化,必须在每次改变后重新编译代码。但通过使用外化的配置,只需更改配置文件并重启动服务即可。
为了应对负载平衡器地址不断变化这一本质,DNS是一种很方便的做法。每个负载平衡器都可分配一个固定的DNS名称,并将这个名称注入所调用的服务。在重建负载平衡器时,其DNS名称可重映射至负载平衡器的新地址。如果准备在环境中运行DNS服务器,就很适合使用这种基于DNS的方法。如果不想运行DNS,但依然希望对负载平衡器进行动态重配置,此时可以考虑使用Spring Cloud Config。
Spring Cloud Config会运行一个名为Config Server的小巧服务,并通过REST API提供可集中访问的配置数据。默认情况下配置数据存储在一个Git仓库中,并可通过标准的PropertySource抽象暴露给Spring Boot服务。使用PropertySource可将本地属性文件中包含的配置与Config Server中存储的配置无缝结合在一起。对于本地开发,可以使用来自本地属性文件的配置,并只在将应用程序部署在现实环境时才覆盖这些配置信息。
为使用Spring Cloud Config取代ConfigurableLeaderBoardApi,首先可以用所需配置初始化一个Git代码库:
[url=][/url]
mkdir -p ~/dev/repmax-config-repocd ~/dev/repmax-config-repogit initecho 'leaderboard.lb.url=http://some.lb.address' >> repmax.propertiesgit add repmax.propertiesgit commit -m 'LB config for the leaderboard service'[url=][/url]
repmax.properties文件中包含repmax应用程序default配置文件的设置。如果希望将配置加入其他配置文件,例如加入development,此时只需要提交另一个名为repmax-development.properties的文件即可。
若要运行Config Server,可以运行spring-cloud-config-server项目提供的默认Config Server,或自行创建一个简单的Spring Boot项目并承载下列Config Server:
[url=][/url]
@SpringBootApplication@EnableConfigServerpublic class RepmaxConfigServerApplication { public static void main(String[] args) { SpringApplication.run(RepmaxConfigServerApplication.class, args); }}[url=][/url]
其中@EnableConfigServer标注可用于通过小巧的Spring Boot应用程序启动Config Server。随后可以用spring.cloud.config.server.git.uri属性将Config Server指向Git代码库。对于本地测试工作,可将其加入Config Server应用程序的application.properties文件:
spring.cloud.config.server.git.uri=file://${user.home}/dev/repmax-config-repo
通过这种方式,团队中的每位开发者都可以在自己的计算机上启动Config Server,并通过本地Git代码库进行测试。若要验证repmax应用程序的属性是否已通过Config Server暴露,可在Config Server运行后使用浏览器访问http://localhost:8888/repmax/default:
在Config Server中浏览配置信息
从图中可以看到,leaderboard.lb.url属性已通过repmax.properties文件暴露,其值为http://localhost:8083。JSONT载荷的version属性显示了加载配置时所用的Git版本。
在生产环境中,可以充分借助PropertySource抽象将Git代码库的名称以环境变量的方式提供:
SPRING_CLOUD_CONFIG_SERVER_GIT_URI=https://gitlab.com/rdh/repmax-config-repo java -jar repmax-config-server-1.0.0-RELEASE.jar |