1. 概述
- 客户端会发起一个Http 请求到 Config Service 的
notifications/v
2 接口,也就是NotificationControllerV2 。 - NotificationControllerV2 不会立即返回结果,而是通过 Spring DeferredResult 把请求挂起。
- 如果在 60 秒内没有该客户端关心的配置发布,那么会返回 Http 状态码 304 给客户端。
- 如果有该客户端关心的配置发布,NotificationControllerV2 会调用 DeferredResult 的 setResult 方法,传入有配置变化的 namespace 信息,同时该请求会立即返回。客户端从返回的结果中获取到配置变化的 namespace 后,会立即请求 Config Service 获取该 namespace 的最新配置。
2. NotificationControllerV2
1.实现 ReleaseMessageListener 接口,通知 Controller ,仅提供 notifications/v2
接口。
2.1 类的继承结构
2.2 客户端请求流程
2.3 pollNotification方法
1.客户端请求配置变化入口
@RequestMapping(method = RequestMethod.GET) public DeferredResult<ResponseEntity<List<ApolloConfigNotification>>> pollNotification( @RequestParam(value = "appId") String appId, @RequestParam(value = "cluster") String cluster, @RequestParam(value = "notifications") String notificationsAsString, @RequestParam(value = "dataCenter", required = false) String dataCenter, @RequestParam(value = "ip", required = false) String clientIp) { // 解析 notificationsAsString 参数,创建 ApolloConfigNotification 数组。 List<ApolloConfigNotification> notifications = null; try { notifications = gson.fromJson(notificationsAsString, notificationsTypeReference); } catch (Throwable ex) { Tracer.logError(ex); } if (CollectionUtils.isEmpty(notifications)) { throw new BadRequestException("Invalid format of notifications: " + notificationsAsString); } // 创建 DeferredResultWrapper 对象 DeferredResultWrapper deferredResultWrapper = new DeferredResultWrapper(); // Namespace 集合 Set<String> namespaces = Sets.newHashSet(); // 客户端的通知 Map 。key 为 Namespace 名,value 为通知编号。 Map<String, Long> clientSideNotifications = Maps.newHashMap(); // 过滤并创建 ApolloConfigNotification Map Map<String, ApolloConfigNotification> filteredNotifications = filterNotifications(appId, notifications); // 循环 ApolloConfigNotification Map ,初始化上述变量。 for (Map.Entry<String, ApolloConfigNotification> notificationEntry : filteredNotifications.entrySet()) { String normalizedNamespace = notificationEntry.getKey(); ApolloConfigNotification notification = notificationEntry.getValue(); // 添加到 `namespaces` 中。 namespaces.add(normalizedNamespace); // 添加到 `clientSideNotifications` 中。 clientSideNotifications.put(normalizedNamespace, notification.getNotificationId()); // 记录名字被归一化的 Namespace 。因为,最终返回给客户端,使用原始的 Namespace 名字,否则客户端无法识别。 if (!Objects.equals(notification.getNamespaceName(), normal |