点击上方“芋道源码”,选择“设为星标”
管她前浪,还是后浪?
能浪的浪,才是好浪!
每天 8:55 更新文章,每天掉亿点点头发...
源码精品专栏
摘要: 原创出处 http://www.iocoder.cn/Apollo/config-service-config-query-api/ 「芋道源码」欢迎转载,保留摘要,谢谢!
1. 概述
2. ConfigController
-
2.1 构造方法
2.2 queryConfig
2.3 tryToGetClientIp
2.4 mergeReleaseConfigurations
3. ConfigService
-
3.1 AbstractConfigService
3.3 DefaultConfigService
3.4 ConfigServiceWithCache
4. ApolloConfig
666. 彩蛋
1. 概述
老艿艿:本系列假定胖友已经阅读过 《Apollo 官方 wiki 文档》 。
本文接 《Apollo 源码解析 —— Config Service 通知配置变化》 一文,分享 Config Service 配置读取的接口的实现。在上文,我们看到通知变化接口,仅返回通知相关的信息,而不包括配置相关的信息。所以 Config Service 需要提供配置读取的接口。
???? 为什么不在通知变化的同时,返回最新的配置信息呢?老艿艿请教了作者,下一篇文章进行分享。
OK,让我们开始看看具体的代码实现。
2. ConfigController
com.ctrip.framework.apollo.configservice.controller.ConfigController
,配置 Controller ,仅提供 configs/{appId}/{clusterName}/{namespace:.+}
接口,提供配置读取的功能。
2.1 构造方法
private static final Splitter X_FORWARDED_FOR_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults();
private static final Type configurationTypeReference = new TypeToken<Map<String, String>>() {}.getType();
@Autowired
private ConfigService configService;
@Autowired
private AppNamespaceServiceWithCache appNamespaceService;
@Autowired
private NamespaceUtil namespaceUtil;
@Autowired
private InstanceConfigAuditUtil instanceConfigAuditUtil;
@Autowired
private Gson gson
2.2 queryConfig
1: @RequestMapping(value = "/{appId}/{clusterName}/{namespace:.+}", method = RequestMethod.GET)
2: public ApolloConfig queryConfig(@PathVariable String appId, @PathVariable String clusterName,
3: @PathVariable String namespace,
4: @RequestParam(value = "dataCenter", required = false) String dataCenter,
5: @RequestParam(value = "releaseKey", defaultValue = "-1") String clientSideReleaseKey,
6: @RequestParam(value = "ip", required = false) String clientIp,
7: @RequestParam(value = "messages", required = false) String messagesAsString,
8: HttpServletRequest request, HttpServletResponse response) throws IOException {
9: String originalNamespace = namespace;
10: // 若 Namespace 名以 .properties 结尾,移除该结尾,并设置到 ApolloConfigNotification 中。例如 application.properties => application 。
11: // strip out .properties suffix
12: namespace = namespaceUtil.filterNamespaceName(namespace);
13: // 获得归一化的 Namespace 名字。因为,客户端 Namespace 会填写错大小写。
14: //fix the character case issue, such as FX.apollo <-> fx.apollo
15: namespace = namespaceUtil.normalizeNamespace(appId, namespace);
16:
17: // 若 clientIp 未提交,从 Request 中获取。
18: if (Strings.isNullOrEmpty(clientIp)) {
19: clientIp = tryToGetClientIp(request);
20: }
21:
22: // 解析 messagesAsString 参数,创建 ApolloNotificationMessages 对象。
23: ApolloNotificationMessages clientMessages = transformMessages(messagesAsString);
24:
25: // 创建 Release 数组
26: List<Release> releases = Lists.newLinkedList();
27: // 获得 Namespace 对应的 Release 对象
28: String appClusterNameLoaded = clusterName;
29: if (!ConfigConsts.NO_APPID_PLACEHOLDER.equalsIgnoreCase(appId)) {
30: // 获得 Release 对象
31: Release currentAppRelease = configService.loadConfig(appId, clientIp, appId, clusterName, namespace, dataCenter, clientMessages);
32: if (currentAppRelease != null) {
33: // 添加到 Release 数组中。
34: releases.add(currentAppRelease);
35: // 获得 Release 对应的 Cluster 名字
36: // we have cluster search process, so the cluster name might be overridden
37: appClusterNameLoaded = currentAppRelease.getClusterName();
38: }
39: }
40: // 若 Namespace 为关联类型,则获取关联的 Namespace 的 Release 对象
41: // if namespace does not belong to this appId, should check if there is a public configuration
42: if (!namespaceBelongsToAppId(appId, namespace)) {
43: // 获得 Release 对象
44: Release publicRelease = this.findPublicConfig(appId, clientIp, clusterName, namespace, dataCenter, clientMessages);
45: // 添加到 Release 数组中
46: if (!Objects.isNull(publicRelease)) {
47: releases.add(publicRelease);
48: }
49: }
50: // 若获得不到 Release ,返回状态码为 404 的响应
51: if (releases.isEmpty()) {
52: response.sendError(HttpServletResponse.SC_NOT_FOUND, String.format("Could not load configurations with appId: %s, clusterName: %s, namespace: %s",
53: app