如何基于app_id将REST请求路由至不同AWS基础设施上的同构微服务
问题描述
我们有一套基于Java的微服务部署在AWS数据湖基础设施上,负责数据的获取、修改与存储。这套数据湖包含S3、Kinesis、Athena、RDS、Airbyte连接器、Airflow等组件,设计用于存储、处理和管理以app_id标识的客户数据——每100个app_id对应一套独立的AWS基础设施(包含同款数据湖与Java微服务)。
目前我们有独立部署的客户端UI,需要根据app_id调用对应主机的微服务(例如查询app_id1-100的数据需调用host1,101-200需调用host2)。现有方案是让每个主机维护全局的主机与app_id映射关系,新增UI查询端点,UI先传入app_id获取对应主机名,再调用目标主机的API,需要两次REST调用。想寻求实现单次调用的方法。
现有方案代码实现
@Override public HostApplicationMappingsResponseDTO getHostForApplicationByIdAndName(String applicationId, String applicationName, boolean isRefreshRequired, String token, String origin) throws IOException { LOGGER.info(" Entering in getHostForApplicationByIdAndName {}", applicationId); ApplicationDTO applicationDTO = clusterCloudRepository.getHostForApplicationByIdAndName(applicationId, isRefreshRequired, token, origin); if (applicationDTO == null) { return new HostApplicationMappingsResponseDTO(new com.firm.controller.dto.Error(HttpStatus.NOT_FOUND.value(), HttpStatus.NOT_FOUND.getReasonPhrase(), "Application not found", null)); } return applicationDTO; } @Override public FirmApplicationListResponse getApplicationByHost(String token, String origin) throws IOException { LOGGER.info(" Entering in getApplicationByHost {}"); FirmApplicationListResponse response = new FirmApplicationListResponse(); List<ApplicationDTO> appList = clusterCloudRepository.getApplicationsByHost("", token, origin); if (CollectionUtils.isEmpty(appList)) { return new FirmApplicationListResponse(new com.firm.controller.dto.Error(HttpStatus.NOT_FOUND.value(), HttpStatus.NOT_FOUND.getReasonPhrase(), "Applications not found", null)); } response.setApplications(appList); return response; }
单次调用的实现方案
以下几种方案都能实现UI单次请求完成数据查询:
1. 基于AWS API Gateway做统一路由层
在UI与微服务之间部署AWS API Gateway,将其作为统一请求入口:
- 配置路由规则:把
app_id作为请求路径参数(如/api/{app_id}/stats)或查询参数,通过网关的集成请求规则或自定义Lambda函数判断app_id所属分片,直接将请求转发到对应主机的微服务端点。 - UI只需调用API Gateway的统一地址,网关自动完成路由转发,全程仅需一次请求。
- 优势:无需修改UI和微服务代码,利用AWS原生组件实现,可配合IAM权限控制、请求限流等功能。
2. UI本地维护路由映射逻辑
如果app_id的分片规则固定(比如每100个一组),可以直接在UI端实现路由判断:
- 把分片规则做成静态逻辑(如
targetHost = "host" + (Math.floor((appId - 1)/100) + 1)),或者从配置中心(如AWS Parameter Store)拉取最新的app_id-主机映射表。 - UI发起请求前直接计算或查询到目标主机,然后直接调用对应微服务的API,仅需一次请求。
- 优势:架构简单,无额外组件开销,适合规则稳定的场景;若规则变更,只需更新UI配置或静态逻辑。
3. 引入服务发现组件
使用服务发现工具(如AWS Cloud Map、Consul)管理微服务实例与app_id分片的对应关系:
- 每个微服务实例启动时,向服务发现组件注册自己负责的
app_id范围(如host1注册1-100,host2注册101-200)。 - UI通过服务发现组件的查询接口,根据
app_id获取对应的微服务实例地址,然后直接调用;或者结合客户端负载均衡器(如Spring Cloud LoadBalancer),UI调用统一服务名,负载均衡器自动根据app_id路由到对应实例。 - 优势:支持动态扩容(新增主机时自动注册分片范围),适合未来分片规则可能频繁调整的场景。
4. 让微服务节点实现请求转发
如果不想引入额外组件,可以让每个微服务节点维护全局的app_id-主机映射表:
- UI随机调用任意一个微服务节点的API,该节点先判断当前
app_id是否属于自己负责的分片:- 如果是,直接处理请求并返回结果;
- 如果不是,将请求转发到对应主机的微服务,拿到结果后再返回给UI。
- 全程UI仅需一次请求,转发逻辑对UI透明。
- 注意:需要处理转发过程中的超时、错误重试等问题,避免成为性能瓶颈。
内容的提问来源于stack exchange,提问作者azaveri7
相关产品推荐
相关产品推荐

