diff --git a/common/src/main/java/com/alibaba/nacos/common/utils/Md5Utils.java b/common/src/main/java/com/alibaba/nacos/common/utils/Md5Utils.java index df2db20d5db..1867561a6c8 100644 --- a/common/src/main/java/com/alibaba/nacos/common/utils/Md5Utils.java +++ b/common/src/main/java/com/alibaba/nacos/common/utils/Md5Utils.java @@ -15,7 +15,9 @@ */ package com.alibaba.nacos.common.utils; -import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; /** * MD5 generator @@ -24,35 +26,34 @@ */ public class Md5Utils { + private static ThreadLocal MESSAGE_DIGEST_LOCAL = new ThreadLocal() { + @Override + protected MessageDigest initialValue() { + try { + return MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + return null; + } + } + }; + private static final int HEX_VALUE_COUNT = 16; - public static String getMD5(byte[] bytes) { - char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - char[] str = new char[16 * 2]; - try { - java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); - md.update(bytes); - byte[] tmp = md.digest(); - int k = 0; - for (int i = 0; i < HEX_VALUE_COUNT; i++) { - byte byte0 = tmp[i]; - str[k++] = hexDigits[byte0 >>> 4 & 0xf]; - str[k++] = hexDigits[byte0 & 0xf]; - } - } catch (Exception e) { - e.printStackTrace(); + public static String getMD5(byte[] bytes) throws NoSuchAlgorithmException { + + MessageDigest messageDigest = MESSAGE_DIGEST_LOCAL.get(); + if (messageDigest != null) { + return new BigInteger(1, messageDigest.digest(bytes)).toString(HEX_VALUE_COUNT); } - return new String(str); + + throw new NoSuchAlgorithmException("MessageDigest get MD5 instance error"); } public static String getMD5(String value, String encode) { - String result = ""; try { - result = getMD5(value.getBytes(encode)); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); + return getMD5(value.getBytes(encode)); + } catch (Exception e) { + throw new RuntimeException(e); } - - return result; } } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/aspect/RequestLogAspect.java b/config/src/main/java/com/alibaba/nacos/config/server/aspect/RequestLogAspect.java index d45eb42faaf..ee6092c61f2 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/aspect/RequestLogAspect.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/aspect/RequestLogAspect.java @@ -15,11 +15,12 @@ */ package com.alibaba.nacos.config.server.aspect; +import com.alibaba.nacos.common.utils.Md5Utils; +import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.monitor.MetricsMonitor; import com.alibaba.nacos.config.server.service.ConfigService; import com.alibaba.nacos.config.server.utils.GroupKey2; import com.alibaba.nacos.config.server.utils.LogUtil; -import com.alibaba.nacos.config.server.utils.MD5; import com.alibaba.nacos.config.server.utils.RequestUtil; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; @@ -66,7 +67,7 @@ public class RequestLogAspect { public Object interfacePublishSingle(ProceedingJoinPoint pjp, HttpServletRequest request, HttpServletResponse response, String dataId, String group, String tenant, String content) throws Throwable { - final String md5 = content == null ? null : MD5.getInstance().getMD5String(content); + final String md5 = content == null ? null : Md5Utils.getMD5(content, Constants.ENCODE); MetricsMonitor.getPublishMonitor().incrementAndGet(); return logClientRequest("publish", pjp, request, response, dataId, group, tenant, md5); } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoBase.java b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoBase.java index 55151910e94..a6cf6944952 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoBase.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoBase.java @@ -15,7 +15,8 @@ */ package com.alibaba.nacos.config.server.model; -import com.alibaba.nacos.config.server.utils.MD5; +import com.alibaba.nacos.common.utils.Md5Utils; +import com.alibaba.nacos.config.server.constant.Constants; import java.io.PrintWriter; import java.io.Serializable; @@ -46,7 +47,7 @@ public ConfigInfoBase(String dataId, String group, String content) { this.group = group; this.content = content; if (this.content != null) { - this.md5 = MD5.getInstance().getMD5String(this.content); + this.md5 = Md5Utils.getMD5(this.content, Constants.ENCODE); } } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigService.java index 62c79028c80..8c9fa115434 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigService.java @@ -15,12 +15,12 @@ */ package com.alibaba.nacos.config.server.service; +import com.alibaba.nacos.common.utils.Md5Utils; import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.model.CacheItem; import com.alibaba.nacos.config.server.model.ConfigInfoBase; import com.alibaba.nacos.config.server.utils.GroupKey; import com.alibaba.nacos.config.server.utils.GroupKey2; -import com.alibaba.nacos.config.server.utils.MD5; import com.alibaba.nacos.config.server.utils.PropertyUtil; import com.alibaba.nacos.config.server.utils.event.EventDispatcher; import org.apache.commons.lang3.StringUtils; @@ -70,7 +70,8 @@ static public boolean dump(String dataId, String group, String tenant, String co } try { - final String md5 = MD5.getInstance().getMD5String(content); + final String md5 = Md5Utils.getMD5(content, Constants.ENCODE); + if (md5.equals(ConfigService.getContentMd5(groupKey))) { dumpLog.warn( "[dump-ignore] ignore to save cache file. groupKey={}, md5={}, lastModifiedOld={}, " @@ -115,7 +116,7 @@ static public boolean dumpBeta(String dataId, String group, String tenant, Strin } try { - final String md5 = MD5.getInstance().getMD5String(content); + final String md5 = Md5Utils.getMD5(content, Constants.ENCODE); if (md5.equals(ConfigService.getContentBetaMd5(groupKey))) { dumpLog.warn( "[dump-beta-ignore] ignore to save cache file. groupKey={}, md5={}, lastModifiedOld={}, " @@ -154,7 +155,7 @@ static public boolean dumpTag(String dataId, String group, String tenant, String } try { - final String md5 = MD5.getInstance().getMD5String(content); + final String md5 = Md5Utils.getMD5(content, Constants.ENCODE); if (md5.equals(ConfigService.getContentTagMd5(groupKey, tag))) { dumpLog.warn( "[dump-tag-ignore] ignore to save cache file. groupKey={}, md5={}, lastModifiedOld={}, " @@ -191,7 +192,7 @@ static public boolean dumpChange(String dataId, String group, String tenant, Str } try { - final String md5 = MD5.getInstance().getMD5String(content); + final String md5 = Md5Utils.getMD5(content, Constants.ENCODE); if (!STANDALONE_MODE || PropertyUtil.isStandaloneUseMysql()) { String loacalMd5 = DiskUtil.getLocalConfigMd5(dataId, group, tenant); if (md5.equals(loacalMd5)) { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/DiskUtil.java b/config/src/main/java/com/alibaba/nacos/config/server/service/DiskUtil.java index d72e77a58a4..5d0450f0eb8 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/DiskUtil.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/DiskUtil.java @@ -16,9 +16,9 @@ package com.alibaba.nacos.config.server.service; import com.alibaba.nacos.common.utils.IoUtils; +import com.alibaba.nacos.common.utils.Md5Utils; import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.utils.LogUtil; -import com.alibaba.nacos.config.server.utils.MD5; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -172,7 +172,7 @@ static public String getConfig(String dataId, String group, String tenant) static public String getLocalConfigMd5(String dataId, String group, String tenant) throws IOException { - return MD5.getInstance().getMD5String(getConfig(dataId, group, tenant)); + return Md5Utils.getMD5(getConfig(dataId, group, tenant), Constants.ENCODE); } static public File heartBeatFile() { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/PersistService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/PersistService.java index 96c1f7b4a4d..82635f2c684 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/PersistService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/PersistService.java @@ -15,11 +15,12 @@ */ package com.alibaba.nacos.config.server.service; +import com.alibaba.nacos.common.utils.Md5Utils; +import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.enums.FileTypeEnum; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.config.server.model.*; import com.alibaba.nacos.config.server.utils.LogUtil; -import com.alibaba.nacos.config.server.utils.MD5; import com.alibaba.nacos.config.server.utils.PaginationHelper; import com.alibaba.nacos.config.server.utils.ParamUtils; import com.alibaba.nacos.config.server.utils.event.EventDispatcher; @@ -537,7 +538,7 @@ public void addConfigInfo4Beta(ConfigInfo configInfo, String betaIps, String appNameTmp = StringUtils.isBlank(configInfo.getAppName()) ? StringUtils.EMPTY : configInfo.getAppName(); String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant(); try { - String md5 = MD5.getInstance().getMD5String(configInfo.getContent()); + String md5 = Md5Utils.getMD5(configInfo.getContent(), Constants.ENCODE); jt.update( "INSERT INTO config_info_beta(data_id,group_id,tenant_id,app_name,content,md5,beta_ips,src_ip," + "src_user,gmt_create,gmt_modified) VALUES(?,?,?,?,?,?,?,?,?,?,?)", @@ -563,7 +564,7 @@ public void addConfigInfo4Tag(ConfigInfo configInfo, String tag, String srcIp, S String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant(); String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim(); try { - String md5 = MD5.getInstance().getMD5String(configInfo.getContent()); + String md5 = Md5Utils.getMD5(configInfo.getContent(), Constants.ENCODE); jt.update( "INSERT INTO config_info_tag(data_id,group_id,tenant_id,tag_id,app_name,content,md5,src_ip,src_user," + "gmt_create,gmt_modified) VALUES(?,?,?,?,?,?,?,?,?,?,?)", @@ -627,7 +628,7 @@ public void updateConfigInfo4Beta(ConfigInfo configInfo, String srcIp, String sr String appNameTmp = StringUtils.isBlank(configInfo.getAppName()) ? StringUtils.EMPTY : configInfo.getAppName(); String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant(); try { - String md5 = MD5.getInstance().getMD5String(configInfo.getContent()); + String md5 = Md5Utils.getMD5(configInfo.getContent(), Constants.ENCODE); jt.update( "UPDATE config_info_beta SET content=?, md5 = ?, src_ip=?,src_user=?,gmt_modified=?,app_name=? WHERE " + "data_id=? AND group_id=? AND tenant_id=?", @@ -653,7 +654,7 @@ public void updateConfigInfo4Tag(ConfigInfo configInfo, String tag, String srcIp String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant(); String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim(); try { - String md5 = MD5.getInstance().getMD5String(configInfo.getContent()); + String md5 = Md5Utils.getMD5(configInfo.getContent(), Constants.ENCODE); jt.update( "UPDATE config_info_tag SET content=?, md5 = ?, src_ip=?,src_user=?,gmt_modified=?,app_name=? WHERE " + "data_id=? AND group_id=? AND tenant_id=? AND tag_id=?", @@ -2694,7 +2695,7 @@ private long addConfigInfoAtomic(final String srcIp, final String srcUser, final final String type = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("type"); final String schema = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("schema"); - final String md5Tmp = MD5.getInstance().getMD5String(configInfo.getContent()); + final String md5Tmp = Md5Utils.getMD5(configInfo.getContent(), Constants.ENCODE); KeyHolder keyHolder = new GeneratedKeyHolder(); @@ -2903,7 +2904,7 @@ private void updateConfigInfoAtomic(final ConfigInfo configInfo, final String sr final Timestamp time, Map configAdvanceInfo) { String appNameTmp = StringUtils.isBlank(configInfo.getAppName()) ? StringUtils.EMPTY : configInfo.getAppName(); String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant(); - final String md5Tmp = MD5.getInstance().getMD5String(configInfo.getContent()); + final String md5Tmp = Md5Utils.getMD5(configInfo.getContent(), Constants.ENCODE); String desc = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("desc"); String use = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("use"); String effect = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("effect"); @@ -3060,7 +3061,7 @@ private void insertConfigHistoryAtomic(long id, ConfigInfo configInfo, String sr final Timestamp time, String ops) { String appNameTmp = StringUtils.isBlank(configInfo.getAppName()) ? StringUtils.EMPTY : configInfo.getAppName(); String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant(); - final String md5Tmp = MD5.getInstance().getMD5String(configInfo.getContent()); + final String md5Tmp = Md5Utils.getMD5(configInfo.getContent(), Constants.ENCODE); try { jt.update( "INSERT INTO his_config_info (id,data_id,group_id,tenant_id,app_name,content,md5,src_ip,src_user,gmt_modified,op_type) VALUES(?,?,?,?,?,?,?,?,?,?,?)", @@ -3354,8 +3355,7 @@ public Boolean completeMd5() { String md5InDb = cf.getMd5(); final String content = cf.getContent(); final String tenant = cf.getTenant(); - final String md5 = MD5.getInstance().getMD5String( - content); + final String md5 = Md5Utils.getMD5(content, Constants.ENCODE); if (StringUtils.isBlank(md5InDb)) { try { updateMd5(cf.getDataId(), cf.getGroup(), tenant, md5, new Timestamp(cf.getLastModified())); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpService.java index e0945ef79c3..0a59ceadbee 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpService.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.config.server.service.dump; import com.alibaba.nacos.common.utils.IoUtils; +import com.alibaba.nacos.common.utils.Md5Utils; import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.manager.TaskManager; import com.alibaba.nacos.config.server.model.ConfigInfo; @@ -346,7 +347,8 @@ public void run() { ConfigInfo cf = MergeTaskProcessor.merge(dataId, group, tenant, datumList); String aggrContent = cf.getContent(); String localContentMD5 = ConfigService.getContentMd5(GroupKey.getKey(dataId, group)); - String aggrConetentMD5 = MD5.getInstance().getMD5String(aggrContent); + String aggrConetentMD5 = Md5Utils.getMD5(aggrContent, Constants.ENCODE); + if (!StringUtils.equals(localContentMD5, aggrConetentMD5)) { persistService.insertOrUpdate(null, null, cf, time, null, false); log.info("[merge-ok] {}, {}, size={}, length={}, md5={}, content={}", dataId, group, diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpTask.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpTask.java index c7ba1d98380..e3479f58b8c 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpTask.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpTask.java @@ -15,6 +15,8 @@ */ package com.alibaba.nacos.config.server.service.dump; +import com.alibaba.nacos.common.utils.Md5Utils; +import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.manager.AbstractTask; import com.alibaba.nacos.config.server.manager.TaskProcessor; import com.alibaba.nacos.config.server.model.ConfigInfo; @@ -28,7 +30,6 @@ import com.alibaba.nacos.config.server.service.trace.ConfigTraceService; import com.alibaba.nacos.config.server.utils.GroupKey2; import com.alibaba.nacos.config.server.utils.LogUtil; -import com.alibaba.nacos.config.server.utils.MD5; import org.apache.commons.lang3.StringUtils; import java.sql.Timestamp; @@ -264,7 +265,7 @@ public boolean process(String taskType, AbstractTask task) { cf.getLastModified(), cf.getType()); final String content = cf.getContent(); - final String md5 = MD5.getInstance().getMD5String(content); + final String md5 = Md5Utils.getMD5(content, Constants.ENCODE); LogUtil.dumpLog.info("[dump-all-ok] {}, {}, length={}, md5={}", GroupKey2.getKey(cf.getDataId(), cf.getGroup()), cf.getLastModified(), content.length(), md5); } @@ -409,7 +410,7 @@ public boolean process(String taskType, AbstractTask task) { boolean result = ConfigService.dumpChange(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getContent(), cf.getLastModified()); final String content = cf.getContent(); - final String md5 = MD5.getInstance().getMD5String(content); + final String md5 = Md5Utils.getMD5(content, Constants.ENCODE); LogUtil.defaultLog.info( "[dump-change-ok] {}, {}, length={}, md5={}", new Object[] { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/trace/ConfigTraceService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/trace/ConfigTraceService.java index 5821068400f..1775cf89345 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/trace/ConfigTraceService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/trace/ConfigTraceService.java @@ -15,9 +15,10 @@ */ package com.alibaba.nacos.config.server.service.trace; +import com.alibaba.nacos.common.utils.Md5Utils; +import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.monitor.MetricsMonitor; import com.alibaba.nacos.config.server.utils.LogUtil; -import com.alibaba.nacos.config.server.utils.MD5; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; @@ -61,7 +62,8 @@ public static void logPersistenceEvent(String dataId, String group, String tenan } //localIp | dataid | group | tenant | requestIpAppName | ts | handleIp | event | type | [delayed = -1] | ext // (md5) - String md5 = content == null ? null : MD5.getInstance().getMD5String(content); + String md5 = content == null ? null : Md5Utils.getMD5(content, Constants.ENCODE); + LogUtil.traceLog.info("{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}", LOCAL_IP, dataId, group, tenant, requestIpAppName, ts, handleIp, "persist", type, -1, md5); } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/utils/MD5.java b/config/src/main/java/com/alibaba/nacos/config/server/utils/MD5.java deleted file mode 100644 index 773625d7dad..00000000000 --- a/config/src/main/java/com/alibaba/nacos/config/server/utils/MD5.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.alibaba.nacos.config.server.utils; - -import com.alibaba.nacos.config.server.constant.Constants; -import com.google.common.collect.Maps; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; -import java.util.Map; -import java.util.concurrent.locks.ReentrantLock; - -/** - * md5 - * - * @author Nacos - */ -@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule") -public class MD5 { - private static char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - private static final int DIGITS_COUNT = 16; - private static final int DIGITS_CHAR_SIZE = 32; - - private static Map rDigits = Maps.newHashMapWithExpectedSize(16); - - static { - for (int i = 0; i < digits.length; ++i) { - rDigits.put(digits[i], i); - } - } - - private static MD5 me = new MD5(); - private MessageDigest mHasher; - private ReentrantLock opLock = new ReentrantLock(); - - private MD5() { - try { - mHasher = MessageDigest.getInstance("md5"); - } catch (Exception e) { - throw new RuntimeException(e); - } - - } - - public static MD5 getInstance() { - return me; - } - - public String getMD5String(String content) { - return bytes2string(hash(content)); - } - - public String getMD5String(byte[] content) { - return bytes2string(hash(content)); - } - - public byte[] getMD5Bytes(byte[] content) { - return hash(content); - } - - /** - * 对字符串进行md5 - * - * @param str - * @return md5 byte[16] - */ - public byte[] hash(String str) { - opLock.lock(); - try { - byte[] bt = mHasher.digest(str.getBytes(Constants.ENCODE)); - if (null == bt || bt.length != DIGITS_COUNT) { - throw new IllegalArgumentException("md5 need"); - } - return bt; - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("unsupported utf-8 encoding", e); - } finally { - opLock.unlock(); - } - } - - /** - * 对二进制数据进行md5 - * - * @param str - * @return md5 byte[16] - */ - public byte[] hash(byte[] data) { - opLock.lock(); - try { - byte[] bt = mHasher.digest(data); - if (null == bt || bt.length != DIGITS_COUNT) { - throw new IllegalArgumentException("md5 need"); - } - return bt; - } finally { - opLock.unlock(); - } - } - - /** - * 将一个字节数组转化为可见的字符串 - * - * @param bt - * @return - */ - public String bytes2string(byte[] bt) { - int l = bt.length; - - char[] out = new char[l << 1]; - - for (int i = 0, j = 0; i < l; i++) { - out[j++] = digits[(0xF0 & bt[i]) >>> 4]; - out[j++] = digits[0x0F & bt[i]]; - } - - return new String(out); - } - - /** - * 将字符串转换为bytes - * - * @param str - * @return byte[] - */ - public byte[] string2bytes(String str) { - if (null == str) { - throw new NullPointerException("参数不能为空"); - } - if (str.length() != DIGITS_CHAR_SIZE) { - throw new IllegalArgumentException("字符串长度必须是32"); - } - byte[] data = new byte[16]; - char[] chs = str.toCharArray(); - for (int i = 0; i < DIGITS_COUNT; ++i) { - int h = rDigits.get(chs[i * 2]); - int l = rDigits.get(chs[i * 2 + 1]); - data[i] = (byte)((h & 0x0F) << 4 | (l & 0x0F)); - } - return data; - } - -} diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/Instances.java b/naming/src/main/java/com/alibaba/nacos/naming/core/Instances.java index 49ad3b913e8..55d16bb151a 100644 --- a/naming/src/main/java/com/alibaba/nacos/naming/core/Instances.java +++ b/naming/src/main/java/com/alibaba/nacos/naming/core/Instances.java @@ -17,15 +17,10 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.annotation.JSONField; -import com.alibaba.nacos.naming.misc.Loggers; +import com.alibaba.nacos.common.utils.Md5Utils; import com.alibaba.nacos.naming.pojo.Record; -import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; -import java.math.BigInteger; -import java.nio.charset.Charset; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -39,17 +34,6 @@ */ public class Instances implements Record { - private static MessageDigest MESSAGE_DIGEST; - - static { - try { - MESSAGE_DIGEST = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - Loggers.SRV_LOG.error("error while calculating checksum(md5) for instances", e); - MESSAGE_DIGEST = null; - } - } - private List instanceList = new ArrayList<>(); public List getInstanceList() { @@ -73,7 +57,6 @@ public String getChecksum() { } private String recalculateChecksum() { - String checksum; StringBuilder sb = new StringBuilder(); Collections.sort(instanceList); for (Instance ip : instanceList) { @@ -83,13 +66,7 @@ private String recalculateChecksum() { sb.append(","); } - if (MESSAGE_DIGEST != null) { - checksum = - new BigInteger(1, MESSAGE_DIGEST.digest((sb.toString()).getBytes(Charset.forName("UTF-8")))).toString(16); - } else { - checksum = RandomStringUtils.randomAscii(32); - } - return checksum; + return Md5Utils.getMD5(sb.toString(), "UTF-8"); } public String convertMap2String(Map map) { diff --git a/naming/src/main/java/com/alibaba/nacos/naming/core/Service.java b/naming/src/main/java/com/alibaba/nacos/naming/core/Service.java index 5862ea50966..147fe13007b 100644 --- a/naming/src/main/java/com/alibaba/nacos/naming/core/Service.java +++ b/naming/src/main/java/com/alibaba/nacos/naming/core/Service.java @@ -17,6 +17,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.annotation.JSONField; +import com.alibaba.nacos.common.utils.Md5Utils; import com.alibaba.nacos.naming.boot.SpringContext; import com.alibaba.nacos.naming.consistency.KeyBuilder; import com.alibaba.nacos.naming.consistency.RecordListener; @@ -32,12 +33,8 @@ import com.alibaba.nacos.naming.selector.Selector; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.ListUtils; -import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; -import java.math.BigInteger; -import java.nio.charset.Charset; -import java.security.MessageDigest; import java.util.*; /** @@ -475,21 +472,7 @@ public synchronized void recalculateChecksum() { ipsString.append(","); } - try { - String result; - try { - MessageDigest md5 = MessageDigest.getInstance("MD5"); - result = new BigInteger(1, md5.digest((ipsString.toString()).getBytes(Charset.forName("UTF-8")))).toString(16); - } catch (Exception e) { - Loggers.SRV_LOG.error("[NACOS-DOM] error while calculating checksum(md5)", e); - result = RandomStringUtils.randomAscii(32); - } - - checksum = result; - } catch (Exception e) { - Loggers.SRV_LOG.error("[NACOS-DOM] error while calculating checksum(md5)", e); - checksum = RandomStringUtils.randomAscii(32); - } + checksum = Md5Utils.getMD5(ipsString.toString(), "UTF-8"); } private void updateOrAddCluster(Collection clusters) { diff --git a/naming/src/test/java/com/alibaba/nacos/naming/core/InstancesTest.java b/naming/src/test/java/com/alibaba/nacos/naming/core/InstancesTest.java new file mode 100644 index 00000000000..630d7d15934 --- /dev/null +++ b/naming/src/test/java/com/alibaba/nacos/naming/core/InstancesTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.naming.core; + +import org.junit.Test; + +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * @author lkxiaolou + */ +public class InstancesTest { + + private static MessageDigest MESSAGE_DIGEST; + + static { + try { + MESSAGE_DIGEST = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + MESSAGE_DIGEST = null; + } + } + + private static ThreadLocal MESSAGE_DIGEST_LOCAL = new ThreadLocal() { + @Override + protected MessageDigest initialValue() { + try { + return MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + return null; + } + } + }; + + @Test + public void checkSumNotThreadSafe() throws Exception { + + final AtomicBoolean catchException = new AtomicBoolean(false); + CountDownLatch countDownLatch = new CountDownLatch(4); + + for (int i = 0; i < 4; i++) { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + while (true) { + if (catchException.get()) { + break; + } + try { + checkSumThreadNotSafeVersion("test"); + } catch (ArrayIndexOutOfBoundsException e) { + catchException.set(true); + } + } + countDownLatch.countDown(); + } + }); + thread.start(); + } + + countDownLatch.await(); + + assert catchException.get(); + } + + //@Test + // 跑起来比较久,所以注释掉 + public void checkSumThreadSafe() throws Exception { + + CountDownLatch countDownLatch = new CountDownLatch(4); + + for (int i = 0; i < 4; i++) { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + for (int j = 0; j < Integer.MAX_VALUE; j++) { + checkSumThreadSafeVersion("test"); + } + countDownLatch.countDown(); + } + }); + thread.start(); + } + countDownLatch.await(); + } + + private String checkSumThreadNotSafeVersion(String checkString) { + return new BigInteger(1, MESSAGE_DIGEST.digest((checkString).getBytes(Charset.forName("UTF-8")))).toString(16); + } + + private String checkSumThreadSafeVersion(String checkString) { + return new BigInteger(1, MESSAGE_DIGEST_LOCAL.get().digest((checkString).getBytes(Charset.forName("UTF-8")))).toString(16); + } +}