前言
Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
作为一个后台开发,nacos是我经常用到的一款集注册中心、配置中心于一身的平台,简单的配置启动,然后应用注册即可使用,还有简洁明了使用的UI页面,点个赞先!
贴上官网地址:
https://nacos.io/
问题及处理
问题
在使用nacos页面更改配置并发布的时候发现一个问题:
当两个人A和B都打开了某个配置的编辑页面,都进行了修改,然后点了发布,则会出现后点发布的B提交的配置生效,因为会覆盖前者A发布的版本,而此时如果没做比对或确认的话A就会没有察觉,从而导致可能的一些问题…
复现
该问题也很好复现,两个人直接按照步骤操作即可,一个人的话通过两个浏览器来模拟:
1、通过浏览器A打开nacos UI页面,找到一个配置文件,点击编辑,打开编辑页面;
2、通过浏览器B打开nacos UI页面,也找到刚刚打开的那个配置文件,点击编辑,打开编辑页面;
3、在浏览器A打开的nacos配置编辑页面对配置进行变更修改,然后点击发布;
4、在浏览器B打开的nacos配置编辑页面也对配置进行变更修改,然后点击发布;
5、再次查看nacos上这个配置文件的配置信息,会发现呈现的是浏览器B编辑发布后的结果;
处理
思路:在发布之前进行MD5比对!拿到源码,本地对逻辑进行变更,然后编译打包使用…
代码修改处如下:
1、com.alibaba.nacos.config.server.model.form.ConfigForm
增加md5参数字段1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110package com.alibaba.nacos.config.server.model.form;
import com.alibaba.nacos.api.exception.api.NacosApiException;
import com.alibaba.nacos.api.model.v2.ErrorCode;
import com.alibaba.nacos.common.utils.StringUtils;
import org.springframework.http.HttpStatus;
import java.io.Serializable;
import java.util.Objects;
public class ConfigForm implements Serializable {
// ... 代码省略
private String md5;
public ConfigForm() {
}
public ConfigForm(String dataId, String group, String namespaceId, String content, String tag, String appName,
String srcUser, String configTags, String desc, String use, String effect, String type, String schema,
String md5) {
this.dataId = dataId;
this.group = group;
this.namespaceId = namespaceId;
this.content = content;
this.tag = tag;
this.appName = appName;
this.srcUser = srcUser;
this.configTags = configTags;
this.desc = desc;
this.use = use;
this.effect = effect;
this.type = type;
this.schema = schema;
this.md5 = md5;
}
// ... 代码省略
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ConfigForm configForm = (ConfigForm) o;
return dataId.equals(configForm.dataId) && group.equals(configForm.group) && Objects.equals(namespaceId, configForm.namespaceId)
&& content.equals(configForm.content) && Objects.equals(tag, configForm.tag) && Objects
.equals(appName, configForm.appName) && Objects.equals(srcUser, configForm.srcUser) && Objects
.equals(configTags, configForm.configTags) && Objects.equals(desc, configForm.desc) && Objects
.equals(use, configForm.use) && Objects.equals(effect, configForm.effect) && Objects
.equals(type, configForm.type) && Objects.equals(schema, configForm.schema)
&& Objects.equals(md5, configForm.md5);
}
public int hashCode() {
return Objects.hash(dataId, group, namespaceId, content, tag, appName, srcUser, configTags, desc, use, effect, type,
schema, md5);
}
public String toString() {
return "ConfigVo{" +
"dataId='" + dataId + '\'' +
", group='" + group + '\'' +
", namespaceId='" + namespaceId + '\'' +
", content='" + content + '\'' +
", tag='" + tag + '\'' +
", appName='" + appName + '\'' +
", srcUser='" + srcUser + '\'' +
", configTags='" + configTags + '\'' +
", desc='" + desc + '\'' +
", use='" + use + '\'' +
", effect='" + effect + '\'' +
", type='" + type + '\'' +
", schema='" + schema + '\'' +
", md5='" + md5 + '\'' +
'}';
}
/**
* Validate.
*
* @throws NacosApiException NacosApiException.
*/
public void validate() throws NacosApiException {
if (StringUtils.isBlank(dataId)) {
throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING,
"Required parameter 'dataId' type String is not present");
} else if (StringUtils.isBlank(group)) {
throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING,
"Required parameter 'group' type String is not present");
} else if (StringUtils.isBlank(content)) {
throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING,
"Required parameter 'content' type String is not present");
}
}
}
2、com.alibaba.nacos.config.server.controller.ConfigController#publishConfig
添加md5入参,前端有传,直接接收
1 |
|
3、com.alibaba.nacos.config.server.service.ConfigOperationService#publishConfig
添加校验逻辑
1 | public Boolean publishConfig(ConfigForm configForm, ConfigRequestInfo configRequestInfo, String encryptedDataKey) |
4、编译打包
1 | mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U |
5、拿到打包后的新包使用即可
新包路径:项目代码路径/distribution/target
复测
再次测试结果符合预期!
结语
到此这个问题就可以如愿解决了,欢迎留言交流!