Merge pull request #2924 from alibaba/feature_1.3.0_beta_grpc_perf
Feature 1.3.0 beta grpc perf
This commit is contained in:
commit
a8c5a8da26
@ -21,13 +21,17 @@ package com.alibaba.nacos.client;
|
||||
import com.alibaba.nacos.api.NacosFactory;
|
||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||
import com.alibaba.nacos.api.config.ConfigService;
|
||||
import com.alibaba.nacos.api.config.listener.AbstractListener;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
@ -35,20 +39,20 @@ import java.util.Properties;
|
||||
@Ignore
|
||||
public class ConfigTest {
|
||||
|
||||
private ConfigService configService;
|
||||
private static ConfigService configService;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
public static void main(String[] args) throws Exception {
|
||||
before();
|
||||
test();
|
||||
}
|
||||
|
||||
public static void before() throws Exception {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(PropertyKeyConst.NAMESPACE, "bebf0150-e1ea-47e2-81fe-6814caf2b952");
|
||||
properties.setProperty(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848");
|
||||
properties.setProperty(PropertyKeyConst.USERNAME, "chuntaojun");
|
||||
properties.setProperty(PropertyKeyConst.PASSWORD, "1017");
|
||||
configService = NacosFactory.createConfigService(properties);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
public static void test() throws Exception {
|
||||
final String dataId = "lessspring";
|
||||
final String group = "lessspring";
|
||||
final String content = "lessspring-" + System.currentTimeMillis();
|
||||
@ -56,8 +60,25 @@ public class ConfigTest {
|
||||
Assert.assertTrue(result);
|
||||
|
||||
ThreadUtils.sleep(10_000);
|
||||
String response = configService.getConfig(dataId, group, 5000);
|
||||
System.out.println(response);
|
||||
|
||||
String response = configService.getConfigAndSignListener(dataId, group, 5000, new AbstractListener() {
|
||||
@Override
|
||||
public void receiveConfigInfo(String configInfo) {
|
||||
System.err.println(configInfo);
|
||||
}
|
||||
});
|
||||
Assert.assertEquals(content, response);
|
||||
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
System.out.println("input content");
|
||||
while (scanner.hasNextLine()){
|
||||
String s = scanner.next();
|
||||
if (Objects.equals("exit", s)) {
|
||||
scanner.close();
|
||||
return;
|
||||
}
|
||||
configService.publishConfig(dataId, group, s);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -82,8 +82,8 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>7</source>
|
||||
<target>7</target>
|
||||
<source>6</source>
|
||||
<target>6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
@ -16,10 +16,8 @@
|
||||
|
||||
package com.alibaba.nacos.common.executor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
@ -39,19 +37,6 @@ public final class ExecutorFactory {
|
||||
|
||||
public static final String DEFAULT_NAMESPACE = "nacos";
|
||||
|
||||
public static ForkJoinPool newForkJoinPool(final String group) {
|
||||
ForkJoinPool forkJoinPool = new ForkJoinPool();
|
||||
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, forkJoinPool);
|
||||
return forkJoinPool;
|
||||
}
|
||||
|
||||
public static ForkJoinPool newForkJoinPool(final String group,
|
||||
final int nThreads) {
|
||||
ForkJoinPool forkJoinPool = new ForkJoinPool(nThreads);
|
||||
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, forkJoinPool);
|
||||
return forkJoinPool;
|
||||
}
|
||||
|
||||
public static ExecutorService newSingleExecutorService(final String group) {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(1);
|
||||
THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);
|
||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.common.executor;
|
||||
|
||||
|
||||
import com.alibaba.nacos.common.utils.ShutdownUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -69,7 +70,7 @@ public final class ThreadPoolManager {
|
||||
private ThreadPoolManager() {}
|
||||
|
||||
private void init() {
|
||||
resourcesManager = new ConcurrentHashMap<>(8);
|
||||
resourcesManager = new ConcurrentHashMap<String, Map<String, Set<ExecutorService>>>(8);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,7 +90,7 @@ public final class ThreadPoolManager {
|
||||
synchronized (monitor) {
|
||||
Map<String, Set<ExecutorService>> map = resourcesManager.get(namespace);
|
||||
if (map == null) {
|
||||
map = new HashMap<>(8);
|
||||
map = new HashMap<String, Set<ExecutorService>>(8);
|
||||
map.put(group, new HashSet<ExecutorService>());
|
||||
map.get(group).add(executor);
|
||||
resourcesManager.put(namespace, map);
|
||||
@ -136,7 +137,12 @@ public final class ThreadPoolManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy(String namespace) {
|
||||
/**
|
||||
* Destroys all thread pool resources under this namespace
|
||||
*
|
||||
* @param namespace namespace
|
||||
*/
|
||||
public void destroy(final String namespace) {
|
||||
final Object monitor = lockers.get(namespace);
|
||||
if (monitor == null) {
|
||||
return;
|
||||
@ -148,7 +154,7 @@ public final class ThreadPoolManager {
|
||||
}
|
||||
for (Map.Entry<String, Set<ExecutorService>> entry : subResource.entrySet()) {
|
||||
for (ExecutorService executor : entry.getValue()) {
|
||||
shutdownThreadPool(executor);
|
||||
ThreadUtils.shutdownThreadPool(executor);
|
||||
}
|
||||
}
|
||||
resourcesManager.get(namespace).clear();
|
||||
@ -156,23 +162,28 @@ public final class ThreadPoolManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void shutdownThreadPool(ExecutorService executor) {
|
||||
executor.shutdown();
|
||||
int retry = 3;
|
||||
while (retry > 0) {
|
||||
retry --;
|
||||
try {
|
||||
if (executor.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||
return;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
executor.shutdownNow();
|
||||
Thread.interrupted();
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("ThreadPoolManager shutdown executor has error : {}", ex);
|
||||
}
|
||||
/**
|
||||
* This namespace destroys all thread pool resources under the grouping
|
||||
*
|
||||
* @param namespace namespace
|
||||
* @param group group
|
||||
*/
|
||||
public void destroy(final String namespace, final String group) {
|
||||
final Object monitor = lockers.get(namespace);
|
||||
if (monitor == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (monitor) {
|
||||
Map<String, Set<ExecutorService>> subResource = resourcesManager.get(namespace);
|
||||
if (subResource == null) {
|
||||
return;
|
||||
}
|
||||
Set<ExecutorService> waitDestroy = subResource.get(group);
|
||||
for (ExecutorService executor : waitDestroy) {
|
||||
ThreadUtils.shutdownThreadPool(executor);
|
||||
}
|
||||
resourcesManager.get(namespace).remove(group);
|
||||
}
|
||||
executor.shutdownNow();
|
||||
}
|
||||
|
||||
public static void shutdown() {
|
||||
|
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* 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.common.utils;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* copy from <link>org.apache.commons.collections</link>
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public final class CollectionUtils {
|
||||
|
||||
/**
|
||||
* Returns the <code>index</code>-th value in <code>object</code>, throwing
|
||||
* <code>IndexOutOfBoundsException</code> if there is no such element or
|
||||
* <code>IllegalArgumentException</code> if <code>object</code> is not an
|
||||
* instance of one of the supported types.
|
||||
* <p>
|
||||
* The supported types, and associated semantics are:
|
||||
* <ul>
|
||||
* <li> Map -- the value returned is the <code>Map.Entry</code> in position
|
||||
* <code>index</code> in the map's <code>entrySet</code> iterator,
|
||||
* if there is such an entry.</li>
|
||||
* <li> List -- this method is equivalent to the list's get method.</li>
|
||||
* <li> Array -- the <code>index</code>-th array entry is returned,
|
||||
* if there is such an entry; otherwise an <code>IndexOutOfBoundsException</code>
|
||||
* is thrown.</li>
|
||||
* <li> Collection -- the value returned is the <code>index</code>-th object
|
||||
* returned by the collection's default iterator, if there is such an element.</li>
|
||||
* <li> Iterator or Enumeration -- the value returned is the
|
||||
* <code>index</code>-th object in the Iterator/Enumeration, if there
|
||||
* is such an element. The Iterator/Enumeration is advanced to
|
||||
* <code>index</code> (or to the end, if <code>index</code> exceeds the
|
||||
* number of entries) as a side effect of this method.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param object the object to get a value from
|
||||
* @param index the index to get
|
||||
* @return the object at the specified index
|
||||
* @throws IndexOutOfBoundsException if the index is invalid
|
||||
* @throws IllegalArgumentException if the object type is invalid
|
||||
*/
|
||||
public static Object get(Object object, int index) {
|
||||
if (index < 0) {
|
||||
throw new IndexOutOfBoundsException("Index cannot be negative: " + index);
|
||||
}
|
||||
if (object instanceof Map) {
|
||||
Map map = (Map) object;
|
||||
Iterator iterator = map.entrySet().iterator();
|
||||
return get(iterator, index);
|
||||
} else if (object instanceof List) {
|
||||
return ((List) object).get(index);
|
||||
} else if (object instanceof Object[]) {
|
||||
return ((Object[]) object)[index];
|
||||
} else if (object instanceof Iterator) {
|
||||
Iterator it = (Iterator) object;
|
||||
while (it.hasNext()) {
|
||||
index--;
|
||||
if (index == -1) {
|
||||
return it.next();
|
||||
} else {
|
||||
it.next();
|
||||
}
|
||||
}
|
||||
throw new IndexOutOfBoundsException("Entry does not exist: " + index);
|
||||
} else if (object instanceof Collection) {
|
||||
Iterator iterator = ((Collection) object).iterator();
|
||||
return get(iterator, index);
|
||||
} else if (object instanceof Enumeration) {
|
||||
Enumeration it = (Enumeration) object;
|
||||
while (it.hasMoreElements()) {
|
||||
index--;
|
||||
if (index == -1) {
|
||||
return it.nextElement();
|
||||
} else {
|
||||
it.nextElement();
|
||||
}
|
||||
}
|
||||
throw new IndexOutOfBoundsException("Entry does not exist: " + index);
|
||||
} else if (object == null) {
|
||||
throw new IllegalArgumentException("Unsupported object type: null");
|
||||
} else {
|
||||
try {
|
||||
return Array.get(object, index);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the collection/iterator specified.
|
||||
* <p>
|
||||
* This method can handles objects as follows
|
||||
* <ul>
|
||||
* <li>Collection - the collection size
|
||||
* <li>Map - the map size
|
||||
* <li>Array - the array size
|
||||
* <li>Iterator - the number of elements remaining in the iterator
|
||||
* <li>Enumeration - the number of elements remaining in the enumeration
|
||||
* </ul>
|
||||
*
|
||||
* @param object the object to get the size of
|
||||
* @return the size of the specified collection
|
||||
* @throws IllegalArgumentException thrown if object is not recognised or null
|
||||
* @since Commons Collections 3.1
|
||||
*/
|
||||
public static int size(Object object) {
|
||||
int total = 0;
|
||||
if (object instanceof Map) {
|
||||
total = ((Map) object).size();
|
||||
} else if (object instanceof Collection) {
|
||||
total = ((Collection) object).size();
|
||||
} else if (object instanceof Object[]) {
|
||||
total = ((Object[]) object).length;
|
||||
} else if (object instanceof Iterator) {
|
||||
Iterator it = (Iterator) object;
|
||||
while (it.hasNext()) {
|
||||
total++;
|
||||
it.next();
|
||||
}
|
||||
} else if (object instanceof Enumeration) {
|
||||
Enumeration it = (Enumeration) object;
|
||||
while (it.hasMoreElements()) {
|
||||
total++;
|
||||
it.nextElement();
|
||||
}
|
||||
} else if (object == null) {
|
||||
throw new IllegalArgumentException("Unsupported object type: null");
|
||||
} else {
|
||||
try {
|
||||
total = Array.getLength(object);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public static boolean sizeIsEmpty(Object object) {
|
||||
if (object instanceof Collection) {
|
||||
return ((Collection) object).isEmpty();
|
||||
} else if (object instanceof Map) {
|
||||
return ((Map) object).isEmpty();
|
||||
} else if (object instanceof Object[]) {
|
||||
return ((Object[]) object).length == 0;
|
||||
} else if (object instanceof Iterator) {
|
||||
return ((Iterator) object).hasNext() == false;
|
||||
} else if (object instanceof Enumeration) {
|
||||
return ((Enumeration) object).hasMoreElements() == false;
|
||||
} else if (object == null) {
|
||||
throw new IllegalArgumentException("Unsupported object type: null");
|
||||
} else {
|
||||
try {
|
||||
return Array.getLength(object) == 0;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe check if the specified collection is empty.
|
||||
* <p>
|
||||
* Null returns true.
|
||||
*
|
||||
* @param coll the collection to check, may be null
|
||||
* @return true if empty or null
|
||||
* @since Commons Collections 3.2
|
||||
*/
|
||||
public static boolean isEmpty(Collection coll) {
|
||||
return (coll == null || coll.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe check if the specified collection is not empty.
|
||||
* <p>
|
||||
* Null returns false.
|
||||
*
|
||||
* @param coll the collection to check, may be null
|
||||
* @return true if non-null and non-empty
|
||||
* @since Commons Collections 3.2
|
||||
*/
|
||||
public static boolean isNotEmpty(Collection coll) {
|
||||
return !CollectionUtils.isEmpty(coll);
|
||||
}
|
||||
|
||||
}
|
@ -42,7 +42,7 @@ public final class ConvertUtils {
|
||||
return Long.parseLong(val);
|
||||
}
|
||||
|
||||
public static boolean toBoolean(String val, boolean defaultValue) {
|
||||
public static boolean toBool(String val, boolean defaultValue) {
|
||||
if (StringUtils.isBlank(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
@ -41,18 +41,23 @@ public class ExceptionUtil {
|
||||
return strBuilder.toString();
|
||||
}
|
||||
|
||||
public static Throwable getCause(final Throwable t) {
|
||||
final Throwable cause = t.getCause();
|
||||
if (Objects.isNull(cause)) {
|
||||
return t;
|
||||
}
|
||||
return cause;
|
||||
}
|
||||
|
||||
public static String getStackTrace(final Throwable t) {
|
||||
if (t == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
try (final ByteArrayOutputStream out = new ByteArrayOutputStream(); final PrintStream ps = new PrintStream(out)) {
|
||||
t.printStackTrace(ps);
|
||||
ps.flush();
|
||||
return new String(out.toByteArray());
|
||||
} catch (final IOException ignored) {
|
||||
// ignored
|
||||
}
|
||||
return "";
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
final PrintStream ps = new PrintStream(out);
|
||||
t.printStackTrace(ps);
|
||||
ps.flush();
|
||||
return new String(out.toByteArray());
|
||||
}
|
||||
}
|
||||
|
@ -44,90 +44,99 @@ public final class JacksonUtils {
|
||||
}
|
||||
|
||||
public static String toJson(Object obj) {
|
||||
try {
|
||||
return mapper.writeValueAsString(obj);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new NacosSerializationException(obj.getClass(), e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return mapper.writeValueAsString(obj);
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
throw new NacosSerializationException(obj.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] toJsonBytes(Object obj) {
|
||||
try {
|
||||
return ByteUtils.toBytes(mapper.writeValueAsString(obj));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new NacosSerializationException(obj.getClass(), e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return ByteUtils.toBytes(mapper.writeValueAsString(obj));
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
throw new NacosSerializationException(obj.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T toObj(byte[] json, Class<T> cls) {
|
||||
try {
|
||||
return toObj(StringUtils.newString4UTF8(json), cls);
|
||||
} catch (Exception e) {
|
||||
throw new NacosDeserializationException(cls, e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return toObj(StringUtils.newString4UTF8(json), cls);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new NacosDeserializationException(cls, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T toObj(byte[] json, Type cls) {
|
||||
try {
|
||||
return toObj(StringUtils.newString4UTF8(json), cls);
|
||||
} catch (Exception e) {
|
||||
throw new NacosDeserializationException(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return toObj(StringUtils.newString4UTF8(json), cls);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new NacosDeserializationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T toObj(byte[] json, TypeReference<T> typeReference) {
|
||||
try {
|
||||
return toObj(StringUtils.newString4UTF8(json), typeReference);
|
||||
} catch (Exception e) {
|
||||
throw new NacosDeserializationException(e);
|
||||
}
|
||||
}
|
||||
public static <T> T toObj(byte[] json, TypeReference<T> typeReference) {
|
||||
try {
|
||||
return toObj(StringUtils.newString4UTF8(json), typeReference);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new NacosDeserializationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T toObj(String json, Class<T> cls) {
|
||||
try {
|
||||
return mapper.readValue(json, cls);
|
||||
} catch (IOException e) {
|
||||
throw new NacosDeserializationException(cls, e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return mapper.readValue(json, cls);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new NacosDeserializationException(cls, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T toObj(String json, Type type) {
|
||||
try {
|
||||
return mapper.readValue(json, mapper.constructType(type));
|
||||
} catch (IOException e) {
|
||||
throw new NacosDeserializationException(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return mapper.readValue(json, mapper.constructType(type));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new NacosDeserializationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T toObj(String json, TypeReference<T> typeReference) {
|
||||
try {
|
||||
return mapper.readValue(json, typeReference);
|
||||
} catch (IOException e) {
|
||||
throw new NacosDeserializationException(typeReference.getClass(), e);
|
||||
}
|
||||
}
|
||||
public static <T> T toObj(String json, TypeReference<T> typeReference) {
|
||||
try {
|
||||
return mapper.readValue(json, typeReference);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new NacosDeserializationException(typeReference.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static JsonNode toObj(String json) {
|
||||
try {
|
||||
return mapper.readTree(json);
|
||||
} catch (IOException e) {
|
||||
throw new NacosDeserializationException(e);
|
||||
}
|
||||
}
|
||||
public static JsonNode toObj(String json) {
|
||||
try {
|
||||
return mapper.readTree(json);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new NacosDeserializationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerSubtype(Class<?> clz, String type) {
|
||||
mapper.registerSubtypes(new NamedType(clz, type));
|
||||
}
|
||||
mapper.registerSubtypes(new NamedType(clz, type));
|
||||
}
|
||||
|
||||
public static ObjectNode createEmptyJsonNode() {
|
||||
return new ObjectNode(mapper.getNodeFactory());
|
||||
}
|
||||
public static ObjectNode createEmptyJsonNode() {
|
||||
return new ObjectNode(mapper.getNodeFactory());
|
||||
}
|
||||
|
||||
public static ArrayNode createEmptyArrayNode() {
|
||||
return new ArrayNode(mapper.getNodeFactory());
|
||||
}
|
||||
public static ArrayNode createEmptyArrayNode() {
|
||||
return new ArrayNode(mapper.getNodeFactory());
|
||||
}
|
||||
|
||||
public static JsonNode transferToJsonNode(Object obj) {
|
||||
return mapper.valueToTree(obj);
|
||||
}
|
||||
public static JsonNode transferToJsonNode(Object obj) {
|
||||
return mapper.valueToTree(obj);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,16 @@ import org.slf4j.Logger;
|
||||
*/
|
||||
public final class LoggerUtils {
|
||||
|
||||
public static final String TRACE = "TRACE";
|
||||
|
||||
public static final String INFO = "INFO";
|
||||
|
||||
public static final String DEBUG = "DEBUG";
|
||||
|
||||
public static final String WARN = "WARN";
|
||||
|
||||
public static final String ERROR = "ERROR";
|
||||
|
||||
public static void printIfDebugEnabled(Logger logger, String s, Object... args) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(s, args);
|
||||
@ -35,4 +45,22 @@ public final class LoggerUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void printIfTraceEnabled(Logger logger, String s, Object... args) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(s, args);
|
||||
}
|
||||
}
|
||||
|
||||
public static void printIfWarnEnabled(Logger logger, String s, Object... args) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(s, args);
|
||||
}
|
||||
}
|
||||
|
||||
public static void printIfErrorEnabled(Logger logger, String s, Object... args) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(s, args);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
*
|
||||
* * 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.common.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Dictionary;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class MapUtils {
|
||||
|
||||
/**
|
||||
* Null-safe check if the specified Dictionary is empty.
|
||||
* <p>
|
||||
* Null returns true.
|
||||
*
|
||||
* @param map the collection to check, may be null
|
||||
* @return true if empty or null
|
||||
*/
|
||||
public static boolean isEmpty(Map map) {
|
||||
return (map == null || map.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe check if the specified Dictionary is not empty.
|
||||
* <p>
|
||||
* Null returns false.
|
||||
*
|
||||
* @param map the collection to check, may be null
|
||||
* @return true if non-null and non-empty
|
||||
*/
|
||||
public static boolean isNotEmpty(Map map) {
|
||||
return !isEmpty(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe check if the specified Dictionary is empty.
|
||||
* <p>
|
||||
* Null returns true.
|
||||
*
|
||||
* @param coll the collection to check, may be null
|
||||
* @return true if empty or null
|
||||
*/
|
||||
public static boolean isEmpty(Dictionary coll) {
|
||||
return (coll == null || coll.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Null-safe check if the specified Dictionary is not empty.
|
||||
* <p>
|
||||
* Null returns false.
|
||||
*
|
||||
* @param coll the collection to check, may be null
|
||||
* @return true if non-null and non-empty
|
||||
*/
|
||||
public static boolean isNotEmpty(Dictionary coll) {
|
||||
return !isEmpty(coll);
|
||||
}
|
||||
|
||||
public static void putIfValNoNull(Map target, Object key, Object value) {
|
||||
Objects.requireNonNull(key, "key");
|
||||
if (value != null) {
|
||||
target.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void putIfValNoEmpty(Map target, Object key, Object value) {
|
||||
Objects.requireNonNull(key, "key");
|
||||
if (value instanceof String) {
|
||||
if (StringUtils.isNotEmpty((String) value)) {
|
||||
target.put(key, value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (value instanceof Collection) {
|
||||
if (CollectionUtils.isNotEmpty((Collection) value)) {
|
||||
target.put(key, value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (value instanceof Map) {
|
||||
if (isNotEmpty((Map) value)) {
|
||||
target.put(key, value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (value instanceof Dictionary) {
|
||||
if (isNotEmpty((Dictionary) value)) {
|
||||
target.put(key, value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
240
common/src/main/java/com/alibaba/nacos/common/utils/Objects.java
Normal file
240
common/src/main/java/com/alibaba/nacos/common/utils/Objects.java
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* 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.common.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class Objects {
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the arguments are equal to each other
|
||||
* and {@code false} otherwise.
|
||||
* Consequently, if both arguments are {@code null}, {@code true}
|
||||
* is returned and if exactly one argument is {@code null}, {@code
|
||||
* false} is returned. Otherwise, equality is determined by using
|
||||
* the {@link Object#equals equals} method of the first
|
||||
* argument.
|
||||
*
|
||||
* @param a an object
|
||||
* @param b an object to be compared with {@code a} for equality
|
||||
* @return {@code true} if the arguments are equal to each other
|
||||
* and {@code false} otherwise
|
||||
* @see Object#equals(Object)
|
||||
*/
|
||||
public static boolean equals(Object a, Object b) {
|
||||
return (a == b) || (a != null && a.equals(b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash code of a non-{@code null} argument and 0 for
|
||||
* a {@code null} argument.
|
||||
*
|
||||
* @param o an object
|
||||
* @return the hash code of a non-{@code null} argument and 0 for
|
||||
* a {@code null} argument
|
||||
* @see Object#hashCode
|
||||
*/
|
||||
public static int hashCode(Object o) {
|
||||
return o != null ? o.hashCode() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a hash code for a sequence of input values. The hash
|
||||
* code is generated as if all the input values were placed into an
|
||||
* array, and that array were hashed by calling {@link
|
||||
* Arrays#hashCode(Object[])}.
|
||||
*
|
||||
* <p>This method is useful for implementing {@link
|
||||
* Object#hashCode()} on objects containing multiple fields. For
|
||||
* example, if an object that has three fields, {@code x}, {@code
|
||||
* y}, and {@code z}, one could write:
|
||||
*
|
||||
* <blockquote><pre>
|
||||
* @Override public int hashCode() {
|
||||
* return Objects.hash(x, y, z);
|
||||
* }
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* <b>Warning: When a single object reference is supplied, the returned
|
||||
* value does not equal the hash code of that object reference.</b> This
|
||||
* value can be computed by calling {@link #hashCode(Object)}.
|
||||
*
|
||||
* @param values the values to be hashed
|
||||
* @return a hash value of the sequence of input values
|
||||
* @see Arrays#hashCode(Object[])
|
||||
* @see List#hashCode
|
||||
*/
|
||||
public static int hash(Object... values) {
|
||||
return Arrays.hashCode(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of calling {@code toString} for a non-{@code
|
||||
* null} argument and {@code "null"} for a {@code null} argument.
|
||||
*
|
||||
* @param o an object
|
||||
* @return the result of calling {@code toString} for a non-{@code
|
||||
* null} argument and {@code "null"} for a {@code null} argument
|
||||
* @see Object#toString
|
||||
* @see String#valueOf(Object)
|
||||
*/
|
||||
public static String toString(Object o) {
|
||||
return String.valueOf(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of calling {@code toString} on the first
|
||||
* argument if the first argument is not {@code null} and returns
|
||||
* the second argument otherwise.
|
||||
*
|
||||
* @param o an object
|
||||
* @param nullDefault string to return if the first argument is
|
||||
* {@code null}
|
||||
* @return the result of calling {@code toString} on the first
|
||||
* argument if it is not {@code null} and the second argument
|
||||
* otherwise.
|
||||
*/
|
||||
public static String toString(Object o, String nullDefault) {
|
||||
return (o != null) ? o.toString() : nullDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 0 if the arguments are identical and {@code
|
||||
* c.compare(a, b)} otherwise.
|
||||
* Consequently, if both arguments are {@code null} 0
|
||||
* is returned.
|
||||
*
|
||||
* <p>Note that if one of the arguments is {@code null}, a {@code
|
||||
* NullPointerException} may or may not be thrown depending on
|
||||
* what ordering policy, if any, the {@link Comparator Comparator}
|
||||
* chooses to have for {@code null} values.
|
||||
*
|
||||
* @param <T> the type of the objects being compared
|
||||
* @param a an object
|
||||
* @param b an object to be compared with {@code a}
|
||||
* @param c the {@code Comparator} to compare the first two arguments
|
||||
* @return 0 if the arguments are identical and {@code
|
||||
* c.compare(a, b)} otherwise.
|
||||
* @see Comparable
|
||||
* @see Comparator
|
||||
*/
|
||||
public static <T> int compare(T a, T b, Comparator<? super T> c) {
|
||||
return (a == b) ? 0 : c.compare(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the specified object reference is not {@code null}. This
|
||||
* method is designed primarily for doing parameter validation in methods
|
||||
* and constructors, as demonstrated below:
|
||||
* <blockquote><pre>
|
||||
* public Foo(Bar bar) {
|
||||
* this.bar = Objects.requireNonNull(bar);
|
||||
* }
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @param obj the object reference to check for nullity
|
||||
* @param <T> the type of the reference
|
||||
* @return {@code obj} if not {@code null}
|
||||
* @throws NullPointerException if {@code obj} is {@code null}
|
||||
*/
|
||||
public static <T> T requireNonNull(T obj) {
|
||||
if (obj == null)
|
||||
throw new NullPointerException();
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the specified object reference is not {@code null} and
|
||||
* throws a customized {@link NullPointerException} if it is. This method
|
||||
* is designed primarily for doing parameter validation in methods and
|
||||
* constructors with multiple parameters, as demonstrated below:
|
||||
* <blockquote><pre>
|
||||
* public Foo(Bar bar, Baz baz) {
|
||||
* this.bar = Objects.requireNonNull(bar, "bar must not be null");
|
||||
* this.baz = Objects.requireNonNull(baz, "baz must not be null");
|
||||
* }
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @param obj the object reference to check for nullity
|
||||
* @param message detail message to be used in the event that a {@code
|
||||
* NullPointerException} is thrown
|
||||
* @param <T> the type of the reference
|
||||
* @return {@code obj} if not {@code null}
|
||||
* @throws NullPointerException if {@code obj} is {@code null}
|
||||
*/
|
||||
public static <T> T requireNonNull(T obj, String message) {
|
||||
if (obj == null)
|
||||
throw new NullPointerException(message);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the provided reference is {@code null} otherwise
|
||||
* returns {@code false}.
|
||||
*
|
||||
* @apiNote This method exists to be used as a
|
||||
*
|
||||
* @param obj a reference to be checked against {@code null}
|
||||
* @return {@code true} if the provided reference is {@code null} otherwise
|
||||
* {@code false}
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public static boolean isNull(Object obj) {
|
||||
return obj == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the provided reference is non-{@code null}
|
||||
* otherwise returns {@code false}.
|
||||
*
|
||||
* @apiNote This method exists to be used as a
|
||||
*
|
||||
* @param obj a reference to be checked against {@code null}
|
||||
* @return {@code true} if the provided reference is non-{@code null}
|
||||
* otherwise {@code false}
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public static boolean nonNull(Object obj) {
|
||||
return obj != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first argument if it is non-{@code null} and
|
||||
* otherwise returns the non-{@code null} second argument.
|
||||
*
|
||||
* @param obj an object
|
||||
* @param defaultObj a non-{@code null} object to return if the first argument
|
||||
* is {@code null}
|
||||
* @param <T> the type of the reference
|
||||
* @return the first argument if it is non-{@code null} and
|
||||
* otherwise the second argument if it is non-{@code null}
|
||||
* @throws NullPointerException if both {@code obj} is null and
|
||||
* {@code defaultObj} is {@code null}
|
||||
* @since 9
|
||||
*/
|
||||
public static <T> T requireNonNullElse(T obj, T defaultObj) {
|
||||
return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj");
|
||||
}
|
||||
}
|
@ -16,7 +16,6 @@
|
||||
|
||||
package com.alibaba.nacos.common.utils;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -25,7 +24,7 @@ import java.util.Set;
|
||||
public class Observable {
|
||||
|
||||
private transient boolean changed = false;
|
||||
private transient Set<Observer> obs = new ConcurrentHashSet<>();
|
||||
private transient Set<Observer> obs = new ConcurrentHashSet<Observer>();
|
||||
private volatile int observerCnt = 0;
|
||||
private boolean alreadyAddObserver = false;
|
||||
|
||||
|
@ -28,7 +28,7 @@ public class Pair<A, B> {
|
||||
}
|
||||
|
||||
public static <A, B> Pair<A, B> with(A first, B second) {
|
||||
return new Pair<>(first, second);
|
||||
return new Pair<A, B>(first, second);
|
||||
}
|
||||
|
||||
public A getFirst() {
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.alibaba.nacos.common.utils;
|
||||
|
||||
import org.apache.commons.lang3.CharSequenceUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
@ -214,4 +216,89 @@ public class StringUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The following utility functions are extracted from <link>org.apache.commons.lang3</link>
|
||||
// start
|
||||
|
||||
/**
|
||||
* <p>Checks if CharSequence contains a search CharSequence irrespective of case,
|
||||
* handling {@code null}. Case-insensitivity is defined as by
|
||||
* {@link String#equalsIgnoreCase(String)}.
|
||||
*
|
||||
* <p>A {@code null} CharSequence will return {@code false}.</p>
|
||||
*
|
||||
* <pre>
|
||||
* StringUtils.contains(null, *) = false
|
||||
* StringUtils.contains(*, null) = false
|
||||
* StringUtils.contains("", "") = true
|
||||
* StringUtils.contains("abc", "") = true
|
||||
* StringUtils.contains("abc", "a") = true
|
||||
* StringUtils.contains("abc", "z") = false
|
||||
* StringUtils.contains("abc", "A") = true
|
||||
* StringUtils.contains("abc", "Z") = false
|
||||
* </pre>
|
||||
*
|
||||
* @param str the CharSequence to check, may be null
|
||||
* @param searchStr the CharSequence to find, may be null
|
||||
* @return true if the CharSequence contains the search CharSequence irrespective of
|
||||
* case or false if not or {@code null} string input
|
||||
* @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence)
|
||||
*/
|
||||
public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) {
|
||||
if (str == null || searchStr == null) {
|
||||
return false;
|
||||
}
|
||||
final int len = searchStr.length();
|
||||
final int max = str.length() - len;
|
||||
for (int i = 0; i <= max; i++) {
|
||||
if (regionMatches(str, true, i, searchStr, 0, len)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Green implementation of regionMatches.
|
||||
*
|
||||
* @param cs the {@code CharSequence} to be processed
|
||||
* @param ignoreCase whether or not to be case insensitive
|
||||
* @param thisStart the index to start on the {@code cs} CharSequence
|
||||
* @param substring the {@code CharSequence} to be looked for
|
||||
* @param start the index to start on the {@code substring} CharSequence
|
||||
* @param length character length of the region
|
||||
* @return whether the region matched
|
||||
*/
|
||||
static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart,
|
||||
final CharSequence substring, final int start, final int length) {
|
||||
if (cs instanceof String && substring instanceof String) {
|
||||
return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length);
|
||||
}
|
||||
int index1 = thisStart;
|
||||
int index2 = start;
|
||||
int tmpLen = length;
|
||||
|
||||
while (tmpLen-- > 0) {
|
||||
final char c1 = cs.charAt(index1++);
|
||||
final char c2 = substring.charAt(index2++);
|
||||
|
||||
if (c1 == c2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ignoreCase) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The same check as in String.regionMatches():
|
||||
if (Character.toUpperCase(c1) != Character.toUpperCase(c2)
|
||||
&& Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// end
|
||||
}
|
||||
|
@ -16,7 +16,11 @@
|
||||
|
||||
package com.alibaba.nacos.common.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -40,6 +44,11 @@ public final class ThreadUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void countDown(CountDownLatch latch) {
|
||||
Objects.requireNonNull(latch, "latch");
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
public static void latchAwait(CountDownLatch latch) {
|
||||
try {
|
||||
latch.await();
|
||||
@ -71,6 +80,31 @@ public final class ThreadUtils {
|
||||
return workerCount;
|
||||
}
|
||||
|
||||
public static void shutdownThreadPool(ExecutorService executor) {
|
||||
shutdownThreadPool(executor, null);
|
||||
}
|
||||
|
||||
public static void shutdownThreadPool(ExecutorService executor, Logger logger) {
|
||||
executor.shutdown();
|
||||
int retry = 3;
|
||||
while (retry > 0) {
|
||||
retry --;
|
||||
try {
|
||||
if (executor.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||
return;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
executor.shutdownNow();
|
||||
Thread.interrupted();
|
||||
} catch (Throwable ex) {
|
||||
if (logger != null) {
|
||||
logger.error("ThreadPoolManager shutdown executor has error : {}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
executor.shutdownNow();
|
||||
}
|
||||
|
||||
private final static int THREAD_MULTIPLER = 2;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
package com.alibaba.nacos.common.utils;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class MapUtilsTest {
|
||||
|
||||
@Test
|
||||
public void test_map() {
|
||||
Map<Object, Object> map = new HashMap<Object, Object>();
|
||||
|
||||
MapUtils.putIfValNoNull(map, "key-1", null);
|
||||
Assert.assertFalse(map.containsKey("key-1"));
|
||||
|
||||
MapUtils.putIfValNoEmpty(map, "key-str", null);
|
||||
Assert.assertFalse(map.containsKey("key-str"));
|
||||
|
||||
MapUtils.putIfValNoEmpty(map, "key-str", "");
|
||||
Assert.assertFalse(map.containsKey("key-str"));
|
||||
|
||||
MapUtils.putIfValNoEmpty(map, "key-str", "1");
|
||||
Assert.assertTrue(map.containsKey("key-str"));
|
||||
|
||||
MapUtils.putIfValNoEmpty(map, "key-list", null);
|
||||
Assert.assertFalse(map.containsKey("key-list"));
|
||||
|
||||
MapUtils.putIfValNoEmpty(map, "key-list", Collections.emptyList());
|
||||
Assert.assertFalse(map.containsKey("key-list"));
|
||||
|
||||
MapUtils.putIfValNoEmpty(map, "key-list", Collections.singletonList(1));
|
||||
Assert.assertTrue(map.containsKey("key-list"));
|
||||
|
||||
MapUtils.putIfValNoEmpty(map, "key-map", null);
|
||||
Assert.assertFalse(map.containsKey("key-map"));
|
||||
|
||||
MapUtils.putIfValNoEmpty(map, "key-map", Collections.emptyMap());
|
||||
Assert.assertFalse(map.containsKey("key-map"));
|
||||
|
||||
Map<String, String> map1 = new HashMap<String, String>();
|
||||
map1.put("1123", "123");
|
||||
|
||||
MapUtils.putIfValNoEmpty(map, "key-map", map1);
|
||||
Assert.assertTrue(map.containsKey("key-map"));
|
||||
}
|
||||
|
||||
}
|
@ -75,10 +75,6 @@
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-dbcp</groupId>
|
||||
<artifactId>commons-dbcp</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derby</artifactId>
|
||||
|
@ -18,7 +18,7 @@ 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.service.ConfigCacheService;
|
||||
import com.alibaba.nacos.config.server.utils.GroupKey2;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.RequestUtil;
|
||||
@ -88,7 +88,7 @@ public class RequestLogAspect {
|
||||
public Object interfaceGetConfig(ProceedingJoinPoint pjp, HttpServletRequest request, HttpServletResponse response,
|
||||
String dataId, String group, String tenant) throws Throwable {
|
||||
final String groupKey = GroupKey2.getKey(dataId, group, tenant);
|
||||
final String md5 = ConfigService.getContentMd5(groupKey);
|
||||
final String md5 = ConfigCacheService.getContentMd5(groupKey);
|
||||
MetricsMonitor.getConfigMonitor().incrementAndGet();
|
||||
return logClientRequest("get", pjp, request, response, dataId, group, tenant, md5);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.service.repository.EmbeddedStoragePersistServiceImpl;
|
||||
import com.alibaba.nacos.config.server.service.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.config.server.service.repository.DatabaseOperate;
|
||||
import com.alibaba.nacos.config.server.service.sql.SqlContextUtils;
|
||||
import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
@ -29,7 +29,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.PERMISSION_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.PERMISSION_ROW_MAPPER;
|
||||
|
||||
/**
|
||||
* There is no self-augmented primary key
|
||||
@ -73,14 +73,14 @@ public class EmbeddedPermissionPersistServiceImpl implements PermissionPersistSe
|
||||
|
||||
public void addPermission(String role, String resource, String action) {
|
||||
String sql = "INSERT into permissions (role, resource, action) VALUES (?, ?, ?)";
|
||||
SqlContextUtils.addSqlContext(sql, role, resource, action);
|
||||
databaseOperate.smartUpdate();
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, role, resource, action);
|
||||
databaseOperate.blockUpdate();
|
||||
}
|
||||
|
||||
public void deletePermission(String role, String resource, String action) {
|
||||
String sql = "DELETE from permissions WHERE role=? and resource=? and action=?";
|
||||
SqlContextUtils.addSqlContext(sql, role, resource, action);
|
||||
databaseOperate.smartUpdate();
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, role, resource, action);
|
||||
databaseOperate.blockUpdate();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.service.repository.EmbeddedStoragePersistServiceImpl;
|
||||
import com.alibaba.nacos.config.server.service.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.config.server.service.repository.DatabaseOperate;
|
||||
import com.alibaba.nacos.config.server.service.sql.SqlContextUtils;
|
||||
import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
@ -29,7 +29,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.ROLE_INFO_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.ROLE_INFO_ROW_MAPPER;
|
||||
|
||||
/**
|
||||
* There is no self-augmented primary key
|
||||
@ -93,30 +93,30 @@ public class EmbeddedRolePersistServiceImpl implements RolePersistService {
|
||||
String sql = "INSERT into roles (role, username) VALUES (?, ?)";
|
||||
|
||||
try {
|
||||
SqlContextUtils.addSqlContext(sql, role, userName);
|
||||
databaseOperate.update(SqlContextUtils.getCurrentSqlContext());
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, role, userName);
|
||||
databaseOperate.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
} finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteRole(String role) {
|
||||
String sql = "DELETE from roles WHERE role=?";
|
||||
try {
|
||||
SqlContextUtils.addSqlContext(sql, role);
|
||||
databaseOperate.update(SqlContextUtils.getCurrentSqlContext());
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, role);
|
||||
databaseOperate.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
} finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteRole(String role, String username) {
|
||||
String sql = "DELETE from roles WHERE role=? and username=?";
|
||||
try {
|
||||
SqlContextUtils.addSqlContext(sql, role, username);
|
||||
databaseOperate.update(SqlContextUtils.getCurrentSqlContext());
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, role, username);
|
||||
databaseOperate.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
} finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,14 +22,14 @@ import com.alibaba.nacos.config.server.model.User;
|
||||
import com.alibaba.nacos.config.server.service.repository.EmbeddedStoragePersistServiceImpl;
|
||||
import com.alibaba.nacos.config.server.service.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.config.server.service.repository.DatabaseOperate;
|
||||
import com.alibaba.nacos.config.server.service.sql.SqlContextUtils;
|
||||
import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.USER_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.USER_ROW_MAPPER;
|
||||
|
||||
/**
|
||||
* There is no self-augmented primary key
|
||||
@ -50,31 +50,31 @@ public class EmbeddedUserPersistServiceImpl implements UserPersistService {
|
||||
String sql = "INSERT into users (username, password, enabled) VALUES (?, ?, ?)";
|
||||
|
||||
try {
|
||||
SqlContextUtils.addSqlContext(sql, username, password, true);
|
||||
databaseOperate.smartUpdate();
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, username, password, true);
|
||||
databaseOperate.blockUpdate();
|
||||
} finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteUser(String username) {
|
||||
String sql = "DELETE from users WHERE username=?";
|
||||
try {
|
||||
SqlContextUtils.addSqlContext(sql, username);
|
||||
databaseOperate.smartUpdate();
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, username);
|
||||
databaseOperate.blockUpdate();
|
||||
} finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateUserPassword(String username, String password) {
|
||||
try {
|
||||
SqlContextUtils.addSqlContext(
|
||||
EmbeddedStorageContextUtils.addSqlContext(
|
||||
"UPDATE users SET password = ? WHERE username=?",
|
||||
password, username);
|
||||
databaseOperate.smartUpdate();
|
||||
databaseOperate.blockUpdate();
|
||||
} finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.auth;
|
||||
|
||||
import com.alibaba.nacos.config.server.configuration.ConditionOnEmbeddedStorage;
|
||||
import com.alibaba.nacos.config.server.configuration.ConditionOnExternalStorage;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.service.repository.ExternalStoragePersistServiceImpl;
|
||||
@ -24,7 +23,6 @@ import com.alibaba.nacos.config.server.service.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@ -33,7 +31,7 @@ import org.springframework.stereotype.Component;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.PERMISSION_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.PERMISSION_ROW_MAPPER;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
|
@ -23,7 +23,6 @@ import com.alibaba.nacos.config.server.service.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@ -35,7 +34,7 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.ROLE_INFO_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.ROLE_INFO_ROW_MAPPER;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
|
@ -23,7 +23,6 @@ import com.alibaba.nacos.config.server.service.repository.ExternalStoragePersist
|
||||
import com.alibaba.nacos.config.server.service.repository.PaginationHelper;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
||||
@ -33,7 +32,7 @@ import org.springframework.stereotype.Component;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.USER_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.USER_ROW_MAPPER;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.alibaba.nacos.config.server.constant;
|
||||
|
||||
import com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;
|
||||
|
||||
/**
|
||||
* Server Constants
|
||||
*
|
||||
@ -175,4 +177,19 @@ public class Constants {
|
||||
public static final int ATOMIC_MAX_SIZE = 1000;
|
||||
public static final String CONFIG_MODEL_RAFT_GROUP = "nacos_config";
|
||||
public static int DATA_IN_BODY_VERSION = 204;
|
||||
|
||||
/**
|
||||
* Configure the dump event name
|
||||
*/
|
||||
public static final String EXTEND_INFO_CONFIG_DUMP_EVENT = ConfigDumpEvent.class.getName();
|
||||
|
||||
/**
|
||||
* Configure the dump event-list name
|
||||
*/
|
||||
public static final String EXTEND_INFOS_CONFIG_DUMP_EVENT = ConfigDumpEvent.class.getName() + "@@many";
|
||||
|
||||
/**
|
||||
* Specifies that reads wait without timeout
|
||||
*/
|
||||
public static final String EXTEND_NEED_READ_UNTIL_HAVE_DATA = "00--0-read-join-0--00";
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ package com.alibaba.nacos.config.server.controller;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.utils.MapUtils;
|
||||
import com.alibaba.nacos.config.server.auth.ConfigResourceParser;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.controller.parameters.SameNamespaceCloneConfigBean;
|
||||
@ -32,10 +33,11 @@ import com.alibaba.nacos.config.server.model.SampleResult;
|
||||
import com.alibaba.nacos.config.server.result.ResultBuilder;
|
||||
import com.alibaba.nacos.config.server.result.code.ResultCodeEnum;
|
||||
import com.alibaba.nacos.config.server.service.AggrWhitelist;
|
||||
import com.alibaba.nacos.config.server.service.ConfigDataChangeEvent;
|
||||
import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;
|
||||
import com.alibaba.nacos.config.server.service.ConfigSubService;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.MD5Util;
|
||||
import com.alibaba.nacos.config.server.utils.ParamUtils;
|
||||
import com.alibaba.nacos.config.server.utils.RequestUtil;
|
||||
@ -45,6 +47,7 @@ import com.alibaba.nacos.config.server.utils.event.EventDispatcher;
|
||||
import com.alibaba.nacos.core.auth.ActionTypes;
|
||||
import com.alibaba.nacos.core.auth.Secured;
|
||||
import com.alibaba.nacos.core.utils.InetUtils;
|
||||
import com.alibaba.nacos.core.utils.WebUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
import org.slf4j.Logger;
|
||||
@ -61,6 +64,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
@ -76,6 +80,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -133,32 +138,20 @@ public class ConfigController {
|
||||
@RequestParam(value = "type", required = false) String type,
|
||||
@RequestParam(value = "schema", required = false) String schema)
|
||||
throws NacosException {
|
||||
|
||||
final String srcIp = RequestUtil.getRemoteIp(request);
|
||||
String requestIpApp = RequestUtil.getAppName(request);
|
||||
// check tenant
|
||||
ParamUtils.checkTenant(tenant);
|
||||
ParamUtils.checkParam(dataId, group, "datumId", content);
|
||||
ParamUtils.checkParam(tag);
|
||||
|
||||
Map<String, Object> configAdvanceInfo = new HashMap<String, Object>(10);
|
||||
if (configTags != null) {
|
||||
configAdvanceInfo.put("config_tags", configTags);
|
||||
}
|
||||
if (desc != null) {
|
||||
configAdvanceInfo.put("desc", desc);
|
||||
}
|
||||
if (use != null) {
|
||||
configAdvanceInfo.put("use", use);
|
||||
}
|
||||
if (effect != null) {
|
||||
configAdvanceInfo.put("effect", effect);
|
||||
}
|
||||
if (type != null) {
|
||||
configAdvanceInfo.put("type", type);
|
||||
}
|
||||
if (schema != null) {
|
||||
configAdvanceInfo.put("schema", schema);
|
||||
}
|
||||
MapUtils.putIfValNoNull(configAdvanceInfo, "config_tags", configTags);
|
||||
MapUtils.putIfValNoNull(configAdvanceInfo, "desc", desc);
|
||||
MapUtils.putIfValNoNull(configAdvanceInfo, "use", use);
|
||||
MapUtils.putIfValNoNull(configAdvanceInfo, "effect", effect);
|
||||
MapUtils.putIfValNoNull(configAdvanceInfo, "type", type);
|
||||
MapUtils.putIfValNoNull(configAdvanceInfo, "schema", schema);
|
||||
ParamUtils.checkParam(configAdvanceInfo);
|
||||
|
||||
if (AggrWhitelist.isAggrDataId(dataId)) {
|
||||
@ -171,33 +164,22 @@ public class ConfigController {
|
||||
final Timestamp time = TimeUtils.getCurrentTime();
|
||||
String betaIps = request.getHeader("betaIps");
|
||||
ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);
|
||||
configInfo.setType(type);
|
||||
if (StringUtils.isBlank(betaIps)) {
|
||||
if (StringUtils.isBlank(tag)) {
|
||||
persistService.insertOrUpdate(srcIp, srcUser, configInfo, time,
|
||||
configAdvanceInfo, false);
|
||||
EventDispatcher.fireEvent(
|
||||
new ConfigDataChangeEvent(false, dataId, group, tenant,
|
||||
time.getTime()));
|
||||
configAdvanceInfo, true);
|
||||
}
|
||||
else {
|
||||
persistService
|
||||
.insertOrUpdateTag(configInfo, tag, srcIp, srcUser, time, false);
|
||||
EventDispatcher.fireEvent(
|
||||
new ConfigDataChangeEvent(false, dataId, group, tenant, tag,
|
||||
time.getTime()));
|
||||
.insertOrUpdateTag(configInfo, tag, srcIp, srcUser, time, true);
|
||||
}
|
||||
}
|
||||
else { // beta publish
|
||||
else {
|
||||
// beta publish
|
||||
persistService
|
||||
.insertOrUpdateBeta(configInfo, betaIps, srcIp, srcUser, time, false);
|
||||
EventDispatcher.fireEvent(
|
||||
new ConfigDataChangeEvent(true, dataId, group, tenant,
|
||||
time.getTime()));
|
||||
.insertOrUpdateBeta(configInfo, betaIps, srcIp, srcUser, time, true);
|
||||
}
|
||||
ConfigTraceService
|
||||
.logPersistenceEvent(dataId, group, tenant, requestIpApp, time.getTime(),
|
||||
InetUtils.getSelfIp(), ConfigTraceService.PERSISTENCE_EVENT_PUB, content);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -275,9 +257,6 @@ public class ConfigController {
|
||||
ConfigTraceService
|
||||
.logPersistenceEvent(dataId, group, tenant, null, time.getTime(),
|
||||
clientIp, ConfigTraceService.PERSISTENCE_EVENT_REMOVE, null);
|
||||
EventDispatcher.fireEvent(
|
||||
new ConfigDataChangeEvent(false, dataId, group, tenant, tag,
|
||||
time.getTime()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -303,10 +282,6 @@ public class ConfigController {
|
||||
configInfo.getGroup(), configInfo.getTenant(), null,
|
||||
time.getTime(), clientIp,
|
||||
ConfigTraceService.PERSISTENCE_EVENT_REMOVE, null);
|
||||
EventDispatcher.fireEvent(
|
||||
new ConfigDataChangeEvent(false, configInfo.getDataId(),
|
||||
configInfo.getGroup(), configInfo.getTenant(),
|
||||
time.getTime()));
|
||||
}
|
||||
}
|
||||
return ResultBuilder.buildSuccessResult(true);
|
||||
@ -453,8 +428,6 @@ public class ConfigController {
|
||||
rr.setMessage("remove beta data error");
|
||||
return rr;
|
||||
}
|
||||
EventDispatcher.fireEvent(new ConfigDataChangeEvent(true, dataId, group, tenant,
|
||||
System.currentTimeMillis()));
|
||||
rr.setCode(200);
|
||||
rr.setData(true);
|
||||
rr.setMessage("stop beta ok");
|
||||
|
@ -18,8 +18,8 @@ package com.alibaba.nacos.config.server.controller;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.service.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.LocalDataSourceServiceImpl;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.datasource.LocalDataSourceServiceImpl;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.service.dump.DumpService;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
|
@ -18,8 +18,8 @@ package com.alibaba.nacos.config.server.controller;
|
||||
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.service.ConfigService;
|
||||
import com.alibaba.nacos.config.server.service.DiskUtil;
|
||||
import com.alibaba.nacos.config.server.service.ConfigCacheService;
|
||||
import com.alibaba.nacos.config.server.utils.DiskUtil;
|
||||
import com.alibaba.nacos.config.server.service.LongPollingService;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
|
||||
@ -60,7 +60,7 @@ public class ConfigServletInner {
|
||||
|
||||
private static final int TRY_GET_LOCK_TIMES = 9;
|
||||
|
||||
private static final int START_LONGPOLLING_VERSION_NUM = 204;
|
||||
private static final int START_LONG_POLLING_VERSION_NUM = 204;
|
||||
|
||||
/**
|
||||
* 轮询接口
|
||||
@ -91,7 +91,7 @@ public class ConfigServletInner {
|
||||
/**
|
||||
* 2.0.4版本以前, 返回值放入header中
|
||||
*/
|
||||
if (versionNum < START_LONGPOLLING_VERSION_NUM) {
|
||||
if (versionNum < START_LONG_POLLING_VERSION_NUM) {
|
||||
response.addHeader(Constants.PROBE_MODIFY_RESPONSE, oldResult);
|
||||
response.addHeader(Constants.PROBE_MODIFY_RESPONSE_NEW, newResult);
|
||||
} else {
|
||||
@ -125,7 +125,7 @@ public class ConfigServletInner {
|
||||
try {
|
||||
String md5 = Constants.NULL;
|
||||
long lastModified = 0L;
|
||||
CacheItem cacheItem = ConfigService.getContentCache(groupKey);
|
||||
CacheItem cacheItem = ConfigCacheService.getContentCache(groupKey);
|
||||
if (cacheItem != null) {
|
||||
if (cacheItem.isBeta()) {
|
||||
if (cacheItem.getIps4Beta().contains(clientIp)) {
|
||||
@ -288,7 +288,7 @@ public class ConfigServletInner {
|
||||
}
|
||||
|
||||
private static void releaseConfigReadLock(String groupKey) {
|
||||
ConfigService.releaseReadLock(groupKey);
|
||||
ConfigCacheService.releaseReadLock(groupKey);
|
||||
}
|
||||
|
||||
private static int tryConfigReadLock(String groupKey) {
|
||||
@ -300,7 +300,7 @@ public class ConfigServletInner {
|
||||
* 尝试加锁,最多10次
|
||||
*/
|
||||
for (int i = TRY_GET_LOCK_TIMES; i >= 0; --i) {
|
||||
lockResult = ConfigService.tryReadLock(groupKey);
|
||||
lockResult = ConfigCacheService.tryReadLock(groupKey);
|
||||
/**
|
||||
* 数据不存在
|
||||
*/
|
||||
|
@ -16,8 +16,8 @@
|
||||
package com.alibaba.nacos.config.server.controller;
|
||||
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.service.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.utils.InetUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -22,7 +22,9 @@ import com.alibaba.nacos.common.utils.Observer;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.model.event.RaftDBErrorEvent;
|
||||
import com.alibaba.nacos.config.server.model.event.RaftDBErrorRecoverEvent;
|
||||
import com.alibaba.nacos.config.server.service.repository.DerbyLoadEvent;
|
||||
import com.alibaba.nacos.consistency.cp.CPProtocol;
|
||||
import com.alibaba.nacos.consistency.cp.MetadataKey;
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.MemberMetaDataConstants;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
@ -115,7 +117,7 @@ public class CurcuitFilter implements Filter {
|
||||
|
||||
private void listenerSelfInCluster() {
|
||||
protocol.protocolMetaData().subscribe(Constants.CONFIG_MODEL_RAFT_GROUP,
|
||||
com.alibaba.nacos.consistency.cp.Constants.RAFT_GROUP_MEMBER,
|
||||
MetadataKey.RAFT_GROUP_MEMBER,
|
||||
new Observer() {
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
|
@ -1,19 +1,21 @@
|
||||
/*
|
||||
* 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
|
||||
* * 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.
|
||||
*
|
||||
* 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.service;
|
||||
package com.alibaba.nacos.config.server.model.event;
|
||||
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.Event;
|
||||
import org.apache.commons.lang3.StringUtils;
|
@ -0,0 +1,221 @@
|
||||
/*
|
||||
*
|
||||
* * 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.model.event;
|
||||
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class ConfigDumpEvent implements Event {
|
||||
|
||||
private static final long serialVersionUID = -8776888606458370294L;
|
||||
|
||||
private boolean remove;
|
||||
private String namespaceId;
|
||||
private String dataId;
|
||||
private String group;
|
||||
private boolean isBeta;
|
||||
private String tag;
|
||||
private String content;
|
||||
private String betaIps;
|
||||
private String handleIp;
|
||||
private String type;
|
||||
private long lastModifiedTs;
|
||||
|
||||
public boolean isRemove() {
|
||||
return remove;
|
||||
}
|
||||
|
||||
public void setRemove(boolean remove) {
|
||||
this.remove = remove;
|
||||
}
|
||||
|
||||
public String getNamespaceId() {
|
||||
return namespaceId;
|
||||
}
|
||||
|
||||
public void setNamespaceId(String namespaceId) {
|
||||
this.namespaceId = namespaceId;
|
||||
}
|
||||
|
||||
public String getDataId() {
|
||||
return dataId;
|
||||
}
|
||||
|
||||
public void setDataId(String dataId) {
|
||||
this.dataId = dataId;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public boolean isBeta() {
|
||||
return isBeta;
|
||||
}
|
||||
|
||||
public void setBeta(boolean beta) {
|
||||
isBeta = beta;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getBetaIps() {
|
||||
return betaIps;
|
||||
}
|
||||
|
||||
public void setBetaIps(String betaIps) {
|
||||
this.betaIps = betaIps;
|
||||
}
|
||||
|
||||
public String getHandleIp() {
|
||||
return handleIp;
|
||||
}
|
||||
|
||||
public void setHandleIp(String handleIp) {
|
||||
this.handleIp = handleIp;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public long getLastModifiedTs() {
|
||||
return lastModifiedTs;
|
||||
}
|
||||
|
||||
public void setLastModifiedTs(long lastModifiedTs) {
|
||||
this.lastModifiedTs = lastModifiedTs;
|
||||
}
|
||||
|
||||
public static ConfigDumpEventBuilder builder() {
|
||||
return new ConfigDumpEventBuilder();
|
||||
}
|
||||
|
||||
public static final class ConfigDumpEventBuilder {
|
||||
private boolean remove;
|
||||
private String namespaceId;
|
||||
private String dataId;
|
||||
private String group;
|
||||
private boolean isBeta;
|
||||
private String tag;
|
||||
private String content;
|
||||
private String betaIps;
|
||||
private String handleIp;
|
||||
private String type;
|
||||
private long lastModifiedTs;
|
||||
|
||||
private ConfigDumpEventBuilder() {
|
||||
}
|
||||
|
||||
public ConfigDumpEventBuilder remove(boolean remove) {
|
||||
this.remove = remove;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigDumpEventBuilder namespaceId(String namespaceId) {
|
||||
this.namespaceId = namespaceId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigDumpEventBuilder dataId(String dataId) {
|
||||
this.dataId = dataId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigDumpEventBuilder group(String group) {
|
||||
this.group = group;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigDumpEventBuilder isBeta(boolean isBeta) {
|
||||
this.isBeta = isBeta;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigDumpEventBuilder tag(String tag) {
|
||||
this.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigDumpEventBuilder content(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigDumpEventBuilder betaIps(String betaIps) {
|
||||
this.betaIps = betaIps;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigDumpEventBuilder handleIp(String handleIp) {
|
||||
this.handleIp = handleIp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigDumpEventBuilder type(String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigDumpEventBuilder lastModifiedTs(long lastModifiedTs) {
|
||||
this.lastModifiedTs = lastModifiedTs;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigDumpEvent build() {
|
||||
ConfigDumpEvent configDumpEvent = new ConfigDumpEvent();
|
||||
configDumpEvent.setRemove(remove);
|
||||
configDumpEvent.setNamespaceId(namespaceId);
|
||||
configDumpEvent.setDataId(dataId);
|
||||
configDumpEvent.setGroup(group);
|
||||
configDumpEvent.setTag(tag);
|
||||
configDumpEvent.setContent(content);
|
||||
configDumpEvent.setBetaIps(betaIps);
|
||||
configDumpEvent.setHandleIp(handleIp);
|
||||
configDumpEvent.setType(type);
|
||||
configDumpEvent.setLastModifiedTs(lastModifiedTs);
|
||||
configDumpEvent.isBeta = this.isBeta;
|
||||
return configDumpEvent;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +1,21 @@
|
||||
/*
|
||||
* 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
|
||||
* * 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.
|
||||
*
|
||||
* 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.service;
|
||||
package com.alibaba.nacos.config.server.model.event;
|
||||
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher.Event;
|
||||
|
@ -16,9 +16,9 @@
|
||||
package com.alibaba.nacos.config.server.monitor;
|
||||
|
||||
import com.alibaba.nacos.config.server.service.ClientTrackService;
|
||||
import com.alibaba.nacos.config.server.service.ConfigService;
|
||||
import com.alibaba.nacos.config.server.service.TimerTaskService;
|
||||
import com.alibaba.nacos.config.server.service.ConfigCacheService;
|
||||
import com.alibaba.nacos.config.server.service.notify.AsyncNotifyService;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -39,13 +39,13 @@ public class MemoryMonitor {
|
||||
@Autowired
|
||||
public MemoryMonitor(AsyncNotifyService notifySingleService) {
|
||||
|
||||
TimerTaskService.scheduleWithFixedDelay(new PrintMemoryTask(), DELAY_SECONDS,
|
||||
ConfigExecutor.scheduleWithFixedDelay(new PrintMemoryTask(), DELAY_SECONDS,
|
||||
DELAY_SECONDS, TimeUnit.SECONDS);
|
||||
|
||||
TimerTaskService.scheduleWithFixedDelay(new PrintGetConfigResponeTask(), DELAY_SECONDS,
|
||||
ConfigExecutor.scheduleWithFixedDelay(new PrintGetConfigResponeTask(), DELAY_SECONDS,
|
||||
DELAY_SECONDS, TimeUnit.SECONDS);
|
||||
|
||||
TimerTaskService.scheduleWithFixedDelay(new NotifyTaskQueueMonitorTask(notifySingleService), DELAY_SECONDS,
|
||||
ConfigExecutor.scheduleWithFixedDelay(new NotifyTaskQueueMonitorTask(notifySingleService), DELAY_SECONDS,
|
||||
DELAY_SECONDS, TimeUnit.SECONDS);
|
||||
|
||||
}
|
||||
@ -70,7 +70,7 @@ class PrintMemoryTask implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int groupCount = ConfigService.groupCount();
|
||||
int groupCount = ConfigCacheService.groupCount();
|
||||
int subClientCount = ClientTrackService.subscribeClientCount();
|
||||
long subCount = ClientTrackService.subscriberCount();
|
||||
memoryLog.info("groupCount={}, subscriberClientCount={}, subscriberCount={}", groupCount, subClientCount,
|
||||
|
@ -85,7 +85,7 @@ public class ClientTrackService {
|
||||
String groupKey = entry.getKey();
|
||||
String clientMd5 = entry.getValue();
|
||||
long lastPollingTs = record.groupKey2pollingTsMap.get(groupKey);
|
||||
boolean isUpdate = ConfigService.isUptodate(groupKey, clientMd5);
|
||||
boolean isUpdate = ConfigCacheService.isUptodate(groupKey, clientMd5);
|
||||
|
||||
status.put(groupKey, new SubscriberStatus(groupKey, isUpdate, clientMd5, lastPollingTs));
|
||||
}
|
||||
@ -104,7 +104,7 @@ public class ClientTrackService {
|
||||
Long lastPollingTs = clientRec.groupKey2pollingTsMap.get(groupKey);
|
||||
|
||||
if (null != clientMd5 && lastPollingTs != null) {
|
||||
Boolean isUpdate = ConfigService.isUptodate(groupKey, clientMd5);
|
||||
Boolean isUpdate = ConfigCacheService.isUptodate(groupKey, clientMd5);
|
||||
subs.put(clientRec.ip, new SubscriberStatus(groupKey, isUpdate, clientMd5, lastPollingTs));
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ public class ClientTrackService {
|
||||
for (Map.Entry<String, String> entry : getClientRecord(ip).groupKey2md5Map.entrySet()) {
|
||||
String groupKey = entry.getKey();
|
||||
String clientMd5 = entry.getValue();
|
||||
Boolean isuptodate = ConfigService.isUptodate(groupKey, clientMd5);
|
||||
Boolean isuptodate = ConfigCacheService.isUptodate(groupKey, clientMd5);
|
||||
result.put(groupKey, isuptodate);
|
||||
}
|
||||
return result;
|
||||
@ -135,7 +135,7 @@ public class ClientTrackService {
|
||||
for (ClientRecord clientRec : clientRecords.values()) {
|
||||
String clientMd5 = clientRec.groupKey2md5Map.get(groupKey);
|
||||
if (null != clientMd5) {
|
||||
Boolean isuptodate = ConfigService.isUptodate(groupKey, clientMd5);
|
||||
Boolean isuptodate = ConfigCacheService.isUptodate(groupKey, clientMd5);
|
||||
subs.put(clientRec.ip, isuptodate);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,9 @@ 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.model.event.LocalDataChangeEvent;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.utils.DiskUtil;
|
||||
import com.alibaba.nacos.config.server.utils.GroupKey;
|
||||
import com.alibaba.nacos.config.server.utils.GroupKey2;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
@ -41,7 +43,7 @@ import static com.alibaba.nacos.config.server.utils.LogUtil.*;
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class ConfigService {
|
||||
public class ConfigCacheService {
|
||||
|
||||
@Autowired
|
||||
private static PersistService persistService;
|
||||
@ -72,11 +74,11 @@ public class ConfigService {
|
||||
try {
|
||||
final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
|
||||
|
||||
if (md5.equals(ConfigService.getContentMd5(groupKey))) {
|
||||
if (md5.equals(ConfigCacheService.getContentMd5(groupKey))) {
|
||||
dumpLog.warn(
|
||||
"[dump-ignore] ignore to save cache file. groupKey={}, md5={}, lastModifiedOld={}, "
|
||||
+ "lastModifiedNew={}",
|
||||
groupKey, md5, ConfigService.getLastModifiedTs(groupKey), lastModifiedTs);
|
||||
groupKey, md5, ConfigCacheService.getLastModifiedTs(groupKey), lastModifiedTs);
|
||||
} else if (!PropertyUtil.isDirectRead()) {
|
||||
DiskUtil.saveToDisk(dataId, group, tenant, content);
|
||||
}
|
||||
@ -117,11 +119,11 @@ public class ConfigService {
|
||||
|
||||
try {
|
||||
final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
|
||||
if (md5.equals(ConfigService.getContentBetaMd5(groupKey))) {
|
||||
if (md5.equals(ConfigCacheService.getContentBetaMd5(groupKey))) {
|
||||
dumpLog.warn(
|
||||
"[dump-beta-ignore] ignore to save cache file. groupKey={}, md5={}, lastModifiedOld={}, "
|
||||
+ "lastModifiedNew={}",
|
||||
groupKey, md5, ConfigService.getLastModifiedTs(groupKey), lastModifiedTs);
|
||||
groupKey, md5, ConfigCacheService.getLastModifiedTs(groupKey), lastModifiedTs);
|
||||
} else if (!PropertyUtil.isDirectRead()) {
|
||||
DiskUtil.saveBetaToDisk(dataId, group, tenant, content);
|
||||
}
|
||||
@ -156,11 +158,11 @@ public class ConfigService {
|
||||
|
||||
try {
|
||||
final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
|
||||
if (md5.equals(ConfigService.getContentTagMd5(groupKey, tag))) {
|
||||
if (md5.equals(ConfigCacheService.getContentTagMd5(groupKey, tag))) {
|
||||
dumpLog.warn(
|
||||
"[dump-tag-ignore] ignore to save cache file. groupKey={}, md5={}, lastModifiedOld={}, "
|
||||
+ "lastModifiedNew={}",
|
||||
groupKey, md5, ConfigService.getLastModifiedTs(groupKey), lastModifiedTs);
|
||||
groupKey, md5, ConfigCacheService.getLastModifiedTs(groupKey), lastModifiedTs);
|
||||
} else if (!PropertyUtil.isDirectRead()) {
|
||||
DiskUtil.saveTagToDisk(dataId, group, tenant, tag, content);
|
||||
}
|
||||
@ -199,7 +201,7 @@ public class ConfigService {
|
||||
dumpLog.warn(
|
||||
"[dump-ignore] ignore to save cache file. groupKey={}, md5={}, lastModifiedOld={}, "
|
||||
+ "lastModifiedNew={}",
|
||||
groupKey, md5, ConfigService.getLastModifiedTs(groupKey), lastModifiedTs);
|
||||
groupKey, md5, ConfigCacheService.getLastModifiedTs(groupKey), lastModifiedTs);
|
||||
} else {
|
||||
DiskUtil.saveToDisk(dataId, group, tenant, content);
|
||||
}
|
||||
@ -517,12 +519,12 @@ public class ConfigService {
|
||||
}
|
||||
|
||||
static public boolean isUptodate(String groupKey, String md5) {
|
||||
String serverMd5 = ConfigService.getContentMd5(groupKey);
|
||||
String serverMd5 = ConfigCacheService.getContentMd5(groupKey);
|
||||
return StringUtils.equals(md5, serverMd5);
|
||||
}
|
||||
|
||||
static public boolean isUptodate(String groupKey, String md5, String ip, String tag) {
|
||||
String serverMd5 = ConfigService.getContentMd5(groupKey, ip, tag);
|
||||
String serverMd5 = ConfigCacheService.getContentMd5(groupKey, ip, tag);
|
||||
return StringUtils.equals(md5, serverMd5);
|
||||
}
|
||||
|
||||
@ -584,7 +586,7 @@ public class ConfigService {
|
||||
private final static String NO_SPACE_EN = "No space left on device";
|
||||
private final static String DISK_QUATA_CN = "超出磁盘限额";
|
||||
private final static String DISK_QUATA_EN = "Disk quota exceeded";
|
||||
static final Logger log = LoggerFactory.getLogger(ConfigService.class);
|
||||
static final Logger log = LoggerFactory.getLogger(ConfigCacheService.class);
|
||||
/**
|
||||
* groupKey -> cacheItem
|
||||
*/
|
@ -16,6 +16,7 @@
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.config.server.model.SampleResult;
|
||||
import com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;
|
||||
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.config.server.utils.GroupKey;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
@ -302,7 +303,7 @@ public class LongPollingService extends AbstractEventListener {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ConfigService.getContentBetaMd5(groupKey);
|
||||
ConfigCacheService.getContentBetaMd5(groupKey);
|
||||
for (Iterator<ClientLongPolling> iter = allSubs.iterator(); iter.hasNext(); ) {
|
||||
ClientLongPolling clientSub = iter.next();
|
||||
if (clientSub.clientMd5Map.containsKey(groupKey)) {
|
||||
|
@ -1,49 +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.service;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 定时任务服务
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class TimerTaskService {
|
||||
@SuppressWarnings("PMD.ThreadPoolCreationRule")
|
||||
private static ScheduledExecutorService scheduledExecutorService = Executors
|
||||
.newScheduledThreadPool(10, new ThreadFactory() {
|
||||
AtomicInteger count = new AtomicInteger(0);
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(r);
|
||||
t.setDaemon(true);
|
||||
t.setName("com.alibaba.nacos.server.Timer-" + count.getAndIncrement());
|
||||
return t;
|
||||
}
|
||||
});
|
||||
|
||||
static public void scheduleWithFixedDelay(Runnable command, long initialDelay, long delay,
|
||||
TimeUnit unit) {
|
||||
scheduledExecutorService.scheduleWithFixedDelay(command, initialDelay, delay, unit);
|
||||
}
|
||||
|
||||
}
|
@ -17,8 +17,8 @@ package com.alibaba.nacos.config.server.service.capacity;
|
||||
|
||||
import com.alibaba.nacos.config.server.model.capacity.Capacity;
|
||||
import com.alibaba.nacos.config.server.model.capacity.GroupCapacity;
|
||||
import com.alibaba.nacos.config.server.service.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.config.server.utils.TimeUtils;
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -16,8 +16,8 @@
|
||||
package com.alibaba.nacos.config.server.service.capacity;
|
||||
|
||||
import com.alibaba.nacos.config.server.model.capacity.TenantCapacity;
|
||||
import com.alibaba.nacos.config.server.service.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.config.server.utils.TimeUtils;
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -1,19 +1,21 @@
|
||||
/*
|
||||
* 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
|
||||
* * 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.
|
||||
*
|
||||
* 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.service;
|
||||
package com.alibaba.nacos.config.server.service.datasource;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
@ -1,19 +1,21 @@
|
||||
/*
|
||||
* 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
|
||||
* * 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.
|
||||
*
|
||||
* 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.service;
|
||||
package com.alibaba.nacos.config.server.service.datasource;
|
||||
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
|
||||
@ -48,7 +50,7 @@ public class DynamicDataSource {
|
||||
}
|
||||
else {
|
||||
if (basicDataSourceService == null) {
|
||||
basicDataSourceService = new BasicDataSourceServiceImpl();
|
||||
basicDataSourceService = new ExternalDataSourceServiceImpl();
|
||||
basicDataSourceService.init();
|
||||
}
|
||||
return basicDataSourceService;
|
@ -1,26 +1,29 @@
|
||||
/*
|
||||
* 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
|
||||
* * 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.
|
||||
*
|
||||
* 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.service;
|
||||
package com.alibaba.nacos.config.server.service.datasource;
|
||||
|
||||
import com.alibaba.nacos.common.utils.ConvertUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import org.apache.commons.dbcp.BasicDataSource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
@ -38,7 +41,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_INFO4BETA_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO4BETA_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.utils.LogUtil.defaultLog;
|
||||
import static com.alibaba.nacos.config.server.utils.LogUtil.fatalLog;
|
||||
|
||||
@ -47,9 +50,10 @@ import static com.alibaba.nacos.config.server.utils.LogUtil.fatalLog;
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
public class ExternalDataSourceServiceImpl implements DataSourceService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BasicDataSourceServiceImpl.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(
|
||||
ExternalDataSourceServiceImpl.class);
|
||||
private static final String DEFAULT_MYSQL_DRIVER = "com.mysql.jdbc.Driver";
|
||||
private static final String MYSQL_HIGH_LEVEL_DRIVER = "com.mysql.cj.jdbc.Driver";
|
||||
private static String JDBC_DRIVER_NAME;
|
||||
@ -63,7 +67,7 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
|
||||
private static final String DB_LOAD_ERROR_MSG = "[db-load-error]load jdbc.properties error";
|
||||
|
||||
private List<BasicDataSource> dataSourceList = new ArrayList<BasicDataSource>();
|
||||
private List<HikariDataSource> dataSourceList = new ArrayList<>();
|
||||
private JdbcTemplate jt;
|
||||
private DataSourceTransactionManager tm;
|
||||
private TransactionTemplate tjt;
|
||||
@ -89,7 +93,7 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
queryTimeout = NumberUtils.toInt(System.getProperty("QUERYTIMEOUT"), 3);
|
||||
queryTimeout = ConvertUtils.toInt(System.getProperty("QUERYTIMEOUT"), 3);
|
||||
jt = new JdbcTemplate();
|
||||
/**
|
||||
* 设置最大记录数,防止内存膨胀
|
||||
@ -125,16 +129,16 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
throw new RuntimeException(DB_LOAD_ERROR_MSG);
|
||||
}
|
||||
|
||||
TimerTaskService.scheduleWithFixedDelay(new SelectMasterTask(), 10, 10,
|
||||
ConfigExecutor.scheduleWithFixedDelay(new SelectMasterTask(), 10, 10,
|
||||
TimeUnit.SECONDS);
|
||||
TimerTaskService.scheduleWithFixedDelay(new CheckDBHealthTask(), 10, 10,
|
||||
ConfigExecutor.scheduleWithFixedDelay(new CheckDBHealthTask(), 10, 10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void reload() throws IOException {
|
||||
List<BasicDataSource> dblist = new ArrayList<BasicDataSource>();
|
||||
List<HikariDataSource> dblist = new ArrayList<>();
|
||||
try {
|
||||
String val = null;
|
||||
val = ApplicationUtils.getProperty("db.num");
|
||||
@ -144,7 +148,7 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
int dbNum = Integer.parseInt(val.trim());
|
||||
|
||||
for (int i = 0; i < dbNum; i++) {
|
||||
BasicDataSource ds = new BasicDataSource();
|
||||
HikariDataSource ds = new HikariDataSource();
|
||||
ds.setDriverClassName(JDBC_DRIVER_NAME);
|
||||
|
||||
val = ApplicationUtils.getProperty("db.url." + i);
|
||||
@ -152,7 +156,7 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
fatalLog.error("db.url." + i + " is null");
|
||||
throw new IllegalArgumentException("db.url." + i + " is null");
|
||||
}
|
||||
ds.setUrl(val.trim());
|
||||
ds.setJdbcUrl(val.trim());
|
||||
|
||||
val = ApplicationUtils.getProperty("db.user." + i, ApplicationUtils.getProperty("db.user"));
|
||||
if (null == val) {
|
||||
@ -168,23 +172,17 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
}
|
||||
ds.setPassword(val.trim());
|
||||
|
||||
val = ApplicationUtils.getProperty("db.initialSize." + i, ApplicationUtils.getProperty("db.initialSize"));
|
||||
ds.setInitialSize(Integer.parseInt(defaultIfNull(val, "10")));
|
||||
val = ApplicationUtils.getProperty("db.maxPoolSize." + i, ApplicationUtils.getProperty("db.maxPoolSize"));
|
||||
ds.setMaximumPoolSize(Integer.parseInt(defaultIfNull(val, "20")));
|
||||
|
||||
val = ApplicationUtils.getProperty("db.maxActive." + i, ApplicationUtils.getProperty("db.maxActive"));
|
||||
ds.setMaxActive(Integer.parseInt(defaultIfNull(val, "20")));
|
||||
val = ApplicationUtils.getProperty("db.minIdle." + i, ApplicationUtils.getProperty("db.minIdle"));
|
||||
ds.setMinimumIdle(Integer.parseInt(defaultIfNull(val, "50")));
|
||||
|
||||
val = ApplicationUtils.getProperty("db.maxIdle." + i, ApplicationUtils.getProperty("db.maxIdle"));
|
||||
ds.setMaxIdle(Integer.parseInt(defaultIfNull(val, "50")));
|
||||
|
||||
ds.setMaxWait(3000L);
|
||||
ds.setPoolPreparedStatements(true);
|
||||
ds.setConnectionTimeout(3000L);
|
||||
|
||||
// 每10分钟检查一遍连接池
|
||||
ds.setTimeBetweenEvictionRunsMillis(TimeUnit.MINUTES
|
||||
.toMillis(10L));
|
||||
ds.setTestWhileIdle(true);
|
||||
ds.setValidationQuery("SELECT 1 FROM dual");
|
||||
ds.setValidationTimeout(TimeUnit.MINUTES.toMillis(10L));
|
||||
ds.setConnectionTestQuery("SELECT 1 FROM dual");
|
||||
|
||||
dblist.add(ds);
|
||||
|
||||
@ -250,8 +248,8 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
if (ds == null) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
BasicDataSource bds = (BasicDataSource) ds;
|
||||
return bds.getUrl();
|
||||
HikariDataSource bds = (HikariDataSource) ds;
|
||||
return bds.getJdbcUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -262,12 +260,12 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
/**
|
||||
* 主库不健康
|
||||
*/
|
||||
return "DOWN:" + getIpFromUrl(dataSourceList.get(i).getUrl());
|
||||
return "DOWN:" + getIpFromUrl(dataSourceList.get(i).getJdbcUrl());
|
||||
} else {
|
||||
/**
|
||||
* 从库不健康
|
||||
*/
|
||||
return "WARN:" + getIpFromUrl(dataSourceList.get(i).getUrl());
|
||||
return "WARN:" + getIpFromUrl(dataSourceList.get(i).getJdbcUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -299,7 +297,7 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
boolean isFound = false;
|
||||
|
||||
int index = -1;
|
||||
for (BasicDataSource ds : dataSourceList) {
|
||||
for (HikariDataSource ds : dataSourceList) {
|
||||
index++;
|
||||
testMasterJT.setDataSource(ds);
|
||||
testMasterJT.setQueryTimeout(queryTimeout);
|
||||
@ -308,7 +306,7 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
.update(
|
||||
"DELETE FROM config_info WHERE data_id='com.alibaba.nacos.testMasterDB'");
|
||||
if (jt.getDataSource() != ds) {
|
||||
fatalLog.warn("[master-db] {}", ds.getUrl());
|
||||
fatalLog.warn("[master-db] {}", ds.getJdbcUrl());
|
||||
}
|
||||
jt.setDataSource(ds);
|
||||
tm.setDataSource(ds);
|
||||
@ -345,10 +343,10 @@ public class BasicDataSourceServiceImpl implements DataSourceService {
|
||||
} catch (DataAccessException e) {
|
||||
if (i == masterIndex) {
|
||||
fatalLog.error("[db-error] master db {} down.",
|
||||
getIpFromUrl(dataSourceList.get(i).getUrl()));
|
||||
getIpFromUrl(dataSourceList.get(i).getJdbcUrl()));
|
||||
} else {
|
||||
fatalLog.error("[db-error] slave db {} down.",
|
||||
getIpFromUrl(dataSourceList.get(i).getUrl()));
|
||||
getIpFromUrl(dataSourceList.get(i).getJdbcUrl()));
|
||||
}
|
||||
isHealthList.set(i, Boolean.FALSE);
|
||||
|
@ -1,24 +1,28 @@
|
||||
/*
|
||||
* 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
|
||||
* * 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.
|
||||
*
|
||||
* 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.service;
|
||||
package com.alibaba.nacos.config.server.service.datasource;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.common.utils.DiskUtils;
|
||||
import com.alibaba.nacos.core.utils.DiskUtils;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import java.io.File;
|
||||
@ -87,7 +91,7 @@ public class LocalDataSourceServiceImpl implements DataSourceService {
|
||||
if (LogUtil.defaultLog.isErrorEnabled()) {
|
||||
LogUtil.defaultLog.error(e.getMessage(), e);
|
||||
}
|
||||
throw new RuntimeException("load schema.sql error.", e);
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, "load schema.sql error.", e);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
*
|
||||
* * 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.service.dump;
|
||||
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;
|
||||
import com.alibaba.nacos.config.server.service.AggrWhitelist;
|
||||
import com.alibaba.nacos.config.server.service.ClientIpWhiteList;
|
||||
import com.alibaba.nacos.config.server.service.ConfigCacheService;
|
||||
import com.alibaba.nacos.config.server.service.SwitchService;
|
||||
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class DumpConfigHandler implements Subscribe<ConfigDumpEvent> {
|
||||
|
||||
public static boolean configDump(ConfigDumpEvent event) {
|
||||
final String dataId = event.getDataId();
|
||||
final String group = event.getGroup();
|
||||
final String namespaceId = event.getNamespaceId();
|
||||
final String content = event.getContent();
|
||||
final String type = event.getType();
|
||||
final long lastModified = event.getLastModifiedTs();
|
||||
if (event.isBeta()) {
|
||||
boolean result = false;
|
||||
if (event.isRemove()) {
|
||||
result = ConfigCacheService.removeBeta(dataId, group, namespaceId);
|
||||
if (result) {
|
||||
ConfigTraceService
|
||||
.logDumpEvent(dataId, group, namespaceId, null, lastModified,
|
||||
event.getHandleIp(),
|
||||
ConfigTraceService.DUMP_EVENT_REMOVE_OK,
|
||||
System.currentTimeMillis() - lastModified, 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
result = ConfigCacheService
|
||||
.dumpBeta(dataId, group, namespaceId, content, lastModified,
|
||||
event.getBetaIps());
|
||||
if (result) {
|
||||
ConfigTraceService
|
||||
.logDumpEvent(dataId, group, namespaceId, null, lastModified,
|
||||
event.getHandleIp(), ConfigTraceService.DUMP_EVENT_OK,
|
||||
System.currentTimeMillis() - lastModified,
|
||||
content.length());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
if (StringUtils.isBlank(event.getTag())) {
|
||||
if (dataId.equals(AggrWhitelist.AGGRIDS_METADATA)) {
|
||||
AggrWhitelist.load(content);
|
||||
}
|
||||
|
||||
if (dataId.equals(ClientIpWhiteList.CLIENT_IP_WHITELIST_METADATA)) {
|
||||
ClientIpWhiteList.load(content);
|
||||
}
|
||||
|
||||
if (dataId.equals(SwitchService.SWITCH_META_DATAID)) {
|
||||
SwitchService.load(content);
|
||||
}
|
||||
|
||||
boolean result;
|
||||
if (!event.isRemove()) {
|
||||
result = ConfigCacheService
|
||||
.dump(dataId, group, namespaceId, content, lastModified, type);
|
||||
|
||||
if (result) {
|
||||
ConfigTraceService
|
||||
.logDumpEvent(dataId, group, namespaceId, null, lastModified,
|
||||
event.getHandleIp(), ConfigTraceService.DUMP_EVENT_OK,
|
||||
System.currentTimeMillis() - lastModified,
|
||||
content.length());
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = ConfigCacheService.remove(dataId, group, namespaceId);
|
||||
|
||||
if (result) {
|
||||
ConfigTraceService
|
||||
.logDumpEvent(dataId, group, namespaceId, null, lastModified,
|
||||
event.getHandleIp(),
|
||||
ConfigTraceService.DUMP_EVENT_REMOVE_OK,
|
||||
System.currentTimeMillis() - lastModified, 0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
//
|
||||
boolean result;
|
||||
if (!event.isRemove()) {
|
||||
result = ConfigCacheService
|
||||
.dumpTag(dataId, group, namespaceId, event.getTag(), content,
|
||||
lastModified);
|
||||
if (result) {
|
||||
ConfigTraceService
|
||||
.logDumpEvent(dataId, group, namespaceId, null, lastModified,
|
||||
event.getHandleIp(), ConfigTraceService.DUMP_EVENT_OK,
|
||||
System.currentTimeMillis() - lastModified,
|
||||
content.length());
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = ConfigCacheService
|
||||
.removeTag(dataId, group, namespaceId, event.getTag());
|
||||
if (result) {
|
||||
ConfigTraceService
|
||||
.logDumpEvent(dataId, group, namespaceId, null, lastModified,
|
||||
event.getHandleIp(),
|
||||
ConfigTraceService.DUMP_EVENT_REMOVE_OK,
|
||||
System.currentTimeMillis() - lastModified, 0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(ConfigDumpEvent event) {
|
||||
configDump(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Event> subscribeType() {
|
||||
return ConfigDumpEvent.class;
|
||||
}
|
||||
}
|
@ -15,11 +15,10 @@
|
||||
*/
|
||||
package com.alibaba.nacos.config.server.service.dump;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.common.utils.Observable;
|
||||
import com.alibaba.nacos.common.utils.Observer;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.manager.TaskManager;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfo;
|
||||
@ -27,32 +26,24 @@ import com.alibaba.nacos.config.server.model.ConfigInfoAggr;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfoChanged;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfoWrapper;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.service.ConfigService;
|
||||
import com.alibaba.nacos.config.server.service.DiskUtil;
|
||||
import com.alibaba.nacos.config.server.service.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.TimerTaskService;
|
||||
import com.alibaba.nacos.config.server.service.ConfigCacheService;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.merge.MergeTaskProcessor;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
import com.alibaba.nacos.config.server.utils.ContentUtils;
|
||||
import com.alibaba.nacos.config.server.utils.DiskUtil;
|
||||
import com.alibaba.nacos.config.server.utils.GroupKey;
|
||||
import com.alibaba.nacos.config.server.utils.GroupKey2;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.config.server.utils.TimeUtils;
|
||||
import com.alibaba.nacos.consistency.cp.CPProtocol;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.distributed.ProtocolManager;
|
||||
import com.alibaba.nacos.core.distributed.raft.exception.NoSuchRaftGroupException;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.GlobalExecutor;
|
||||
import com.alibaba.nacos.core.utils.InetUtils;
|
||||
import com.alibaba.nacos.core.utils.TimerContext;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@ -61,12 +52,9 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static com.alibaba.nacos.config.server.utils.LogUtil.fatalLog;
|
||||
|
||||
@ -75,12 +63,16 @@ import static com.alibaba.nacos.config.server.utils.LogUtil.fatalLog;
|
||||
*
|
||||
* @author Nacos
|
||||
*/
|
||||
@Service
|
||||
public class DumpService {
|
||||
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
|
||||
public abstract class DumpService {
|
||||
|
||||
private final PersistService persistService;
|
||||
private final ServerMemberManager memberManager;
|
||||
private final ProtocolManager protocolManager;
|
||||
protected DumpProcessor processor;
|
||||
protected DumpAllProcessor dumpAllProcessor;
|
||||
protected DumpAllBetaProcessor dumpAllBetaProcessor;
|
||||
protected DumpAllTagProcessor dumpAllTagProcessor;
|
||||
|
||||
protected final PersistService persistService;
|
||||
protected final ServerMemberManager memberManager;
|
||||
|
||||
/**
|
||||
* Here you inject the dependent objects constructively, ensuring that some
|
||||
@ -88,13 +80,20 @@ public class DumpService {
|
||||
*
|
||||
* @param persistService {@link PersistService}
|
||||
* @param memberManager {@link ServerMemberManager}
|
||||
* @param protocolManager {@link ProtocolManager}
|
||||
*/
|
||||
public DumpService(PersistService persistService, ServerMemberManager memberManager,
|
||||
ProtocolManager protocolManager) {
|
||||
public DumpService(PersistService persistService, ServerMemberManager memberManager) {
|
||||
this.persistService = persistService;
|
||||
this.memberManager = memberManager;
|
||||
this.protocolManager = protocolManager;
|
||||
this.processor = new DumpProcessor(this);
|
||||
this.dumpAllProcessor = new DumpAllProcessor(this);
|
||||
this.dumpAllBetaProcessor = new DumpAllBetaProcessor(this);
|
||||
this.dumpAllTagProcessor = new DumpAllTagProcessor(this);
|
||||
this.dumpTaskMgr = new TaskManager("com.alibaba.nacos.server.DumpTaskManager");
|
||||
this.dumpTaskMgr.setDefaultTaskProcessor(processor);
|
||||
|
||||
this.dumpAllTaskMgr = new TaskManager("com.alibaba.nacos.server.DumpAllTaskManager");
|
||||
this.dumpAllTaskMgr.setDefaultTaskProcessor(dumpAllProcessor);
|
||||
DynamicDataSource.getInstance().getDataSource();
|
||||
}
|
||||
|
||||
public PersistService getPersistService() {
|
||||
@ -105,88 +104,17 @@ public class DumpService {
|
||||
return memberManager;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
protected void init() throws Throwable {
|
||||
DynamicDataSource.getInstance().getDataSource();
|
||||
/**
|
||||
* initialize
|
||||
*
|
||||
* @throws Throwable
|
||||
*/
|
||||
protected abstract void init() throws Throwable;
|
||||
|
||||
DumpProcessor processor = new DumpProcessor(this);
|
||||
DumpAllProcessor dumpAllProcessor = new DumpAllProcessor(this);
|
||||
DumpAllBetaProcessor dumpAllBetaProcessor = new DumpAllBetaProcessor(this);
|
||||
DumpAllTagProcessor dumpAllTagProcessor = new DumpAllTagProcessor(this);
|
||||
|
||||
dumpTaskMgr = new TaskManager("com.alibaba.nacos.server.DumpTaskManager");
|
||||
dumpTaskMgr.setDefaultTaskProcessor(processor);
|
||||
|
||||
dumpAllTaskMgr = new TaskManager("com.alibaba.nacos.server.DumpAllTaskManager");
|
||||
dumpAllTaskMgr.setDefaultTaskProcessor(dumpAllProcessor);
|
||||
|
||||
// If using embedded distributed storage, you need to wait for the
|
||||
// underlying master to complete the selection
|
||||
if (PropertyUtil.isEmbeddedStorage() && !ApplicationUtils.getStandaloneMode()) {
|
||||
|
||||
CPProtocol protocol = protocolManager.getCpProtocol();
|
||||
|
||||
LogUtil.dumpLog
|
||||
.info("With embedded distributed storage, you need to wait for "
|
||||
+ "the underlying master to complete before you can perform the dump operation.");
|
||||
|
||||
AtomicReference<Throwable> errorReference = new AtomicReference<>(null);
|
||||
CountDownLatch waitDumpFinish = new CountDownLatch(1);
|
||||
|
||||
// watch path => /nacos_config/leader/ has value ?
|
||||
Observer observer = new Observer() {
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
GlobalExecutor.executeByCommon(() -> {
|
||||
// must make sure that there is a value here to perform the correct operation that follows
|
||||
if (Objects.isNull(arg)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
dumpOperate(processor, dumpAllProcessor, dumpAllBetaProcessor,
|
||||
dumpAllTagProcessor);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
errorReference.set(ex);
|
||||
}
|
||||
finally {
|
||||
waitDumpFinish.countDown();
|
||||
}
|
||||
protocol.protocolMetaData()
|
||||
.unSubscribe(Constants.CONFIG_MODEL_RAFT_GROUP,
|
||||
com.alibaba.nacos.consistency.cp.Constants.LEADER_META_DATA,
|
||||
this);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
protocol.protocolMetaData().subscribe(Constants.CONFIG_MODEL_RAFT_GROUP,
|
||||
com.alibaba.nacos.consistency.cp.Constants.LEADER_META_DATA,
|
||||
observer);
|
||||
|
||||
// We must wait for the dump task to complete the callback operation before
|
||||
// continuing with the initialization
|
||||
ThreadUtils.latchAwait(waitDumpFinish);
|
||||
|
||||
// If an exception occurs during the execution of the dump task, the exception
|
||||
// needs to be thrown, triggering the node to start the failed process
|
||||
final Throwable ex = errorReference.get();
|
||||
if (Objects.nonNull(ex)) {
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
dumpOperate(processor, dumpAllProcessor, dumpAllBetaProcessor,
|
||||
dumpAllTagProcessor);
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpOperate(DumpProcessor processor, DumpAllProcessor dumpAllProcessor,
|
||||
protected void dumpOperate(DumpProcessor processor, DumpAllProcessor dumpAllProcessor,
|
||||
DumpAllBetaProcessor dumpAllBetaProcessor,
|
||||
DumpAllTagProcessor dumpAllTagProcessor) {
|
||||
TimerContext.start("config dump job");
|
||||
DumpAllTagProcessor dumpAllTagProcessor) throws NacosException {
|
||||
TimerContext.start("CONFIG_DUMP_TO_FILE");
|
||||
try {
|
||||
LogUtil.defaultLog.warn("DumpService start");
|
||||
|
||||
@ -218,7 +146,7 @@ public class DumpService {
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
log.error("clearConfigHistory error", e);
|
||||
log.error("clearConfigHistory error : {}", e.toString());
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -257,10 +185,10 @@ public class DumpService {
|
||||
catch (Exception e) {
|
||||
LogUtil.fatalLog
|
||||
.error("Nacos Server did not start because dumpservice bean construction failure :\n"
|
||||
+ e.getMessage(), e.getCause());
|
||||
throw new RuntimeException(
|
||||
+ e.toString());
|
||||
throw new NacosException(NacosException.SERVER_ERROR,
|
||||
"Nacos Server did not start because dumpservice bean construction failure :\n"
|
||||
+ e.getMessage());
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
if (!ApplicationUtils.getStandaloneMode()) {
|
||||
Runnable heartbeat = () -> {
|
||||
@ -274,20 +202,20 @@ public class DumpService {
|
||||
}
|
||||
};
|
||||
|
||||
TimerTaskService
|
||||
ConfigExecutor
|
||||
.scheduleWithFixedDelay(heartbeat, 0, 10, TimeUnit.SECONDS);
|
||||
|
||||
long initialDelay = new Random().nextInt(INITIAL_DELAY_IN_MINUTE) + 10;
|
||||
LogUtil.defaultLog.warn("initialDelay:{}", initialDelay);
|
||||
|
||||
TimerTaskService.scheduleWithFixedDelay(dumpAll, initialDelay,
|
||||
ConfigExecutor.scheduleWithFixedDelay(dumpAll, initialDelay,
|
||||
DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
|
||||
|
||||
TimerTaskService.scheduleWithFixedDelay(dumpAllBeta, initialDelay,
|
||||
ConfigExecutor.scheduleWithFixedDelay(dumpAllBeta, initialDelay,
|
||||
DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
TimerTaskService
|
||||
ConfigExecutor
|
||||
.scheduleWithFixedDelay(clearConfigHistory, 10, 10, TimeUnit.MINUTES);
|
||||
}
|
||||
finally {
|
||||
@ -327,7 +255,7 @@ public class DumpService {
|
||||
dumpChangeProcessor.process(DumpChangeTask.TASK_ID, new DumpChangeTask());
|
||||
Runnable checkMd5Task = () -> {
|
||||
LogUtil.defaultLog.error("start checkMd5Task");
|
||||
List<String> diffList = ConfigService.checkMd5();
|
||||
List<String> diffList = ConfigCacheService.checkMd5();
|
||||
for (String groupKey : diffList) {
|
||||
String[] dg = GroupKey.parseKey(groupKey);
|
||||
String dataId = dg[0];
|
||||
@ -335,12 +263,12 @@ public class DumpService {
|
||||
String tenant = dg[2];
|
||||
ConfigInfoWrapper configInfo = persistService
|
||||
.queryConfigInfo(dataId, group, tenant);
|
||||
ConfigService.dumpChange(dataId, group, tenant,
|
||||
ConfigCacheService.dumpChange(dataId, group, tenant,
|
||||
configInfo.getContent(), configInfo.getLastModified());
|
||||
}
|
||||
LogUtil.defaultLog.error("end checkMd5Task");
|
||||
};
|
||||
TimerTaskService
|
||||
ConfigExecutor
|
||||
.scheduleWithFixedDelay(checkMd5Task, 0, 12, TimeUnit.HOURS);
|
||||
}
|
||||
}
|
||||
@ -492,7 +420,7 @@ public class DumpService {
|
||||
ConfigInfo cf = MergeTaskProcessor
|
||||
.merge(dataId, group, tenant, datumList);
|
||||
String aggrContent = cf.getContent();
|
||||
String localContentMD5 = ConfigService
|
||||
String localContentMD5 = ConfigCacheService
|
||||
.getContentMd5(GroupKey.getKey(dataId, group));
|
||||
String aggrConetentMD5 = MD5Utils
|
||||
.md5Hex(aggrContent, Constants.ENCODE);
|
||||
@ -530,25 +458,12 @@ public class DumpService {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canExecute() {
|
||||
try {
|
||||
CPProtocol protocol = protocolManager.getCpProtocol();
|
||||
// if is derby + raft mode, only leader can execute
|
||||
if (PropertyUtil.isEmbeddedStorage() && !ApplicationUtils
|
||||
.getStandaloneMode()) {
|
||||
return protocol.isLeader(Constants.CONFIG_MODEL_RAFT_GROUP);
|
||||
}
|
||||
// If it is external storage, it determines whether it is the first node of the cluster
|
||||
return memberManager.isFirstIp();
|
||||
}
|
||||
catch (NoSuchRaftGroupException e) {
|
||||
return true;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
// It's impossible to get to this point
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Used to determine whether the aggregation task, configuration history cleanup task can be performed
|
||||
*
|
||||
* @return {@link Boolean}
|
||||
*/
|
||||
protected abstract boolean canExecute();
|
||||
|
||||
/**
|
||||
* 全量dump间隔
|
||||
|
@ -26,15 +26,16 @@ import com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfoWrapper;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;
|
||||
import com.alibaba.nacos.config.server.service.*;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
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 org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.alibaba.nacos.config.server.utils.LogUtil.defaultLog;
|
||||
|
||||
@ -142,89 +143,42 @@ class DumpProcessor implements TaskProcessor {
|
||||
String handleIp = dumpTask.handleIp;
|
||||
boolean isBeta = dumpTask.isBeta;
|
||||
String tag = dumpTask.tag;
|
||||
|
||||
ConfigDumpEvent.ConfigDumpEventBuilder build = ConfigDumpEvent.builder()
|
||||
.namespaceId(tenant)
|
||||
.dataId(dataId)
|
||||
.group(group)
|
||||
.isBeta(isBeta)
|
||||
.tag(tag)
|
||||
.lastModifiedTs(lastModified)
|
||||
.handleIp(handleIp);
|
||||
|
||||
if (isBeta) {
|
||||
// beta发布,则dump数据,更新beta缓存
|
||||
ConfigInfo4Beta cf = persistService.findConfigInfo4Beta(dataId, group, tenant);
|
||||
boolean result;
|
||||
if (null != cf) {
|
||||
result = ConfigService.dumpBeta(dataId, group, tenant, cf.getContent(), lastModified, cf.getBetaIps());
|
||||
if (result) {
|
||||
ConfigTraceService.logDumpEvent(dataId, group, tenant, null, lastModified, handleIp,
|
||||
ConfigTraceService.DUMP_EVENT_OK, System.currentTimeMillis() - lastModified,
|
||||
cf.getContent().length());
|
||||
}
|
||||
} else {
|
||||
result = ConfigService.removeBeta(dataId, group, tenant);
|
||||
if (result) {
|
||||
ConfigTraceService.logDumpEvent(dataId, group, tenant, null, lastModified, handleIp,
|
||||
ConfigTraceService.DUMP_EVENT_REMOVE_OK, System.currentTimeMillis() - lastModified, 0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
build.remove(Objects.isNull(cf));
|
||||
build.betaIps(Objects.isNull(cf) ? null : cf.getBetaIps());
|
||||
build.content(Objects.isNull(cf) ? null : cf.getContent());
|
||||
|
||||
return DumpConfigHandler.configDump(build.build());
|
||||
} else {
|
||||
if (StringUtils.isBlank(tag)) {
|
||||
ConfigInfo cf = persistService.findConfigInfo(dataId, group, tenant);
|
||||
if (dataId.equals(AggrWhitelist.AGGRIDS_METADATA)) {
|
||||
if (null != cf) {
|
||||
AggrWhitelist.load(cf.getContent());
|
||||
} else {
|
||||
AggrWhitelist.load(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (dataId.equals(ClientIpWhiteList.CLIENT_IP_WHITELIST_METADATA)) {
|
||||
if (null != cf) {
|
||||
ClientIpWhiteList.load(cf.getContent());
|
||||
} else {
|
||||
ClientIpWhiteList.load(null);
|
||||
}
|
||||
}
|
||||
build.remove(Objects.isNull(cf));
|
||||
build.content(Objects.isNull(cf) ? null : cf.getContent());
|
||||
build.type(Objects.isNull(cf) ? null : cf.getType());
|
||||
|
||||
if (dataId.equals(SwitchService.SWITCH_META_DATAID)) {
|
||||
if (null != cf) {
|
||||
SwitchService.load(cf.getContent());
|
||||
} else {
|
||||
SwitchService.load(null);
|
||||
}
|
||||
}
|
||||
|
||||
boolean result;
|
||||
if (null != cf) {
|
||||
result = ConfigService.dump(dataId, group, tenant, cf.getContent(), lastModified, cf.getType());
|
||||
|
||||
if (result) {
|
||||
ConfigTraceService.logDumpEvent(dataId, group, tenant, null, lastModified, handleIp,
|
||||
ConfigTraceService.DUMP_EVENT_OK, System.currentTimeMillis() - lastModified,
|
||||
cf.getContent().length());
|
||||
}
|
||||
} else {
|
||||
result = ConfigService.remove(dataId, group, tenant);
|
||||
|
||||
if (result) {
|
||||
ConfigTraceService.logDumpEvent(dataId, group, tenant, null, lastModified, handleIp,
|
||||
ConfigTraceService.DUMP_EVENT_REMOVE_OK, System.currentTimeMillis() - lastModified, 0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return DumpConfigHandler.configDump(build.build());
|
||||
} else {
|
||||
|
||||
ConfigInfo4Tag cf = persistService.findConfigInfo4Tag(dataId, group, tenant, tag);
|
||||
//
|
||||
boolean result;
|
||||
if (null != cf) {
|
||||
result = ConfigService.dumpTag(dataId, group, tenant, tag, cf.getContent(), lastModified);
|
||||
if (result) {
|
||||
ConfigTraceService.logDumpEvent(dataId, group, tenant, null, lastModified, handleIp,
|
||||
ConfigTraceService.DUMP_EVENT_OK, System.currentTimeMillis() - lastModified,
|
||||
cf.getContent().length());
|
||||
}
|
||||
} else {
|
||||
result = ConfigService.removeTag(dataId, group, tenant, tag);
|
||||
if (result) {
|
||||
ConfigTraceService.logDumpEvent(dataId, group, tenant, null, lastModified, handleIp,
|
||||
ConfigTraceService.DUMP_EVENT_REMOVE_OK, System.currentTimeMillis() - lastModified, 0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
build.remove(Objects.isNull(cf));
|
||||
build.content(Objects.isNull(cf) ? null : cf.getContent());
|
||||
|
||||
return DumpConfigHandler.configDump(build.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -262,7 +216,8 @@ class DumpAllProcessor implements TaskProcessor {
|
||||
SwitchService.load(cf.getContent());
|
||||
}
|
||||
|
||||
boolean result = ConfigService.dump(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getContent(),
|
||||
boolean result = ConfigCacheService
|
||||
.dump(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getContent(),
|
||||
cf.getLastModified(), cf.getType());
|
||||
|
||||
final String content = cf.getContent();
|
||||
@ -301,7 +256,8 @@ class DumpAllBetaProcessor implements TaskProcessor {
|
||||
Page<ConfigInfoBetaWrapper> page = persistService.findAllConfigInfoBetaForDumpAll(pageNo, PAGE_SIZE);
|
||||
if (page != null) {
|
||||
for (ConfigInfoBetaWrapper cf : page.getPageItems()) {
|
||||
boolean result = ConfigService.dumpBeta(cf.getDataId(), cf.getGroup(), cf.getTenant(),
|
||||
boolean result = ConfigCacheService
|
||||
.dumpBeta(cf.getDataId(), cf.getGroup(), cf.getTenant(),
|
||||
cf.getContent(), cf.getLastModified(), cf.getBetaIps());
|
||||
LogUtil.dumpLog.info("[dump-all-beta-ok] result={}, {}, {}, length={}, md5={}", result,
|
||||
GroupKey2.getKey(cf.getDataId(), cf.getGroup()), cf.getLastModified(), cf.getContent()
|
||||
@ -338,7 +294,8 @@ class DumpAllTagProcessor implements TaskProcessor {
|
||||
Page<ConfigInfoTagWrapper> page = persistService.findAllConfigInfoTagForDumpAll(pageNo, PAGE_SIZE);
|
||||
if (page != null) {
|
||||
for (ConfigInfoTagWrapper cf : page.getPageItems()) {
|
||||
boolean result = ConfigService.dumpTag(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getTag(),
|
||||
boolean result = ConfigCacheService
|
||||
.dumpTag(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getTag(),
|
||||
cf.getContent(), cf.getLastModified());
|
||||
LogUtil.dumpLog.info("[dump-all-Tag-ok] result={}, {}, {}, length={}, md5={}", result,
|
||||
GroupKey2.getKey(cf.getDataId(), cf.getGroup()), cf.getLastModified(), cf.getContent()
|
||||
@ -380,7 +337,7 @@ class DumpChangeProcessor implements TaskProcessor {
|
||||
for (ConfigInfoWrapper config : updateMd5List) {
|
||||
final String groupKey = GroupKey2.getKey(config.getDataId(),
|
||||
config.getGroup());
|
||||
ConfigService.updateMd5(groupKey, config.getMd5(),
|
||||
ConfigCacheService.updateMd5(groupKey, config.getMd5(),
|
||||
config.getLastModified());
|
||||
}
|
||||
long endUpdateMd5 = System.currentTimeMillis();
|
||||
@ -395,7 +352,8 @@ class DumpChangeProcessor implements TaskProcessor {
|
||||
for (ConfigInfo configInfo : configDeleted) {
|
||||
if (persistService.findConfigInfo(configInfo.getDataId(), configInfo.getGroup(),
|
||||
configInfo.getTenant()) == null) {
|
||||
ConfigService.remove(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());
|
||||
ConfigCacheService
|
||||
.remove(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());
|
||||
}
|
||||
}
|
||||
long endDeletedConfigTime = System.currentTimeMillis();
|
||||
@ -408,7 +366,8 @@ class DumpChangeProcessor implements TaskProcessor {
|
||||
.findChangeConfig(startTime, endTime);
|
||||
LogUtil.defaultLog.warn("changeConfig count:{}", changeConfigs.size());
|
||||
for (ConfigInfoWrapper cf : changeConfigs) {
|
||||
boolean result = ConfigService.dumpChange(cf.getDataId(), cf.getGroup(), cf.getTenant(),
|
||||
boolean result = ConfigCacheService
|
||||
.dumpChange(cf.getDataId(), cf.getGroup(), cf.getTenant(),
|
||||
cf.getContent(), cf.getLastModified());
|
||||
final String content = cf.getContent();
|
||||
final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);
|
||||
@ -418,7 +377,7 @@ class DumpChangeProcessor implements TaskProcessor {
|
||||
GroupKey2.getKey(cf.getDataId(), cf.getGroup()),
|
||||
cf.getLastModified(), content.length(), md5});
|
||||
}
|
||||
ConfigService.reloadConfig();
|
||||
ConfigCacheService.reloadConfig();
|
||||
long endChangeConfigTime = System.currentTimeMillis();
|
||||
LogUtil.defaultLog.warn("changeConfig done,cost:{}",
|
||||
endChangeConfigTime - startChangeConfigTime);
|
||||
|
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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.service.dump;
|
||||
|
||||
import com.alibaba.nacos.common.utils.Observable;
|
||||
import com.alibaba.nacos.common.utils.Observer;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.config.server.configuration.ConditionOnEmbeddedStorage;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;
|
||||
import com.alibaba.nacos.consistency.cp.CPProtocol;
|
||||
import com.alibaba.nacos.consistency.cp.MetadataKey;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import com.alibaba.nacos.core.distributed.ProtocolManager;
|
||||
import com.alibaba.nacos.core.distributed.raft.exception.NoSuchRaftGroupException;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.GlobalExecutor;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
@Conditional(ConditionOnEmbeddedStorage.class)
|
||||
@Component
|
||||
public class EmbeddedDumpService extends DumpService {
|
||||
|
||||
private final ProtocolManager protocolManager;
|
||||
|
||||
/** If it's just a normal reading failure, it can be resolved by retrying */
|
||||
final String[] retryMessages = new String[] {
|
||||
"The conformance protocol is temporarily unavailable for reading" };
|
||||
|
||||
/**If the read failed due to an internal problem in the Raft state machine, it cannot be remedied by retrying */
|
||||
final String[] errorMessages = new String[] {
|
||||
"FSMCaller is overload.",
|
||||
"STATE_ERROR"
|
||||
};
|
||||
|
||||
/**
|
||||
* Here you inject the dependent objects constructively, ensuring that some
|
||||
* of the dependent functionality is initialized ahead of time
|
||||
*
|
||||
* @param persistService {@link PersistService}
|
||||
* @param memberManager {@link ServerMemberManager}
|
||||
* @param protocolManager {@link ProtocolManager}
|
||||
*/
|
||||
public EmbeddedDumpService(PersistService persistService,
|
||||
ServerMemberManager memberManager, ProtocolManager protocolManager) {
|
||||
super(persistService, memberManager);
|
||||
this.protocolManager = protocolManager;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
protected void init() throws Throwable {
|
||||
if (ApplicationUtils.getStandaloneMode()) {
|
||||
dumpOperate(processor, dumpAllProcessor, dumpAllBetaProcessor,
|
||||
dumpAllTagProcessor);
|
||||
return;
|
||||
}
|
||||
|
||||
CPProtocol protocol = protocolManager.getCpProtocol();
|
||||
AtomicReference<Throwable> errorReference = new AtomicReference<>(null);
|
||||
CountDownLatch waitDumpFinish = new CountDownLatch(1);
|
||||
|
||||
// watch path => /nacos_config/leader/ has value ?
|
||||
Observer observer = new Observer() {
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
GlobalExecutor.executeByCommon(() -> {
|
||||
// must make sure that there is a value here to perform the correct operation that follows
|
||||
if (Objects.isNull(arg)) {
|
||||
return;
|
||||
}
|
||||
// Identify without a timeout mechanism
|
||||
EmbeddedStorageContextUtils
|
||||
.putExtendInfo(Constants.EXTEND_NEED_READ_UNTIL_HAVE_DATA,
|
||||
"true");
|
||||
// Remove your own listening to avoid task accumulation
|
||||
boolean canEnd = false;
|
||||
for (; ; ) {
|
||||
try {
|
||||
dumpOperate(processor, dumpAllProcessor, dumpAllBetaProcessor,
|
||||
dumpAllTagProcessor);
|
||||
protocol.protocolMetaData()
|
||||
.unSubscribe(Constants.CONFIG_MODEL_RAFT_GROUP,
|
||||
MetadataKey.LEADER_META_DATA, this);
|
||||
canEnd = true;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (!shouldRetry(ex)) {
|
||||
errorReference.set(ex);
|
||||
canEnd = true;
|
||||
}
|
||||
}
|
||||
if (canEnd) {
|
||||
ThreadUtils.countDown(waitDumpFinish);
|
||||
break;
|
||||
}
|
||||
ThreadUtils.sleep(500L);
|
||||
}
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
protocol.protocolMetaData().subscribe(Constants.CONFIG_MODEL_RAFT_GROUP,
|
||||
MetadataKey.LEADER_META_DATA, observer);
|
||||
|
||||
// We must wait for the dump task to complete the callback operation before
|
||||
// continuing with the initialization
|
||||
ThreadUtils.latchAwait(waitDumpFinish);
|
||||
|
||||
// If an exception occurs during the execution of the dump task, the exception
|
||||
// needs to be thrown, triggering the node to start the failed process
|
||||
final Throwable ex = errorReference.get();
|
||||
if (Objects.nonNull(ex)) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldRetry(Throwable ex) {
|
||||
final String errMsg = ex.getMessage();
|
||||
|
||||
for (String failedMsg : errorMessages) {
|
||||
if (StringUtils.containsIgnoreCase(errMsg, failedMsg)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (final String retryMsg : retryMessages) {
|
||||
if (StringUtils.containsIgnoreCase(errMsg, retryMsg)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canExecute() {
|
||||
try {
|
||||
// if is derby + raft mode, only leader can execute
|
||||
CPProtocol protocol = protocolManager.getCpProtocol();
|
||||
return protocol.isLeader(Constants.CONFIG_MODEL_RAFT_GROUP);
|
||||
}
|
||||
catch (NoSuchRaftGroupException e) {
|
||||
return true;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
// It's impossible to get to this point
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.service.dump;
|
||||
|
||||
import com.alibaba.nacos.config.server.configuration.ConditionOnExternalStorage;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.core.cluster.ServerMemberManager;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
@Conditional(ConditionOnExternalStorage.class)
|
||||
@Component
|
||||
public class ExternalDumpService extends DumpService {
|
||||
|
||||
/**
|
||||
* Here you inject the dependent objects constructively, ensuring that some
|
||||
* of the dependent functionality is initialized ahead of time
|
||||
*
|
||||
* @param persistService {@link PersistService}
|
||||
* @param memberManager {@link ServerMemberManager}
|
||||
*/
|
||||
public ExternalDumpService(PersistService persistService,
|
||||
ServerMemberManager memberManager) {
|
||||
super(persistService, memberManager);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
protected void init() throws Throwable {
|
||||
dumpOperate(processor, dumpAllProcessor, dumpAllBetaProcessor,
|
||||
dumpAllTagProcessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canExecute() {
|
||||
return memberManager.isFirstIp();
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ import com.alibaba.nacos.config.server.manager.TaskProcessor;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfo;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfoAggr;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.service.ConfigDataChangeEvent;
|
||||
import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
|
||||
import com.alibaba.nacos.config.server.utils.ContentUtils;
|
||||
|
@ -17,7 +17,7 @@ package com.alibaba.nacos.config.server.service.notify;
|
||||
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.config.server.service.ConfigDataChangeEvent;
|
||||
import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;
|
||||
import com.alibaba.nacos.config.server.service.trace.ConfigTraceService;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
|
@ -18,9 +18,13 @@ package com.alibaba.nacos.config.server.service.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.alibaba.nacos.config.server.service.sql.ModifyRequest;
|
||||
import com.alibaba.nacos.config.server.service.sql.SqlContextUtils;
|
||||
import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
/**
|
||||
@ -95,9 +99,20 @@ public interface DatabaseOperate {
|
||||
* data modify transaction
|
||||
*
|
||||
* @param modifyRequests {@link List< ModifyRequest >}
|
||||
* @param consumer {@link BiConsumer}
|
||||
* @return is success
|
||||
*/
|
||||
Boolean update(List<ModifyRequest> modifyRequests);
|
||||
Boolean update(List<ModifyRequest> modifyRequests, BiConsumer<Boolean, Throwable> consumer);
|
||||
|
||||
/**
|
||||
* data modify transaction
|
||||
*
|
||||
* @param modifyRequests {@link List< ModifyRequest >}
|
||||
* @return is success
|
||||
*/
|
||||
default Boolean update(List<ModifyRequest> modifyRequests) {
|
||||
return update(modifyRequests, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* data modify transaction
|
||||
@ -105,11 +120,33 @@ public interface DatabaseOperate {
|
||||
*
|
||||
* @return is success
|
||||
*/
|
||||
default Boolean smartUpdate() {
|
||||
default Boolean blockUpdate() {
|
||||
try {
|
||||
return update(SqlContextUtils.getCurrentSqlContext());
|
||||
return update(EmbeddedStorageContextUtils.getCurrentSqlContext(), null);
|
||||
} finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* data modify transaction
|
||||
* The SqlContext to be executed in the current thread will be executed and automatically cleared
|
||||
*
|
||||
* @return is success
|
||||
*/
|
||||
default CompletableFuture<Boolean> futureUpdate() {
|
||||
try {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
update(EmbeddedStorageContextUtils.getCurrentSqlContext(), (o, throwable) -> {
|
||||
if (Objects.nonNull(throwable)) {
|
||||
future.completeExceptionally(throwable);
|
||||
return;
|
||||
}
|
||||
future.complete(o);
|
||||
});
|
||||
return future;
|
||||
} finally {
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.service.repository;
|
||||
|
||||
import com.alibaba.nacos.core.notify.SlowEvent;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class DerbyLoadEvent implements SlowEvent {
|
||||
|
||||
public static final DerbyLoadEvent INSTANCE = new DerbyLoadEvent();
|
||||
|
||||
private static final long serialVersionUID = 875401667921565121L;
|
||||
|
||||
}
|
@ -16,17 +16,19 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service.repository;
|
||||
|
||||
import com.alibaba.nacos.config.server.service.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.LocalDataSourceServiceImpl;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.datasource.LocalDataSourceServiceImpl;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.consistency.snapshot.LocalFileMeta;
|
||||
import com.alibaba.nacos.consistency.snapshot.Reader;
|
||||
import com.alibaba.nacos.consistency.snapshot.SnapshotOperation;
|
||||
import com.alibaba.nacos.consistency.snapshot.Writer;
|
||||
import com.alibaba.nacos.core.distributed.raft.utils.RaftExecutor;
|
||||
import com.alibaba.nacos.common.utils.DiskUtils;
|
||||
import com.alibaba.nacos.core.utils.DiskUtils;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.TimerContext;
|
||||
import com.alipay.sofa.jraft.util.CRC64;
|
||||
|
||||
import java.io.File;
|
||||
@ -35,6 +37,7 @@ import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.zip.Checksum;
|
||||
@ -60,7 +63,11 @@ public class DerbySnapshotOperation implements SnapshotOperation {
|
||||
@Override
|
||||
public void onSnapshotSave(Writer writer, BiConsumer<Boolean, Throwable> callFinally) {
|
||||
RaftExecutor.doSnapshot(() -> {
|
||||
writeLock.lock();
|
||||
|
||||
TimerContext.start("CONFIG_DERBY_SNAPSHOT_SAVE");
|
||||
|
||||
final Lock lock = writeLock;
|
||||
lock.lock();
|
||||
try {
|
||||
final String writePath = writer.getPath();
|
||||
final String parentPath = Paths.get(writePath, snapshotDir).toString();
|
||||
@ -83,7 +90,8 @@ public class DerbySnapshotOperation implements SnapshotOperation {
|
||||
writer.getPath(), writer.listFiles(), t);
|
||||
callFinally.accept(false, t);
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
lock.unlock();
|
||||
TimerContext.end(LogUtil.fatalLog);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -92,7 +100,10 @@ public class DerbySnapshotOperation implements SnapshotOperation {
|
||||
public boolean onSnapshotLoad(Reader reader) {
|
||||
final String readerPath = reader.getPath();
|
||||
final String sourceFile = Paths.get(readerPath, snapshotArchive).toString();
|
||||
writeLock.lock();
|
||||
|
||||
TimerContext.start("CONFIG_DERBY_SNAPSHOT_LOAD");
|
||||
final Lock lock = writeLock;
|
||||
lock.lock();
|
||||
try {
|
||||
final Checksum checksum = new CRC64();
|
||||
DiskUtils.decompress(sourceFile, readerPath, checksum);
|
||||
@ -118,20 +129,22 @@ public class DerbySnapshotOperation implements SnapshotOperation {
|
||||
return null;
|
||||
});
|
||||
DiskUtils.deleteDirectory(loadPath);
|
||||
NotifyCenter.publishEvent(DerbyLoadEvent.INSTANCE);
|
||||
return true;
|
||||
} catch (final Throwable t) {
|
||||
LogUtil.fatalLog.error("Fail to load snapshot, path={}, file list={}, {}.", readerPath,
|
||||
reader.listFiles(), t);
|
||||
return false;
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
lock.unlock();
|
||||
TimerContext.end(LogUtil.fatalLog);
|
||||
}
|
||||
}
|
||||
|
||||
private void doDerbyBackup(String backupDirectory) throws Exception {
|
||||
DataSourceService sourceService = DynamicDataSource.getInstance().getDataSource();
|
||||
DataSource dataSource = sourceService.getJdbcTemplate().getDataSource();
|
||||
try (Connection holder = Objects.requireNonNull(dataSource).getConnection()) {
|
||||
try (Connection holder = Objects.requireNonNull(dataSource, "dataSource").getConnection()) {
|
||||
CallableStatement cs = holder.prepareCall(backupSql);
|
||||
cs.setString(1, backupDirectory);
|
||||
cs.execute();
|
||||
|
@ -16,19 +16,27 @@
|
||||
|
||||
package com.alibaba.nacos.config.server.service.repository;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
|
||||
import com.alibaba.nacos.common.JustForTest;
|
||||
import com.alibaba.nacos.common.utils.ExceptionUtil;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.LoggerUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.configuration.ConditionDistributedEmbedStorage;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.exception.NJdbcException;
|
||||
import com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;
|
||||
import com.alibaba.nacos.config.server.model.event.RaftDBErrorEvent;
|
||||
import com.alibaba.nacos.config.server.service.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.LocalDataSourceServiceImpl;
|
||||
import com.alibaba.nacos.config.server.service.RowMapperManager;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.datasource.LocalDataSourceServiceImpl;
|
||||
import com.alibaba.nacos.config.server.service.dump.DumpConfigHandler;
|
||||
import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;
|
||||
import com.alibaba.nacos.config.server.service.sql.ModifyRequest;
|
||||
import com.alibaba.nacos.config.server.service.sql.QueryType;
|
||||
import com.alibaba.nacos.config.server.service.sql.SelectRequest;
|
||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.consistency.SerializeFactory;
|
||||
import com.alibaba.nacos.consistency.Serializer;
|
||||
@ -45,6 +53,7 @@ import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
import com.alibaba.nacos.core.utils.ClassUtils;
|
||||
import com.alibaba.nacos.core.utils.GenericType;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.protobuf.ByteString;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
@ -60,7 +69,11 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@ -136,16 +149,13 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
ProtocolManager protocolManager) throws Exception {
|
||||
this.memberManager = memberManager;
|
||||
this.protocol = protocolManager.getCpProtocol();
|
||||
|
||||
init();
|
||||
|
||||
this.protocol.addLogProcessors(Collections.singletonList(this));
|
||||
}
|
||||
|
||||
protected void init() throws Exception {
|
||||
|
||||
this.dataSourceService = (LocalDataSourceServiceImpl) DynamicDataSource.getInstance()
|
||||
.getDataSource();
|
||||
this.dataSourceService = (LocalDataSourceServiceImpl) DynamicDataSource
|
||||
.getInstance().getDataSource();
|
||||
|
||||
// Because in Raft + Derby mode, ensuring data consistency depends on the Raft's
|
||||
// log playback and snapshot recovery capabilities, and the last data must be cleared
|
||||
@ -156,6 +166,8 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
|
||||
// Registers a Derby Raft state machine failure event for node degradation processing
|
||||
NotifyCenter.registerToSharePublisher(RaftDBErrorEvent.class);
|
||||
// Register the snapshot load event
|
||||
NotifyCenter.registerToSharePublisher(DerbyLoadEvent.class);
|
||||
|
||||
NotifyCenter.registerSubscribe(new Subscribe<RaftDBErrorEvent>() {
|
||||
@Override
|
||||
@ -169,6 +181,11 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
}
|
||||
});
|
||||
|
||||
NotifyCenter.registerToPublisher(ConfigDumpEvent.class,
|
||||
NotifyCenter.RING_BUFFER_SIZE);
|
||||
NotifyCenter.registerSubscribe(new DumpConfigHandler());
|
||||
|
||||
this.protocol.addLogProcessors(Collections.singletonList(this));
|
||||
LogUtil.defaultLog.info("use DistributedTransactionServicesImpl");
|
||||
}
|
||||
|
||||
@ -180,15 +197,19 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
@Override
|
||||
public <R> R queryOne(String sql, Class<R> cls) {
|
||||
try {
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog, "queryOne info : sql : {}", sql);
|
||||
LoggerUtils
|
||||
.printIfDebugEnabled(LogUtil.defaultLog, "queryOne info : sql : {}",
|
||||
sql);
|
||||
|
||||
byte[] data = serializer.serialize(SelectRequest.builder()
|
||||
.queryType(QueryType.QUERY_ONE_NO_MAPPER_NO_ARGS).sql(sql)
|
||||
.className(cls.getCanonicalName()).build());
|
||||
|
||||
Response response = protocol.getData(
|
||||
GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data)).build());
|
||||
final boolean blockRead = EmbeddedStorageContextUtils.containsExtendInfo(Constants.EXTEND_NEED_READ_UNTIL_HAVE_DATA);
|
||||
|
||||
Response response = innerRead(GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data))
|
||||
.build(), blockRead);
|
||||
if (response.getSuccess()) {
|
||||
return serializer.deserialize(response.getData().toByteArray(), cls);
|
||||
}
|
||||
@ -196,23 +217,27 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
}
|
||||
catch (Exception e) {
|
||||
LogUtil.fatalLog
|
||||
.error("An exception occurred during the query operation : {}", e.toString());
|
||||
throw new NJdbcException(e);
|
||||
.error("An exception occurred during the query operation : {}",
|
||||
e.toString());
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, ExceptionUtil.getCause(e).toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R queryOne(String sql, Object[] args, Class<R> cls) {
|
||||
try {
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog, "queryOne info : sql : {}, args : {}", sql, args);
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog,
|
||||
"queryOne info : sql : {}, args : {}", sql, args);
|
||||
|
||||
byte[] data = serializer.serialize(SelectRequest.builder()
|
||||
.queryType(QueryType.QUERY_ONE_NO_MAPPER_WITH_ARGS).sql(sql)
|
||||
.args(args).className(cls.getCanonicalName()).build());
|
||||
|
||||
Response response = protocol.getData(
|
||||
GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data)).build());
|
||||
final boolean blockRead = EmbeddedStorageContextUtils.containsExtendInfo(Constants.EXTEND_NEED_READ_UNTIL_HAVE_DATA);
|
||||
|
||||
Response response = innerRead(GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data))
|
||||
.build(), blockRead);
|
||||
if (response.getSuccess()) {
|
||||
return serializer.deserialize(response.getData().toByteArray(), cls);
|
||||
}
|
||||
@ -220,23 +245,27 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
}
|
||||
catch (Exception e) {
|
||||
LogUtil.fatalLog
|
||||
.error("An exception occurred during the query operation : {}", e.toString());
|
||||
throw new NJdbcException(e);
|
||||
.error("An exception occurred during the query operation : {}",
|
||||
e.toString());
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, ExceptionUtil.getCause(e).toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R queryOne(String sql, Object[] args, RowMapper<R> mapper) {
|
||||
try {
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog, "queryOne info : sql : {}, args : {}", sql, args);
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog,
|
||||
"queryOne info : sql : {}, args : {}", sql, args);
|
||||
|
||||
byte[] data = serializer.serialize(SelectRequest.builder()
|
||||
.queryType(QueryType.QUERY_ONE_WITH_MAPPER_WITH_ARGS).sql(sql)
|
||||
.args(args).className(mapper.getClass().getCanonicalName()).build());
|
||||
|
||||
Response response = protocol.getData(
|
||||
GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data)).build());
|
||||
final boolean blockRead = EmbeddedStorageContextUtils.containsExtendInfo(Constants.EXTEND_NEED_READ_UNTIL_HAVE_DATA);
|
||||
|
||||
Response response = innerRead(GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data))
|
||||
.build(), blockRead);
|
||||
if (response.getSuccess()) {
|
||||
return serializer.deserialize(response.getData().toByteArray(),
|
||||
ClassUtils.resolveGenericTypeByInterface(mapper.getClass()));
|
||||
@ -245,23 +274,27 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
}
|
||||
catch (Exception e) {
|
||||
LogUtil.fatalLog
|
||||
.error("An exception occurred during the query operation : {}", e.toString());
|
||||
throw new NJdbcException(e);
|
||||
.error("An exception occurred during the query operation : {}",
|
||||
e.toString());
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, ExceptionUtil.getCause(e).toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> List<R> queryMany(String sql, Object[] args, RowMapper<R> mapper) {
|
||||
try {
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog, "queryMany info : sql : {}, args : {}", sql, args);
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog,
|
||||
"queryMany info : sql : {}, args : {}", sql, args);
|
||||
|
||||
byte[] data = serializer.serialize(SelectRequest.builder()
|
||||
.queryType(QueryType.QUERY_MANY_WITH_MAPPER_WITH_ARGS).sql(sql)
|
||||
.args(args).className(mapper.getClass().getCanonicalName()).build());
|
||||
|
||||
Response response = protocol.getData(
|
||||
GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data)).build());
|
||||
final boolean blockRead = EmbeddedStorageContextUtils.containsExtendInfo(Constants.EXTEND_NEED_READ_UNTIL_HAVE_DATA);
|
||||
|
||||
Response response = innerRead(GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data))
|
||||
.build(), blockRead);
|
||||
if (response.getSuccess()) {
|
||||
return serializer
|
||||
.deserialize(response.getData().toByteArray(), List.class);
|
||||
@ -270,22 +303,27 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
}
|
||||
catch (Exception e) {
|
||||
LogUtil.fatalLog
|
||||
.error("An exception occurred during the query operation : {}", e.toString());
|
||||
throw new NJdbcException(e);
|
||||
.error("An exception occurred during the query operation : {}",
|
||||
e.toString());
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, ExceptionUtil.getCause(e).toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> List<R> queryMany(String sql, Object[] args, Class<R> rClass) {
|
||||
try {
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog, "queryMany info : sql : {}, args : {}", sql, args);
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog,
|
||||
"queryMany info : sql : {}, args : {}", sql, args);
|
||||
|
||||
byte[] data = serializer.serialize(SelectRequest.builder()
|
||||
.queryType(QueryType.QUERY_MANY_NO_MAPPER_WITH_ARGS).sql(sql)
|
||||
.args(args).className(rClass.getCanonicalName()).build());
|
||||
Response response = protocol.getData(
|
||||
GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data)).build());
|
||||
|
||||
final boolean blockRead = EmbeddedStorageContextUtils.containsExtendInfo(Constants.EXTEND_NEED_READ_UNTIL_HAVE_DATA);
|
||||
|
||||
Response response = innerRead(GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data))
|
||||
.build(), blockRead);
|
||||
if (response.getSuccess()) {
|
||||
return serializer
|
||||
.deserialize(response.getData().toByteArray(), List.class);
|
||||
@ -294,23 +332,27 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
}
|
||||
catch (Exception e) {
|
||||
LogUtil.fatalLog
|
||||
.error("An exception occurred during the query operation : {}", e.toString());
|
||||
throw new NJdbcException(e);
|
||||
.error("An exception occurred during the query operation : {}",
|
||||
e.toString());
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, ExceptionUtil.getCause(e).toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> queryMany(String sql, Object[] args) {
|
||||
try {
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog, "queryMany info : sql : {}, args : {}", sql, args);
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog,
|
||||
"queryMany info : sql : {}, args : {}", sql, args);
|
||||
|
||||
byte[] data = serializer.serialize(SelectRequest.builder()
|
||||
.queryType(QueryType.QUERY_MANY_WITH_LIST_WITH_ARGS).sql(sql)
|
||||
.args(args).build());
|
||||
|
||||
Response response = protocol.getData(
|
||||
GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data)).build());
|
||||
final boolean blockRead = EmbeddedStorageContextUtils.containsExtendInfo(Constants.EXTEND_NEED_READ_UNTIL_HAVE_DATA);
|
||||
|
||||
Response response = innerRead(GetRequest.newBuilder().setGroup(group())
|
||||
.setData(ByteString.copyFrom(data))
|
||||
.build(), blockRead);
|
||||
if (response.getSuccess()) {
|
||||
return serializer
|
||||
.deserialize(response.getData().toByteArray(), List.class);
|
||||
@ -319,42 +361,84 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
}
|
||||
catch (Exception e) {
|
||||
LogUtil.fatalLog
|
||||
.error("An exception occurred during the query operation : {}", e.toString());
|
||||
throw new NJdbcException(e);
|
||||
.error("An exception occurred during the query operation : {}",
|
||||
e.toString());
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, ExceptionUtil.getCause(e).toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In some business situations, you need to avoid the timeout issue, so blockRead is used to determine this
|
||||
*
|
||||
* @param request {@link GetRequest}
|
||||
* @param blockRead
|
||||
* @return {@link Response}
|
||||
* @throws Exception
|
||||
*/
|
||||
private Response innerRead(GetRequest request, boolean blockRead) throws Exception {
|
||||
if (blockRead) {
|
||||
return (Response) protocol.aGetData(request).join();
|
||||
}
|
||||
Response response = protocol.getData(request);
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean update(List<ModifyRequest> sqlContext) {
|
||||
public Boolean update(List<ModifyRequest> sqlContext,
|
||||
BiConsumer<Boolean, Throwable> consumer) {
|
||||
try {
|
||||
|
||||
// Since the SQL parameter is Object[], in order to ensure that the types of
|
||||
// array elements are not lost, the serialization here is done using the java-specific
|
||||
// serialization framework, rather than continuing with the protobuff
|
||||
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog, "modifyRequests info : {}", sqlContext);
|
||||
LoggerUtils
|
||||
.printIfDebugEnabled(LogUtil.defaultLog, "modifyRequests info : {}",
|
||||
sqlContext);
|
||||
|
||||
// {timestamp}-{group}-{ip:port}-{signature}
|
||||
|
||||
final String key =
|
||||
System.currentTimeMillis() + "-" + group() + "-" + memberManager.getSelf().getAddress() + "-"
|
||||
+ MD5Utils.md5Hex(sqlContext.toString(), Constants.ENCODE);
|
||||
System.currentTimeMillis() + "-" + group() + "-" + memberManager
|
||||
.getSelf().getAddress() + "-" + MD5Utils
|
||||
.md5Hex(sqlContext.toString(), Constants.ENCODE);
|
||||
Log log = Log.newBuilder().setGroup(group()).setKey(key)
|
||||
.setData(ByteString.copyFrom(serializer.serialize(sqlContext)))
|
||||
.putAllExtendInfo(EmbeddedStorageContextUtils.getCurrentExtendInfo())
|
||||
.setType(sqlContext.getClass().getCanonicalName()).build();
|
||||
Response response = this.protocol.submit(log);
|
||||
if (response.getSuccess()) {
|
||||
return true;
|
||||
if (Objects.isNull(consumer)) {
|
||||
Response response = this.protocol.submit(log);
|
||||
if (response.getSuccess()) {
|
||||
return true;
|
||||
}
|
||||
LogUtil.defaultLog.error("execute sql modify operation failed : {}",
|
||||
response.getErrMsg());
|
||||
return false;
|
||||
}
|
||||
throw new ConsistencyException(response.getErrMsg());
|
||||
else {
|
||||
this.protocol.submitAsync(log)
|
||||
.whenComplete(
|
||||
(BiConsumer<Response, Throwable>) (response, ex) -> {
|
||||
String errMsg = Objects.isNull(ex) ?
|
||||
response.getErrMsg() :
|
||||
ExceptionUtil.getCause(ex).getMessage();
|
||||
consumer.accept(response.getSuccess(),
|
||||
StringUtils.isBlank(errMsg) ?
|
||||
null :
|
||||
new NJdbcException(errMsg));
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
LogUtil.fatalLog
|
||||
.error("An timeout exception occurred during the update operation");
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, ExceptionUtil.getCause(e).toString());
|
||||
}
|
||||
catch (Throwable e) {
|
||||
if (e instanceof ConsistencyException) {
|
||||
throw (ConsistencyException) e;
|
||||
}
|
||||
LogUtil.fatalLog
|
||||
.error("An exception occurred during the update operation : {}", e);
|
||||
throw new NJdbcException(e.toString());
|
||||
throw new NacosRuntimeException(NacosException.SERVER_ERROR, ExceptionUtil.getCause(e).toString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,7 +453,8 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
final SelectRequest selectRequest = serializer
|
||||
.deserialize(request.getData().toByteArray(), SelectRequest.class);
|
||||
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog, "getData info : selectRequest : {}", selectRequest);
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog,
|
||||
"getData info : selectRequest : {}", selectRequest);
|
||||
|
||||
final RowMapper<Object> mapper = RowMapperManager
|
||||
.getRowMapper(selectRequest.getClassName());
|
||||
@ -413,9 +498,8 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
LogUtil.fatalLog
|
||||
.error("There was an error querying the data, request : {}, error : {}",
|
||||
selectRequest, e.toString());
|
||||
return Response.newBuilder()
|
||||
.setSuccess(false)
|
||||
.setErrMsg(e.getClass().getSimpleName() + ":" + e.getMessage())
|
||||
return Response.newBuilder().setSuccess(false)
|
||||
.setErrMsg(ClassUtils.getSimplaName(e) + ":" + ExceptionUtil.getCause(e).getMessage())
|
||||
.build();
|
||||
}
|
||||
finally {
|
||||
@ -425,37 +509,41 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
|
||||
@Override
|
||||
public Response onApply(Log log) {
|
||||
LoggerUtils.printIfDebugEnabled(LogUtil.defaultLog, "onApply info : log : {}", log);
|
||||
|
||||
LoggerUtils
|
||||
.printIfDebugEnabled(LogUtil.defaultLog, "onApply info : log : {}", log);
|
||||
final ByteString byteString = log.getData();
|
||||
Preconditions.checkArgument(byteString != null, "Log.getData() must not null");
|
||||
List<ModifyRequest> sqlContext = serializer
|
||||
.deserialize(byteString.toByteArray(), List.class);
|
||||
readLock.lock();
|
||||
final Lock lock = readLock;
|
||||
lock.lock();
|
||||
try {
|
||||
Collections.sort(sqlContext, new Comparator<ModifyRequest>() {
|
||||
@Override
|
||||
public int compare(ModifyRequest pre, ModifyRequest next) {
|
||||
return pre.getExecuteNo() - next.getExecuteNo();
|
||||
}
|
||||
});
|
||||
sqlContext.sort(Comparator.comparingInt(ModifyRequest::getExecuteNo));
|
||||
boolean isOk = onUpdate(sqlContext);
|
||||
|
||||
// If there is additional information, post processing
|
||||
// Put into the asynchronous thread pool for processing to avoid blocking the
|
||||
// normal execution of the state machine
|
||||
ConfigExecutor
|
||||
.executeEmbeddedDump(() -> handleExtendInfo(log.getExtendInfoMap()));
|
||||
|
||||
return Response.newBuilder().setSuccess(isOk).build();
|
||||
|
||||
// We do not believe that an error caused by a problem with an SQL error
|
||||
// should trigger the stop operation of the raft state machine
|
||||
}
|
||||
catch (BadSqlGrammarException | DataIntegrityViolationException e) {
|
||||
return Response.newBuilder().setSuccess(false).setErrMsg(e.toString()).build();
|
||||
return Response.newBuilder().setSuccess(false).setErrMsg(e.toString())
|
||||
.build();
|
||||
}
|
||||
catch (DataAccessException e) {
|
||||
throw new ConsistencyException(e);
|
||||
throw new ConsistencyException(e.toString());
|
||||
}
|
||||
catch (Throwable t) {
|
||||
throw t;
|
||||
}
|
||||
finally {
|
||||
readLock.unlock();
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -474,27 +562,48 @@ public class DistributedDatabaseOperateImpl extends LogProcessor4CP
|
||||
return update(transactionTemplate, jdbcTemplate, sqlContext);
|
||||
}
|
||||
|
||||
public <R> R onQueryOne(String sql, Class<R> rClass) {
|
||||
public <R> R onQueryOne(String sql, Class<R> rClass) {
|
||||
return queryOne(jdbcTemplate, sql, rClass);
|
||||
}
|
||||
|
||||
public <R> R onQueryOne(String sql, Object[] args, Class<R> rClass) {
|
||||
public <R> R onQueryOne(String sql, Object[] args, Class<R> rClass) {
|
||||
return queryOne(jdbcTemplate, sql, args, rClass);
|
||||
}
|
||||
|
||||
public <R> R onQueryOne(String sql, Object[] args, RowMapper<R> mapper) {
|
||||
public <R> R onQueryOne(String sql, Object[] args, RowMapper<R> mapper) {
|
||||
return queryOne(jdbcTemplate, sql, args, mapper);
|
||||
}
|
||||
|
||||
public <R> List<R> onQueryMany(String sql, Object[] args, RowMapper<R> mapper) {
|
||||
public <R> List<R> onQueryMany(String sql, Object[] args, RowMapper<R> mapper) {
|
||||
return queryMany(jdbcTemplate, sql, args, mapper);
|
||||
}
|
||||
|
||||
public <R> List<R> onQueryMany(String sql, Object[] args, Class<R> rClass) {
|
||||
public <R> List<R> onQueryMany(String sql, Object[] args, Class<R> rClass) {
|
||||
return queryMany(jdbcTemplate, sql, args, rClass);
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> onQueryMany(String sql, Object[] args) {
|
||||
public List<Map<String, Object>> onQueryMany(String sql, Object[] args) {
|
||||
return queryMany(jdbcTemplate, sql, args);
|
||||
}
|
||||
|
||||
private void handleExtendInfo(Map<String, String> extendInfo) {
|
||||
if (extendInfo.containsKey(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT)) {
|
||||
String jsonVal = extendInfo.get(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT);
|
||||
if (StringUtils.isNotBlank(jsonVal)) {
|
||||
NotifyCenter
|
||||
.publishEvent(JacksonUtils.toObj(jsonVal, ConfigDumpEvent.class));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (extendInfo.containsKey(Constants.EXTEND_INFOS_CONFIG_DUMP_EVENT)) {
|
||||
String jsonVal = extendInfo.get(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT);
|
||||
if (StringUtils.isNotBlank(jsonVal)) {
|
||||
List<ConfigDumpEvent> list = JacksonUtils
|
||||
.toObj(jsonVal, new GenericType<List<ConfigDumpEvent>>() {
|
||||
}.getType());
|
||||
list.stream().filter(Objects::nonNull)
|
||||
.forEach(NotifyCenter::publishEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
package com.alibaba.nacos.config.server.service.repository;
|
||||
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.service.sql.SqlContextUtils;
|
||||
import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
@ -188,11 +188,11 @@ class EmbeddedPaginationHelperImpl<E> implements PaginationHelper {
|
||||
public void updateLimit(final String sql, final Object[] args) {
|
||||
String sqlUpdate = sql.replaceAll("limit \\?", "OFFSET 0 ROWS FETCH NEXT ? ROWS ONLY");
|
||||
|
||||
SqlContextUtils.addSqlContext(sqlUpdate, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sqlUpdate, args);
|
||||
try {
|
||||
databaseOperate.update(SqlContextUtils.getCurrentSqlContext());
|
||||
databaseOperate.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
} finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,13 +38,11 @@ import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.model.SameConfigPolicy;
|
||||
import com.alibaba.nacos.config.server.model.SubInfo;
|
||||
import com.alibaba.nacos.config.server.model.TenantInfo;
|
||||
import com.alibaba.nacos.config.server.service.ConfigDataChangeEvent;
|
||||
import com.alibaba.nacos.config.server.service.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.sql.SqlContextUtils;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import com.alibaba.nacos.config.server.utils.ParamUtils;
|
||||
import com.alibaba.nacos.config.server.utils.event.EventDispatcher;
|
||||
import com.alibaba.nacos.core.distributed.id.IdGeneratorManager;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Lists;
|
||||
@ -69,21 +67,21 @@ import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_ADVANCE_INFO_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_ALL_INFO_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_INFO4BETA_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_INFO4TAG_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_INFO_AGGR_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_INFO_BASE_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_INFO_CHANGED_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_INFO_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_INFO_WRAPPER_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.CONFIG_KEY_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.HISTORY_DETAIL_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.HISTORY_LIST_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.RowMapperManager.TENANT_INFO_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_ADVANCE_INFO_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_ALL_INFO_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO4BETA_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO4TAG_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO_AGGR_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO_BASE_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO_CHANGED_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_INFO_WRAPPER_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.CONFIG_KEY_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.HISTORY_DETAIL_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.HISTORY_LIST_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.service.repository.RowMapperManager.TENANT_INFO_ROW_MAPPER;
|
||||
import static com.alibaba.nacos.config.server.utils.LogUtil.defaultLog;
|
||||
|
||||
/**
|
||||
@ -96,26 +94,26 @@ import static com.alibaba.nacos.config.server.utils.LogUtil.defaultLog;
|
||||
@Component
|
||||
public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
|
||||
private final String configInfoId = "config-info-id";
|
||||
private final String configHistoryId = "config-history-id";
|
||||
private final String configTagRelationId = "config-tag-relation-id";
|
||||
private final String appConfigDataRelationSubs = "app-configdata-relation-subs";
|
||||
private final String configBetaId = "config-beta-id";
|
||||
private final String namespaceId = "namespace-id";
|
||||
private final String userId = "user-id";
|
||||
private final String roleId = "role-id";
|
||||
private final String permissionsId = "permissions_id";
|
||||
private static final String RESOURCE_CONFIG_INFO_ID = "config-info-id";
|
||||
private static final String RESOURCE_CONFIG_HISTORY_ID = "config-history-id";
|
||||
private static final String RESOURCE_CONFIG_TAG_RELATION_ID = "config-tag-relation-id";
|
||||
private static final String RESOURCE_APP_CONFIGDATA_RELATION_SUBS = "app-configdata-relation-subs";
|
||||
private static final String RESOURCE_CONFIG_BETA_ID = "config-beta-id";
|
||||
private static final String RESOURCE_NAMESPACE_ID = "namespace-id";
|
||||
private static final String RESOURCE_USER_ID = "user-id";
|
||||
private static final String RESOURCE_ROLE_ID = "role-id";
|
||||
private static final String RESOURCE_PERMISSIONS_ID = "permissions_id";
|
||||
|
||||
private DataSourceService dataSourceService;
|
||||
private DataSourceService dataSourceService;
|
||||
|
||||
private final DatabaseOperate databaseOperate;
|
||||
private final DatabaseOperate databaseOperate;
|
||||
|
||||
private final IdGeneratorManager idGeneratorManager;
|
||||
|
||||
/**
|
||||
* The constructor sets the dependency injection order
|
||||
*
|
||||
* @param databaseOperate {@link EmbeddedStoragePersistServiceImpl}
|
||||
* @param databaseOperate {@link EmbeddedStoragePersistServiceImpl}
|
||||
* @param idGeneratorManager {@link IdGeneratorManager}
|
||||
*/
|
||||
public EmbeddedStoragePersistServiceImpl(DatabaseOperate databaseOperate,
|
||||
@ -127,8 +125,10 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
dataSourceService = DynamicDataSource.getInstance().getDataSource();
|
||||
idGeneratorManager.register(configInfoId, configHistoryId, configTagRelationId, appConfigDataRelationSubs,
|
||||
configBetaId, namespaceId, userId, roleId, permissionsId);
|
||||
idGeneratorManager.register(RESOURCE_CONFIG_INFO_ID, RESOURCE_CONFIG_HISTORY_ID,
|
||||
RESOURCE_CONFIG_TAG_RELATION_ID, RESOURCE_APP_CONFIGDATA_RELATION_SUBS,
|
||||
RESOURCE_CONFIG_BETA_ID, RESOURCE_NAMESPACE_ID, RESOURCE_USER_ID,
|
||||
RESOURCE_ROLE_ID, RESOURCE_PERMISSIONS_ID);
|
||||
}
|
||||
|
||||
public boolean checkMasterWritable() {
|
||||
@ -169,13 +169,18 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
return new EmbeddedPaginationHelperImpl<E>(databaseOperate);
|
||||
}
|
||||
|
||||
public void addConfigInfo(final String srcIp, final String srcUser,
|
||||
final ConfigInfo configInfo, final Timestamp time,
|
||||
public void addConfigInfo(final String srcIp,
|
||||
final String srcUser, final ConfigInfo configInfo, final Timestamp time,
|
||||
final Map<String, Object> configAdvanceInfo, final boolean notify) {
|
||||
|
||||
try {
|
||||
long configId = idGeneratorManager.nextId(configInfoId);
|
||||
long hisId = idGeneratorManager.nextId(configHistoryId);
|
||||
final String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ?
|
||||
StringUtils.EMPTY :
|
||||
configInfo.getTenant();
|
||||
configInfo.setTenant(tenantTmp);
|
||||
|
||||
long configId = idGeneratorManager.nextId(RESOURCE_CONFIG_INFO_ID);
|
||||
long hisId = idGeneratorManager.nextId(RESOURCE_CONFIG_HISTORY_ID);
|
||||
|
||||
addConfigInfoAtomic(configId, srcIp, srcUser, configInfo, time,
|
||||
configAdvanceInfo);
|
||||
@ -185,34 +190,26 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
|
||||
addConfigTagsRelation(configId, configTags, configInfo.getDataId(),
|
||||
configInfo.getGroup(), configInfo.getTenant());
|
||||
insertConfigHistoryAtomic(hisId, configInfo, srcIp, srcUser, time,
|
||||
"I");
|
||||
|
||||
boolean result = databaseOperate.smartUpdate();
|
||||
if (!result) {
|
||||
throw new NacosConfigException("Config add failed");
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
EventDispatcher.fireEvent(
|
||||
new ConfigDataChangeEvent(false, configInfo.getDataId(),
|
||||
configInfo.getGroup(), configInfo.getTenant(),
|
||||
time.getTime()));
|
||||
}
|
||||
insertConfigHistoryAtomic(hisId, configInfo, srcIp, srcUser, time, "I");
|
||||
EmbeddedStorageContextUtils.onModifyConfigInfo(configInfo, srcIp, time);
|
||||
databaseOperate.blockUpdate();
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void addConfigInfo4Beta(ConfigInfo configInfo, String betaIps, String srcIp,
|
||||
String srcUser, Timestamp time, boolean notify) {
|
||||
public void addConfigInfo4Beta(ConfigInfo configInfo,
|
||||
String betaIps, String srcIp, String srcUser, Timestamp time,
|
||||
boolean notify) {
|
||||
String appNameTmp = StringUtils.isBlank(configInfo.getAppName()) ?
|
||||
StringUtils.EMPTY :
|
||||
configInfo.getAppName();
|
||||
String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ?
|
||||
StringUtils.EMPTY :
|
||||
configInfo.getTenant();
|
||||
|
||||
configInfo.setTenant(tenantTmp);
|
||||
try {
|
||||
String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);
|
||||
|
||||
@ -223,25 +220,19 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
configInfo.getGroup(), tenantTmp, appNameTmp, configInfo.getContent(),
|
||||
md5, betaIps, srcIp, srcUser, time, time };
|
||||
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils
|
||||
.onModifyConfigBetaInfo(configInfo, betaIps, srcIp, time);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
boolean result = databaseOperate.smartUpdate();
|
||||
if (!result) {
|
||||
throw new NacosConfigException("[Beta] Config add failed");
|
||||
}
|
||||
if (notify) {
|
||||
EventDispatcher.fireEvent(
|
||||
new ConfigDataChangeEvent(true, configInfo.getDataId(),
|
||||
configInfo.getGroup(), tenantTmp, time.getTime()));
|
||||
}
|
||||
databaseOperate.blockUpdate();
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void addConfigInfo4Tag(ConfigInfo configInfo, String tag, String srcIp,
|
||||
String srcUser, Timestamp time, boolean notify) {
|
||||
public void addConfigInfo4Tag(ConfigInfo configInfo, String tag,
|
||||
String srcIp, String srcUser, Timestamp time, boolean notify) {
|
||||
String appNameTmp = StringUtils.isBlank(configInfo.getAppName()) ?
|
||||
StringUtils.EMPTY :
|
||||
configInfo.getAppName();
|
||||
@ -249,6 +240,9 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
StringUtils.EMPTY :
|
||||
configInfo.getTenant();
|
||||
String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim();
|
||||
|
||||
configInfo.setTenant(tenantTmp);
|
||||
|
||||
try {
|
||||
String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);
|
||||
|
||||
@ -259,30 +253,30 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
configInfo.getGroup(), tenantTmp, tagTmp, appNameTmp,
|
||||
configInfo.getContent(), md5, srcIp, srcUser, time, time };
|
||||
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils
|
||||
.onModifyConfigTagInfo(configInfo, tagTmp, srcIp, time);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
boolean result = databaseOperate.smartUpdate();
|
||||
if (!result) {
|
||||
throw new NacosConfigException("[Tag] Config add failed");
|
||||
}
|
||||
if (notify) {
|
||||
EventDispatcher.fireEvent(
|
||||
new ConfigDataChangeEvent(false, configInfo.getDataId(),
|
||||
configInfo.getGroup(), tenantTmp, tagTmp,
|
||||
time.getTime()));
|
||||
}
|
||||
databaseOperate.blockUpdate();
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateConfigInfo(final ConfigInfo configInfo, final String srcIp,
|
||||
final String srcUser, final Timestamp time,
|
||||
public void updateConfigInfo(final ConfigInfo configInfo,
|
||||
final String srcIp, final String srcUser, final Timestamp time,
|
||||
final Map<String, Object> configAdvanceInfo, final boolean notify) {
|
||||
try {
|
||||
ConfigInfo oldConfigInfo = findConfigInfo(configInfo.getDataId(),
|
||||
configInfo.getGroup(), configInfo.getTenant());
|
||||
|
||||
final String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ?
|
||||
StringUtils.EMPTY :
|
||||
configInfo.getTenant();
|
||||
|
||||
oldConfigInfo.setTenant(tenantTmp);
|
||||
|
||||
String appNameTmp = oldConfigInfo.getAppName();
|
||||
// If the appName passed by the user is not empty, the appName of the user is persisted;
|
||||
// otherwise, the appName of db is used. Empty string is required to clear appName
|
||||
@ -306,32 +300,26 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
insertConfigHistoryAtomic(oldConfigInfo.getId(), oldConfigInfo, srcIp,
|
||||
srcUser, time, "U");
|
||||
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException("config modification failed");
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
EventDispatcher.fireEvent(
|
||||
new ConfigDataChangeEvent(false, configInfo.getDataId(),
|
||||
configInfo.getGroup(), configInfo.getTenant(),
|
||||
time.getTime()));
|
||||
}
|
||||
EmbeddedStorageContextUtils.onModifyConfigInfo(configInfo, srcIp, time);
|
||||
databaseOperate.blockUpdate();
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateConfigInfo4Beta(ConfigInfo configInfo, String srcIp, String srcUser,
|
||||
Timestamp time, boolean notify) {
|
||||
@Override
|
||||
public void updateConfigInfo4Beta(ConfigInfo configInfo,
|
||||
String betaIps, String srcIp, String srcUser, Timestamp time,
|
||||
boolean notify) {
|
||||
String appNameTmp = StringUtils.isBlank(configInfo.getAppName()) ?
|
||||
StringUtils.EMPTY :
|
||||
configInfo.getAppName();
|
||||
String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ?
|
||||
StringUtils.EMPTY :
|
||||
configInfo.getTenant();
|
||||
|
||||
configInfo.setTenant(tenantTmp);
|
||||
try {
|
||||
String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);
|
||||
|
||||
@ -342,26 +330,19 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
srcUser, time, appNameTmp, configInfo.getDataId(),
|
||||
configInfo.getGroup(), tenantTmp };
|
||||
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils
|
||||
.onModifyConfigBetaInfo(configInfo, betaIps, srcIp, time);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException("[Beta] config modification failed");
|
||||
}
|
||||
if (notify) {
|
||||
EventDispatcher.fireEvent(
|
||||
new ConfigDataChangeEvent(true, configInfo.getDataId(),
|
||||
configInfo.getGroup(), tenantTmp, time.getTime()));
|
||||
}
|
||||
databaseOperate.blockUpdate();
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateConfigInfo4Tag(ConfigInfo configInfo, String tag, String srcIp,
|
||||
String srcUser, Timestamp time, boolean notify) {
|
||||
public void updateConfigInfo4Tag(ConfigInfo configInfo,
|
||||
String tag, String srcIp, String srcUser, Timestamp time, boolean notify) {
|
||||
String appNameTmp = StringUtils.isBlank(configInfo.getAppName()) ?
|
||||
StringUtils.EMPTY :
|
||||
configInfo.getAppName();
|
||||
@ -369,6 +350,9 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
StringUtils.EMPTY :
|
||||
configInfo.getTenant();
|
||||
String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim();
|
||||
|
||||
configInfo.setTenant(tenantTmp);
|
||||
|
||||
try {
|
||||
String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);
|
||||
|
||||
@ -379,23 +363,14 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
srcUser, time, appNameTmp, configInfo.getDataId(),
|
||||
configInfo.getGroup(), tenantTmp, tagTmp };
|
||||
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils
|
||||
.onModifyConfigTagInfo(configInfo, tagTmp, srcIp, time);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException("[Tag] config modification failed");
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
EventDispatcher.fireEvent(
|
||||
new ConfigDataChangeEvent(true, configInfo.getDataId(),
|
||||
configInfo.getGroup(), tenantTmp, tagTmp,
|
||||
time.getTime()));
|
||||
}
|
||||
databaseOperate.blockUpdate();
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -407,7 +382,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
addConfigInfo4Beta(configInfo, betaIps, srcIp, null, time, notify);
|
||||
}
|
||||
else {
|
||||
updateConfigInfo4Beta(configInfo, srcIp, null, time, notify);
|
||||
updateConfigInfo4Beta(configInfo, betaIps, srcIp, null, time, notify);
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,16 +407,16 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
final Object[] args = new Object[] { md5, dataId, group, tenantTmp,
|
||||
lastTime };
|
||||
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException("Failed to config the MD5 modification");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,7 +440,8 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
if (isAlreadyExist(subInfo)) {
|
||||
updateConfigSubAtomic(subInfo.getDataId(), subInfo.getGroup(),
|
||||
subInfo.getAppName(), subInfo.getDate());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
addConfigSubAtomic(subInfo.getDataId(), subInfo.getGroup(),
|
||||
subInfo.getAppName(), subInfo.getDate());
|
||||
}
|
||||
@ -473,9 +449,9 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
|
||||
private boolean isAlreadyExist(SubInfo subInfo) {
|
||||
final String sql = "SELECT * from app_configdata_relation_subs WHERE dara_id=? and group_id=? and app_name=?";
|
||||
Map obj = databaseOperate.queryOne(sql, new Object[] {
|
||||
subInfo.getDataId(), subInfo.getGroup(), subInfo.getAppName()
|
||||
}, Map.class);
|
||||
Map obj = databaseOperate.queryOne(sql,
|
||||
new Object[] { subInfo.getDataId(), subInfo.getGroup(),
|
||||
subInfo.getAppName() }, Map.class);
|
||||
return obj != null;
|
||||
}
|
||||
|
||||
@ -485,19 +461,26 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
ConfigInfo configInfo = findConfigInfo(dataId, group, tenant);
|
||||
if (Objects.nonNull(configInfo)) {
|
||||
try {
|
||||
removeConfigInfoAtomic(dataId, group, tenant, srcIp, srcUser);
|
||||
String tenantTmp = StringUtils.isBlank(tenant) ?
|
||||
StringUtils.EMPTY :
|
||||
tenant;
|
||||
|
||||
removeConfigInfoAtomic(dataId, group, tenantTmp, srcIp, srcUser);
|
||||
removeTagByIdAtomic(configInfo.getId());
|
||||
insertConfigHistoryAtomic(configInfo.getId(), configInfo, srcIp, srcUser,
|
||||
time, "D");
|
||||
|
||||
EmbeddedStorageContextUtils
|
||||
.onDeleteConfigInfo(tenantTmp, group, dataId, srcIp, time);
|
||||
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException("config deletion failed");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -521,8 +504,9 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
}
|
||||
}
|
||||
|
||||
EmbeddedStorageContextUtils.onBatchDeleteConfigInfo(configInfoList);
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException("Failed to config batch deletion");
|
||||
}
|
||||
@ -530,7 +514,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
return configInfoList;
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -542,16 +526,20 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
try {
|
||||
final String sql = "DELETE FROM config_info_beta WHERE data_id=? AND group_id=? AND tenant_id=?";
|
||||
final Object[] args = new Object[] { dataId, group, tenantTmp };
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
|
||||
EmbeddedStorageContextUtils
|
||||
.onDeleteConfigBetaInfo(tenantTmp, group, dataId,
|
||||
System.currentTimeMillis());
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException("[Tag] Configuration deletion failed");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
|
||||
}
|
||||
@ -581,24 +569,24 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
if (Objects.isNull(dbContent)) {
|
||||
final Object[] args = new Object[] { dataId, group, tenantTmp, datumId,
|
||||
appNameTmp, contentTmp, now };
|
||||
SqlContextUtils.addSqlContext(insert, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(insert, args);
|
||||
}
|
||||
else if (!dbContent.equals(content)) {
|
||||
final Object[] args = new Object[] { contentTmp, now, dataId, group,
|
||||
tenantTmp, datumId };
|
||||
SqlContextUtils.addSqlContext(update, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(update, args);
|
||||
}
|
||||
|
||||
try {
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException("[Merge] Configuration release failed");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -608,18 +596,18 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
|
||||
final String sql = "DELETE FROM config_info_aggr WHERE data_id=? AND group_id=? AND tenant_id=? AND datum_id=?";
|
||||
final Object[] args = new Object[] { dataId, group, tenantTmp, datumId };
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
try {
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException(
|
||||
"[aggregation with single] Configuration deletion failed");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -629,18 +617,18 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
|
||||
final String sql = "DELETE FROM config_info_aggr WHERE data_id=? AND group_id=? AND tenant_id=?";
|
||||
final Object[] args = new Object[] { dataId, group, tenantTmp };
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
try {
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException(
|
||||
"[aggregation with all] Configuration deletion failed");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -656,11 +644,11 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
"delete from config_info_aggr where data_id=? and group_id=? and tenant_id=? and datum_id in ("
|
||||
+ datumString.toString() + ")";
|
||||
final Object[] args = new Object[] { dataId, group, tenantTmp };
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
try {
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException(
|
||||
"[aggregation] Failed to configure batch deletion");
|
||||
@ -668,7 +656,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
return true;
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -703,7 +691,8 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
entry.getValue());
|
||||
}
|
||||
|
||||
isPublishOk = databaseOperate.update(SqlContextUtils.getCurrentSqlContext());
|
||||
isPublishOk = databaseOperate
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
|
||||
if (isPublishOk == null) {
|
||||
return false;
|
||||
@ -711,7 +700,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
return isPublishOk;
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -731,10 +720,11 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
final Object[] args = new Object[] { dataId, group, tenantTmp,
|
||||
datumEntry.getKey(), appNameTmp, datumEntry.getValue(),
|
||||
new Timestamp(System.currentTimeMillis()) };
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
}
|
||||
try {
|
||||
isReplaceOk = databaseOperate.update(SqlContextUtils.getCurrentSqlContext());
|
||||
isReplaceOk = databaseOperate
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
|
||||
if (isReplaceOk == null) {
|
||||
return false;
|
||||
@ -742,7 +732,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
return isReplaceOk;
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1981,7 +1971,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
final Object[] args = new Object[] { id, configInfo.getDataId(),
|
||||
configInfo.getGroup(), tenantTmp, appNameTmp, configInfo.getContent(),
|
||||
md5Tmp, srcIp, srcUser, time, time, desc, use, effect, type, schema, };
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -1992,7 +1982,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
+ "VALUES(?,?,?,?,?,?)";
|
||||
final Object[] args = new Object[] { configId, tagName, null, dataId, group,
|
||||
tenant };
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
}
|
||||
|
||||
public void addConfigTagsRelation(long configId, String configTags, String dataId,
|
||||
@ -2008,7 +1998,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
public void removeTagByIdAtomic(long id) {
|
||||
final String sql = "DELETE FROM config_tags_relation WHERE id=?";
|
||||
final Object[] args = new Object[] { id };
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
}
|
||||
|
||||
public List<String> getConfigTagsByTenant(String tenant) {
|
||||
@ -2029,7 +2019,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
final String sql = "DELETE FROM config_info WHERE data_id=? AND group_id=? AND tenant_id=?";
|
||||
final Object[] args = new Object[] { dataId, group, tenantTmp };
|
||||
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
}
|
||||
|
||||
public void removeConfigInfoByIdsAtomic(final String ids) {
|
||||
@ -2048,7 +2038,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
paramList.add(Long.parseLong(tagArr[i]));
|
||||
}
|
||||
sql.append(") ");
|
||||
SqlContextUtils.addSqlContext(sql.toString(), paramList.toArray());
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql.toString(), paramList.toArray());
|
||||
}
|
||||
|
||||
public void removeConfigInfoTag(final String dataId, final String group,
|
||||
@ -2060,12 +2050,14 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
final String sql = "DELETE FROM config_info_tag WHERE data_id=? AND group_id=? AND tenant_id=? AND tag_id=?";
|
||||
final Object[] args = new Object[] { dataId, group, tenantTmp, tagTmp };
|
||||
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils
|
||||
.onDeleteConfigTagInfo(tenantTmp, group, dataId, tagTmp, srcIp);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
try {
|
||||
databaseOperate.update(SqlContextUtils.getCurrentSqlContext());
|
||||
databaseOperate.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2100,7 +2092,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
srcUser, time, appNameTmp, desc, use, effect, type, schema,
|
||||
configInfo.getDataId(), configInfo.getGroup(), tenantTmp };
|
||||
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
}
|
||||
|
||||
public ConfigInfo findConfigInfo(final String dataId, final String group,
|
||||
@ -2206,7 +2198,7 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
configInfo.getGroup(), tenantTmp, appNameTmp, configInfo.getContent(),
|
||||
md5Tmp, srcIp, srcUser, time, ops };
|
||||
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
}
|
||||
|
||||
public Page<ConfigHistoryInfo> findConfigHistory(String dataId, String group,
|
||||
@ -2224,17 +2216,17 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
public void addConfigSubAtomic(final String dataId, final String group,
|
||||
final String appName, final Timestamp date) {
|
||||
final String appNameTmp = appName == null ? "" : appName;
|
||||
final long id = idGeneratorManager.nextId(appConfigDataRelationSubs);
|
||||
final long id = idGeneratorManager.nextId(RESOURCE_APP_CONFIGDATA_RELATION_SUBS);
|
||||
|
||||
final String sql = "INSERT INTO app_configdata_relation_subs(id, data_id,group_id,app_name,gmt_modified) VALUES(?,?,?,?,?)";
|
||||
final Object[] args = new Object[] { id, dataId, group, appNameTmp, date };
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
try {
|
||||
databaseOperate.update(SqlContextUtils.getCurrentSqlContext());
|
||||
databaseOperate.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2244,13 +2236,13 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
|
||||
final String sql = "UPDATE app_configdata_relation_subs SET gmt_modified=? WHERE data_id=? AND group_id=? AND app_name=?";
|
||||
final Object[] args = new Object[] { time, dataId, group, appNameTmp };
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
try {
|
||||
databaseOperate.update(SqlContextUtils.getCurrentSqlContext());
|
||||
databaseOperate.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2269,17 +2261,17 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
final Object[] args = new Object[] { kp, tenantId, tenantName, tenantDesc,
|
||||
createResoure, time, time };
|
||||
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
try {
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException("Namespace creation failed");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2290,17 +2282,17 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
final Object[] args = new Object[] { tenantName, tenantDesc,
|
||||
System.currentTimeMillis(), kp, tenantId };
|
||||
|
||||
SqlContextUtils.addSqlContext(sql, args);
|
||||
EmbeddedStorageContextUtils.addSqlContext(sql, args);
|
||||
|
||||
try {
|
||||
boolean result = databaseOperate
|
||||
.update(SqlContextUtils.getCurrentSqlContext());
|
||||
.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
if (!result) {
|
||||
throw new NacosConfigException("Namespace update failed");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2319,14 +2311,14 @@ public class EmbeddedStoragePersistServiceImpl implements PersistService {
|
||||
}
|
||||
|
||||
public void removeTenantInfoAtomic(final String kp, final String tenantId) {
|
||||
SqlContextUtils
|
||||
EmbeddedStorageContextUtils
|
||||
.addSqlContext("DELETE FROM tenant_info WHERE kp=? AND tenant_id=?", kp,
|
||||
tenantId);
|
||||
try {
|
||||
databaseOperate.update(SqlContextUtils.getCurrentSqlContext());
|
||||
databaseOperate.update(EmbeddedStorageContextUtils.getCurrentSqlContext());
|
||||
}
|
||||
finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
package com.alibaba.nacos.config.server.service.repository;
|
||||
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.config.server.service.sql.SqlContextUtils;
|
||||
import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;
|
||||
import com.alibaba.nacos.config.server.utils.PropertyUtil;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@ -210,7 +210,7 @@ class ExternalStoragePaginationHelperImpl<E> implements PaginationHelper {
|
||||
try {
|
||||
jdbcTemplate.update(sqlUpdate, args);
|
||||
} finally {
|
||||
SqlContextUtils.cleanCurrentSqlContext();
|
||||
EmbeddedStorageContextUtils.cleanAllContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -93,7 +93,8 @@ public interface PersistService {
|
||||
/**
|
||||
* 更新配置信息
|
||||
*/
|
||||
void updateConfigInfo4Beta(ConfigInfo configInfo, String srcIp, String srcUser, Timestamp time,
|
||||
void updateConfigInfo4Beta(ConfigInfo configInfo,
|
||||
String betaIps, String srcIp, String srcUser, Timestamp time,
|
||||
boolean notify);
|
||||
|
||||
/**
|
||||
@ -798,4 +799,4 @@ public interface PersistService {
|
||||
* @return count by tenantId
|
||||
*/
|
||||
int tenantInfoCountByTenantId(String tenantId);
|
||||
}
|
||||
}
|
@ -1,20 +1,22 @@
|
||||
/*
|
||||
* 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
|
||||
* * 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.
|
||||
*
|
||||
* 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.service;
|
||||
package com.alibaba.nacos.config.server.service.repository;
|
||||
|
||||
import com.alibaba.nacos.config.server.auth.PermissionInfo;
|
||||
import com.alibaba.nacos.config.server.auth.RoleInfo;
|
@ -17,8 +17,8 @@
|
||||
package com.alibaba.nacos.config.server.service.repository;
|
||||
|
||||
import com.alibaba.nacos.config.server.configuration.ConditionStandaloneEmbedStorage;
|
||||
import com.alibaba.nacos.config.server.service.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DynamicDataSource;
|
||||
import com.alibaba.nacos.config.server.service.sql.ModifyRequest;
|
||||
import com.alibaba.nacos.config.server.utils.LogUtil;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
@ -30,6 +30,9 @@ import org.springframework.transaction.support.TransactionTemplate;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
@ -81,6 +84,12 @@ public class StandaloneDatabaseOperateImpl implements BaseDatabaseOperate, Datab
|
||||
return queryMany(jdbcTemplate, sql, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean update(List<ModifyRequest> modifyRequests,
|
||||
BiConsumer<Boolean, Throwable> consumer) {
|
||||
return update(modifyRequests);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean update(List<ModifyRequest> requestList) {
|
||||
return update(transactionTemplate, jdbcTemplate, requestList);
|
||||
|
@ -0,0 +1,285 @@
|
||||
/*
|
||||
* 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.service.sql;
|
||||
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.model.ConfigInfo;
|
||||
import com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Temporarily saves all insert, update, and delete statements under
|
||||
* a transaction in the order in which they occur
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class EmbeddedStorageContextUtils {
|
||||
|
||||
private static final ThreadLocal<ArrayList<ModifyRequest>> SQL_CONTEXT =
|
||||
ThreadLocal.withInitial(ArrayList::new);
|
||||
|
||||
private static final ThreadLocal<Map<String, String>> EXTEND_INFO_CONTEXT = ThreadLocal.withInitial(
|
||||
HashMap::new);
|
||||
|
||||
public static void addSqlContext(String sql, Object... args) {
|
||||
ArrayList<ModifyRequest> requests = SQL_CONTEXT.get();
|
||||
ModifyRequest context = new ModifyRequest();
|
||||
context.setExecuteNo(requests.size());
|
||||
context.setSql(sql);
|
||||
context.setArgs(args);
|
||||
requests.add(context);
|
||||
SQL_CONTEXT.set(requests);
|
||||
}
|
||||
|
||||
public static void putExtendInfo(String key, String value) {
|
||||
Map<String, String> old = EXTEND_INFO_CONTEXT.get();
|
||||
old.put(key, value);
|
||||
EXTEND_INFO_CONTEXT.set(old);
|
||||
}
|
||||
|
||||
public static void putAllExtendInfo(Map<String, String> map) {
|
||||
Map<String, String> old = EXTEND_INFO_CONTEXT.get();
|
||||
old.putAll(map);
|
||||
EXTEND_INFO_CONTEXT.set(old);
|
||||
}
|
||||
|
||||
/**
|
||||
* In the case of the in-cluster storage mode, the logic of horizontal notification
|
||||
* is implemented asynchronously via the raft state machine, along with the information
|
||||
*
|
||||
* @param configInfo {@link ConfigInfo}
|
||||
* @param srcIp The IP of the operator
|
||||
* @param time Operating time
|
||||
*/
|
||||
public static void onModifyConfigInfo(ConfigInfo configInfo, String srcIp, Timestamp time) {
|
||||
if (!ApplicationUtils.getStandaloneMode()) {
|
||||
ConfigDumpEvent event = ConfigDumpEvent.builder()
|
||||
.remove(false)
|
||||
.namespaceId(configInfo.getTenant())
|
||||
.dataId(configInfo.getDataId())
|
||||
.group(configInfo.getGroup())
|
||||
.isBeta(false)
|
||||
.content(configInfo.getContent())
|
||||
.type(configInfo.getType())
|
||||
.handleIp(srcIp)
|
||||
.lastModifiedTs(time.getTime())
|
||||
.build();
|
||||
|
||||
Map<String, String> extendInfo = new HashMap<>(2);
|
||||
extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));
|
||||
EmbeddedStorageContextUtils.putAllExtendInfo(extendInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In the case of the in-cluster storage mode, the logic of horizontal notification
|
||||
* is implemented asynchronously via the raft state machine, along with the information
|
||||
*
|
||||
* @param configInfo {@link ConfigInfo}
|
||||
* @param betaIps Receive client IP for grayscale configuration publishing
|
||||
* @param srcIp The IP of the operator
|
||||
* @param time Operating time
|
||||
*/
|
||||
public static void onModifyConfigBetaInfo(ConfigInfo configInfo, String betaIps, String srcIp, Timestamp time) {
|
||||
if (!ApplicationUtils.getStandaloneMode()) {
|
||||
ConfigDumpEvent event = ConfigDumpEvent.builder()
|
||||
.remove(false)
|
||||
.namespaceId(configInfo.getTenant())
|
||||
.dataId(configInfo.getDataId())
|
||||
.group(configInfo.getGroup())
|
||||
.isBeta(true)
|
||||
.betaIps(betaIps)
|
||||
.content(configInfo.getContent())
|
||||
.type(configInfo.getType())
|
||||
.handleIp(srcIp)
|
||||
.lastModifiedTs(time.getTime())
|
||||
.build();
|
||||
|
||||
Map<String, String> extendInfo = new HashMap<>(2);
|
||||
extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));
|
||||
EmbeddedStorageContextUtils.putAllExtendInfo(extendInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In the case of the in-cluster storage mode, the logic of horizontal notification
|
||||
* is implemented asynchronously via the raft state machine, along with the information
|
||||
*
|
||||
* @param configInfo {@link ConfigInfo}
|
||||
* @param tag tag info
|
||||
* @param srcIp The IP of the operator
|
||||
* @param time Operating time
|
||||
*/
|
||||
public static void onModifyConfigTagInfo(ConfigInfo configInfo, String tag, String srcIp, Timestamp time) {
|
||||
if (!ApplicationUtils.getStandaloneMode()) {
|
||||
ConfigDumpEvent event = ConfigDumpEvent.builder()
|
||||
.remove(false)
|
||||
.namespaceId(configInfo.getTenant())
|
||||
.dataId(configInfo.getDataId())
|
||||
.group(configInfo.getGroup())
|
||||
.isBeta(false)
|
||||
.tag(tag)
|
||||
.content(configInfo.getContent())
|
||||
.type(configInfo.getType())
|
||||
.handleIp(srcIp)
|
||||
.lastModifiedTs(time.getTime())
|
||||
.build();
|
||||
|
||||
Map<String, String> extendInfo = new HashMap<>(2);
|
||||
extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));
|
||||
EmbeddedStorageContextUtils.putAllExtendInfo(extendInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In the case of the in-cluster storage mode, the logic of horizontal notification
|
||||
* is implemented asynchronously via the raft state machine, along with the information
|
||||
*
|
||||
* @param namespaceId namespaceId
|
||||
* @param group groupName
|
||||
* @param dataId dataId
|
||||
* @param srcIp The IP of the operator
|
||||
* @param time Operating time
|
||||
*/
|
||||
public static void onDeleteConfigInfo(String namespaceId, String group, String dataId, String srcIp, Timestamp time) {
|
||||
if (!ApplicationUtils.getStandaloneMode()) {
|
||||
ConfigDumpEvent event = ConfigDumpEvent.builder()
|
||||
.remove(true)
|
||||
.namespaceId(namespaceId)
|
||||
.group(group)
|
||||
.dataId(dataId)
|
||||
.isBeta(false)
|
||||
.handleIp(srcIp)
|
||||
.lastModifiedTs(time.getTime())
|
||||
.build();
|
||||
|
||||
Map<String, String> extendInfo = new HashMap<>(2);
|
||||
extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));
|
||||
EmbeddedStorageContextUtils.putAllExtendInfo(extendInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In the case of the in-cluster storage mode, the logic of horizontal notification
|
||||
* is implemented asynchronously via the raft state machine, along with the information
|
||||
*
|
||||
* @param configInfos {@link List<ConfigInfo>}
|
||||
*/
|
||||
public static void onBatchDeleteConfigInfo(List<ConfigInfo> configInfos) {
|
||||
if (!ApplicationUtils.getStandaloneMode()) {
|
||||
List<ConfigDumpEvent> events = new ArrayList<>();
|
||||
for (ConfigInfo configInfo : configInfos) {
|
||||
String namespaceId = StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant();
|
||||
ConfigDumpEvent event = ConfigDumpEvent.builder()
|
||||
.remove(true)
|
||||
.namespaceId(namespaceId)
|
||||
.group(configInfo.getGroup())
|
||||
.dataId(configInfo.getDataId())
|
||||
.isBeta(false)
|
||||
.build();
|
||||
|
||||
events.add(event);
|
||||
}
|
||||
|
||||
Map<String, String> extendInfo = new HashMap<>(2);
|
||||
extendInfo.put(Constants.EXTEND_INFOS_CONFIG_DUMP_EVENT, JacksonUtils.toJson(events));
|
||||
EmbeddedStorageContextUtils.putAllExtendInfo(extendInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In the case of the in-cluster storage mode, the logic of horizontal notification
|
||||
* is implemented asynchronously via the raft state machine, along with the information
|
||||
*
|
||||
* @param namespaceId namespaceId
|
||||
* @param group group
|
||||
* @param dataId dataId
|
||||
* @param time Operating time
|
||||
*/
|
||||
public static void onDeleteConfigBetaInfo(String namespaceId, String group, String dataId, long time) {
|
||||
if (!ApplicationUtils.getStandaloneMode()) {
|
||||
ConfigDumpEvent event = ConfigDumpEvent.builder()
|
||||
.remove(true)
|
||||
.namespaceId(namespaceId)
|
||||
.dataId(dataId)
|
||||
.group(group)
|
||||
.isBeta(true)
|
||||
.build();
|
||||
|
||||
Map<String, String> extendInfo = new HashMap<>(2);
|
||||
extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));
|
||||
EmbeddedStorageContextUtils.putAllExtendInfo(extendInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In the case of the in-cluster storage mode, the logic of horizontal notification
|
||||
* is implemented asynchronously via the raft state machine, along with the information
|
||||
*
|
||||
* @param namespaceId namespaceId
|
||||
* @param group group
|
||||
* @param dataId dataId
|
||||
* @param tag tag info
|
||||
* @param srcIp The IP of the operator
|
||||
*/
|
||||
public static void onDeleteConfigTagInfo(String namespaceId, String group, String dataId, String tag, String srcIp) {
|
||||
if (!ApplicationUtils.getStandaloneMode()) {
|
||||
ConfigDumpEvent event = ConfigDumpEvent.builder()
|
||||
.remove(true)
|
||||
.namespaceId(namespaceId)
|
||||
.group(group)
|
||||
.dataId(dataId)
|
||||
.isBeta(true)
|
||||
.tag(tag)
|
||||
.handleIp(srcIp)
|
||||
.build();
|
||||
|
||||
Map<String, String> extendInfo = new HashMap<>(2);
|
||||
extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));
|
||||
EmbeddedStorageContextUtils.putAllExtendInfo(extendInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean containsExtendInfo(String key) {
|
||||
Map<String, String> extendInfo = EXTEND_INFO_CONTEXT.get();
|
||||
boolean exist = extendInfo.containsKey(key);
|
||||
EXTEND_INFO_CONTEXT.set(extendInfo);
|
||||
return exist;
|
||||
}
|
||||
|
||||
public static List<ModifyRequest> getCurrentSqlContext() {
|
||||
return SQL_CONTEXT.get();
|
||||
}
|
||||
|
||||
public static Map<String, String> getCurrentExtendInfo() {
|
||||
return EXTEND_INFO_CONTEXT.get();
|
||||
}
|
||||
|
||||
public static void cleanAllContext() {
|
||||
SQL_CONTEXT.remove();
|
||||
EXTEND_INFO_CONTEXT.remove();
|
||||
}
|
||||
|
||||
}
|
@ -1,51 +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.service.sql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Temporarily saves all insert, update, and delete statements under
|
||||
* a transaction in the order in which they occur
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class SqlContextUtils {
|
||||
|
||||
private static final ThreadLocal<ArrayList<ModifyRequest>> SQL_CONTEXT =
|
||||
ThreadLocal.withInitial(ArrayList::new);
|
||||
|
||||
public static void addSqlContext(String sql, Object... args) {
|
||||
ArrayList<ModifyRequest> requests = SQL_CONTEXT.get();
|
||||
ModifyRequest context = new ModifyRequest();
|
||||
context.setExecuteNo(requests.size());
|
||||
context.setSql(sql);
|
||||
context.setArgs(args);
|
||||
requests.add(context);
|
||||
SQL_CONTEXT.set(requests);
|
||||
}
|
||||
|
||||
public static List<ModifyRequest> getCurrentSqlContext() {
|
||||
return SQL_CONTEXT.get();
|
||||
}
|
||||
|
||||
public static void cleanCurrentSqlContext() {
|
||||
SQL_CONTEXT.remove();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.common.executor.ExecutorFactory;
|
||||
import com.alibaba.nacos.common.executor.NameThreadFactory;
|
||||
import com.alibaba.nacos.config.server.Config;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public final class ConfigExecutor {
|
||||
|
||||
private static final Executor DUMP_EXECUTOR = ExecutorFactory.newFixExecutorService(
|
||||
Config.class.getCanonicalName(),
|
||||
1,
|
||||
new NameThreadFactory("nacos.config.embedded.dump"));
|
||||
|
||||
private static ScheduledExecutorService TIMER_EXECUTOR = ExecutorFactory.newScheduledExecutorService(Config.class.getCanonicalName(),
|
||||
10,
|
||||
new NameThreadFactory("com.alibaba.nacos.server.Timer"));
|
||||
|
||||
static public void scheduleWithFixedDelay(Runnable command, long initialDelay, long delay,
|
||||
TimeUnit unit) {
|
||||
TIMER_EXECUTOR.scheduleWithFixedDelay(command, initialDelay, delay, unit);
|
||||
}
|
||||
|
||||
public static void executeEmbeddedDump(Runnable runnable) {
|
||||
DUMP_EXECUTOR.execute(runnable);
|
||||
}
|
||||
|
||||
}
|
@ -1,19 +1,21 @@
|
||||
/*
|
||||
* 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
|
||||
* * 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.
|
||||
*
|
||||
* 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.service;
|
||||
package com.alibaba.nacos.config.server.utils;
|
||||
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.MD5Utils;
|
@ -16,7 +16,7 @@
|
||||
package com.alibaba.nacos.config.server.utils;
|
||||
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.service.ConfigService;
|
||||
import com.alibaba.nacos.config.server.service.ConfigCacheService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -52,7 +52,8 @@ public class MD5Util {
|
||||
String groupKey = entry.getKey();
|
||||
String clientMd5 = entry.getValue();
|
||||
String ip = RequestUtil.getRemoteIp(request);
|
||||
boolean isUptodate = ConfigService.isUptodate(groupKey, clientMd5, ip, tag);
|
||||
boolean isUptodate = ConfigCacheService
|
||||
.isUptodate(groupKey, clientMd5, ip, tag);
|
||||
if (!isUptodate) {
|
||||
changedGroupKeys.add(groupKey);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import com.alibaba.nacos.config.server.constant.Constants;
|
||||
import com.alibaba.nacos.config.server.service.DataSourceService;
|
||||
import com.alibaba.nacos.config.server.service.datasource.DataSourceService;
|
||||
|
||||
/**
|
||||
* Created by qingliang on 2017/8/14.
|
||||
|
@ -40,7 +40,7 @@ public class ClientTrackServiceTest {
|
||||
String groupKey = GroupKey2.getKey(dataId, group);
|
||||
String md5 = "xxxxxxxxxxxxx";
|
||||
|
||||
ConfigService.updateMd5(groupKey, md5, System.currentTimeMillis());
|
||||
ConfigCacheService.updateMd5(groupKey, md5, System.currentTimeMillis());
|
||||
|
||||
ClientTrackService.trackClientMd5(clientIp, groupKey, md5);
|
||||
ClientTrackService.trackClientMd5(clientIp, groupKey, md5);
|
||||
@ -50,7 +50,7 @@ public class ClientTrackServiceTest {
|
||||
Assert.assertEquals(1, ClientTrackService.subscriberCount());
|
||||
|
||||
//服务端数据更新
|
||||
ConfigService.updateMd5(groupKey, md5 + "111", System.currentTimeMillis());
|
||||
ConfigCacheService.updateMd5(groupKey, md5 + "111", System.currentTimeMillis());
|
||||
Assert.assertEquals(false, ClientTrackService.isClientUptodate(clientIp).get(groupKey));
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.config.server.utils.DiskUtil;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.alibaba.nacos.config.server.service;
|
||||
|
||||
import com.alibaba.nacos.config.server.service.repository.RowMapperManager;
|
||||
import com.alibaba.nacos.core.utils.ClassUtils;
|
||||
import com.alibaba.nacos.config.server.model.User;
|
||||
import org.junit.Assert;
|
||||
|
@ -68,17 +68,25 @@ public interface ConsistencyProtocol<T extends Config, P extends LogProcessor> e
|
||||
* Obtain data according to the request
|
||||
*
|
||||
* @param request request
|
||||
* @return data {@link GetRequest}
|
||||
* @return data {@link Response}
|
||||
* @throws Exception
|
||||
*/
|
||||
Response getData(GetRequest request) throws Exception;
|
||||
|
||||
/**
|
||||
* Get data asynchronously
|
||||
*
|
||||
* @param request request
|
||||
* @return data {@link CompletableFuture<Response>}
|
||||
*/
|
||||
CompletableFuture<Response> aGetData(GetRequest request);
|
||||
|
||||
/**
|
||||
* Data operation, returning submission results synchronously
|
||||
* 同步数据提交,在 Datum 中已携带相应的数据操作信息
|
||||
*
|
||||
* @param data {@link Log}
|
||||
* @return submit operation result
|
||||
* @return submit operation result {@link Response}
|
||||
* @throws Exception
|
||||
*/
|
||||
Response submit(Log data) throws Exception;
|
||||
|
@ -19,7 +19,7 @@ package com.alibaba.nacos.consistency.cp;
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public class Constants {
|
||||
public class MetadataKey {
|
||||
|
||||
public static final String LEADER_META_DATA = "leader";
|
||||
|
@ -6,11 +6,8 @@ import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.Observable;
|
||||
import com.alibaba.nacos.common.utils.Observer;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -28,6 +25,7 @@ public class ProtocolMetaDataTest {
|
||||
|
||||
metaData.load(map);
|
||||
|
||||
String json = JacksonUtils.toJson(metaData);
|
||||
AtomicInteger count = new AtomicInteger(0);
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(2);
|
||||
@ -38,7 +36,6 @@ public class ProtocolMetaDataTest {
|
||||
latch.countDown();
|
||||
});
|
||||
|
||||
String json = JacksonUtils.toJson(metaData);
|
||||
System.out.println(json);
|
||||
|
||||
map = new HashMap<>();
|
||||
|
@ -145,13 +145,11 @@ nacos.istio.mcp.server.enabled=false
|
||||
# nacos.core.protocol.raft.data.election_timeout_ms=5000
|
||||
### Sets the amount of time the Raft snapshot will execute periodically, default is 30 minute
|
||||
# nacos.core.protocol.raft.data.snapshot_interval_secs=30
|
||||
### Requested retries, default value is 1
|
||||
# nacos.core.protocol.raft.data.request_failoverRetries=1
|
||||
### raft internal worker threads
|
||||
# nacos.core.protocol.raft.data.core_thread_num=8
|
||||
### Number of threads required for raft business request processing
|
||||
# nacos.core.protocol.raft.data.cli_service_thread_num=4
|
||||
### raft linear read strategy, defaults to index
|
||||
### raft linear read strategy. Safe linear reads are used by default, that is, the Leader tenure is confirmed by heartbeat
|
||||
# nacos.core.protocol.raft.data.read_index_type=ReadOnlySafe
|
||||
### rpc request timeout, default 5 seconds
|
||||
# nacos.core.protocol.raft.data.rpc_request_timeout_ms=5000
|
16
core/pom.xml
16
core/pom.xml
@ -166,5 +166,21 @@
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- micrometer start -->
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-registry-prometheus</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-registry-influx</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-registry-elastic</artifactId>
|
||||
</dependency>
|
||||
<!-- micrometer end -->
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -44,7 +44,7 @@ public @interface Secured {
|
||||
String resource() default StringUtils.EMPTY;
|
||||
|
||||
/**
|
||||
* Resource name parser. Should have lower priority than name()
|
||||
* Resource name parser. Should have lower priority than resource()
|
||||
*
|
||||
* @return class type of resource parser
|
||||
*/
|
||||
|
@ -17,9 +17,9 @@
|
||||
package com.alibaba.nacos.core.cluster.lookup;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.file.FileChangeEvent;
|
||||
import com.alibaba.nacos.common.file.FileWatcher;
|
||||
import com.alibaba.nacos.common.file.WatchFileCenter;
|
||||
import com.alibaba.nacos.core.file.FileChangeEvent;
|
||||
import com.alibaba.nacos.core.file.FileWatcher;
|
||||
import com.alibaba.nacos.core.file.WatchFileCenter;
|
||||
import com.alibaba.nacos.core.cluster.AbstractMemberLookup;
|
||||
import com.alibaba.nacos.core.cluster.Member;
|
||||
import com.alibaba.nacos.core.cluster.MemberUtils;
|
||||
|
@ -18,9 +18,9 @@ package com.alibaba.nacos.core.code;
|
||||
import com.alibaba.nacos.common.executor.ExecutorFactory;
|
||||
import com.alibaba.nacos.common.executor.NameThreadFactory;
|
||||
import com.alibaba.nacos.common.executor.ThreadPoolManager;
|
||||
import com.alibaba.nacos.common.file.WatchFileCenter;
|
||||
import com.alibaba.nacos.core.file.WatchFileCenter;
|
||||
import com.alibaba.nacos.common.http.HttpClientManager;
|
||||
import com.alibaba.nacos.common.utils.DiskUtils;
|
||||
import com.alibaba.nacos.core.utils.DiskUtils;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.InetUtils;
|
||||
|
@ -17,12 +17,13 @@
|
||||
package com.alibaba.nacos.core.distributed.raft;
|
||||
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.utils.MapUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.consistency.ProtocolMetaData;
|
||||
import com.alibaba.nacos.consistency.SerializeFactory;
|
||||
import com.alibaba.nacos.consistency.Serializer;
|
||||
import com.alibaba.nacos.consistency.cp.CPProtocol;
|
||||
import com.alibaba.nacos.consistency.cp.Constants;
|
||||
import com.alibaba.nacos.consistency.cp.MetadataKey;
|
||||
import com.alibaba.nacos.consistency.cp.LogProcessor4CP;
|
||||
import com.alibaba.nacos.consistency.entity.GetRequest;
|
||||
import com.alibaba.nacos.consistency.entity.Log;
|
||||
@ -34,17 +35,13 @@ import com.alibaba.nacos.core.distributed.raft.exception.NoSuchRaftGroupExceptio
|
||||
import com.alibaba.nacos.core.notify.Event;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
import com.alibaba.nacos.core.utils.InetUtils;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alipay.sofa.jraft.Node;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -102,9 +99,7 @@ public class JRaftProtocol
|
||||
private RaftConfig raftConfig;
|
||||
private JRaftServer raftServer;
|
||||
private JRaftMaintainService jRaftMaintainService;
|
||||
private Node raftNode;
|
||||
private ServerMemberManager memberManager;
|
||||
private String selfAddress = InetUtils.getSelfIp();
|
||||
private final Serializer serializer = SerializeFactory.getDefault();
|
||||
|
||||
public JRaftProtocol(ServerMemberManager memberManager) throws Exception {
|
||||
@ -117,7 +112,6 @@ public class JRaftProtocol
|
||||
public void init(RaftConfig config) {
|
||||
if (initialized.compareAndSet(false, true)) {
|
||||
this.raftConfig = config;
|
||||
this.selfAddress = memberManager.getSelf().getAddress();
|
||||
NotifyCenter.registerToSharePublisher(RaftEvent.class);
|
||||
this.raftServer.init(this.raftConfig);
|
||||
this.raftServer.start();
|
||||
@ -137,15 +131,10 @@ public class JRaftProtocol
|
||||
|
||||
// Leader information needs to be selectively updated. If it is valid data,
|
||||
// the information in the protocol metadata is updated.
|
||||
if (StringUtils.isNotBlank(leader)) {
|
||||
properties.put(Constants.LEADER_META_DATA, leader);
|
||||
}
|
||||
if (Objects.nonNull(term)) {
|
||||
properties.put(Constants.TERM_META_DATA, term);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(raftClusterInfo)) {
|
||||
properties.put(Constants.RAFT_GROUP_MEMBER, raftClusterInfo);
|
||||
}
|
||||
MapUtils.putIfValNoEmpty(properties, MetadataKey.LEADER_META_DATA, leader);
|
||||
MapUtils.putIfValNoNull(properties, MetadataKey.TERM_META_DATA, term);
|
||||
MapUtils.putIfValNoEmpty(properties, MetadataKey.RAFT_GROUP_MEMBER, raftClusterInfo);
|
||||
|
||||
value.put(groupId, properties);
|
||||
metaData.load(value);
|
||||
|
||||
@ -169,6 +158,12 @@ public class JRaftProtocol
|
||||
|
||||
@Override
|
||||
public Response getData(GetRequest request) throws Exception {
|
||||
CompletableFuture<Response> future = aGetData(request);
|
||||
return future.get(5_000L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Response> aGetData(GetRequest request) {
|
||||
return raftServer.get(request);
|
||||
}
|
||||
|
||||
@ -181,14 +176,12 @@ public class JRaftProtocol
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Response> submitAsync(Log data) {
|
||||
CompletableFuture<Response> future = new CompletableFuture<>();
|
||||
raftServer.commit(data.getGroup(), data, future);
|
||||
return future;
|
||||
return raftServer.commit(data.getGroup(), data, new CompletableFuture<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void memberChange(Set<String> addresses) {
|
||||
for (int i = 0; i < 5; i ++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (this.raftServer.peerChange(jRaftMaintainService, addresses)) {
|
||||
return;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package com.alibaba.nacos.core.distributed.raft;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.utils.ConvertUtils;
|
||||
import com.alibaba.nacos.common.utils.LoggerUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
import com.alibaba.nacos.consistency.LogProcessor;
|
||||
import com.alibaba.nacos.consistency.SerializeFactory;
|
||||
@ -37,9 +38,12 @@ import com.alibaba.nacos.core.distributed.raft.utils.JRaftConstants;
|
||||
import com.alibaba.nacos.core.distributed.raft.utils.JRaftUtils;
|
||||
import com.alibaba.nacos.core.distributed.raft.utils.RaftExecutor;
|
||||
import com.alibaba.nacos.core.distributed.raft.utils.RaftOptionsBuilder;
|
||||
import com.alibaba.nacos.core.monitor.MetricsMonitor;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.utils.ApplicationUtils;
|
||||
import com.alibaba.nacos.core.utils.ClassUtils;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alibaba.nacos.core.utils.TimerContext;
|
||||
import com.alipay.sofa.jraft.CliService;
|
||||
import com.alipay.sofa.jraft.Node;
|
||||
import com.alipay.sofa.jraft.RaftGroupService;
|
||||
@ -274,53 +278,51 @@ public class JRaftServer {
|
||||
Random random = new Random();
|
||||
long period = nodeOptions.getElectionTimeoutMs() + random.nextInt(5 * 1000);
|
||||
RaftExecutor.scheduleRaftMemberRefreshJob(() -> refreshRouteTable(groupName),
|
||||
period, period, TimeUnit.MILLISECONDS);
|
||||
nodeOptions.getElectionTimeoutMs(), period, TimeUnit.MILLISECONDS);
|
||||
multiRaftGroup.put(groupName,
|
||||
new RaftGroupTuple(node, processor, raftGroupService, machine));
|
||||
}
|
||||
}
|
||||
|
||||
Response get(final GetRequest request) {
|
||||
CompletableFuture<Response> get(final GetRequest request) {
|
||||
final String group = request.getGroup();
|
||||
CompletableFuture<Response> future = new CompletableFuture<>();
|
||||
final RaftGroupTuple tuple = findTupleByGroup(group);
|
||||
if (Objects.isNull(tuple)) {
|
||||
future.completeExceptionally(new NoSuchRaftGroupException(group));
|
||||
return future.join();
|
||||
return future;
|
||||
}
|
||||
final Node node = tuple.node;
|
||||
|
||||
final LogProcessor processor = tuple.processor;
|
||||
try {
|
||||
node.readIndex(BytesUtil.EMPTY_BYTES, new ReadIndexClosure() {
|
||||
@Override
|
||||
public void run(Status status, long index, byte[] reqCtx) {
|
||||
if (status.isOk()) {
|
||||
try {
|
||||
Response response = tuple.processor.onRequest(request);
|
||||
Response response = processor.onRequest(request);
|
||||
future.complete(response);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
future.completeExceptionally(t);
|
||||
MetricsMonitor.raftReadIndexFailed();
|
||||
future.completeExceptionally(new ConsistencyException("The conformance protocol is temporarily unavailable for reading", t));
|
||||
}
|
||||
return;
|
||||
}
|
||||
MetricsMonitor.raftReadIndexFailed();
|
||||
Loggers.RAFT.error("ReadIndex has error : {}", status.getErrorMsg());
|
||||
future.completeExceptionally(
|
||||
new ConsistencyException(status.getErrorMsg()));
|
||||
new ConsistencyException("The conformance protocol is temporarily unavailable for reading, " + status.getErrorMsg()));
|
||||
}
|
||||
});
|
||||
return future.get(rpcRequestTimeoutMs, TimeUnit.MILLISECONDS);
|
||||
return future;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
MetricsMonitor.raftReadFromLeader();
|
||||
Loggers.RAFT.warn("Raft linear read failed, go to Leader read logic : {}", e.toString());
|
||||
// run raft read
|
||||
readFromLeader(request, future);
|
||||
try {
|
||||
return future.get(rpcRequestTimeoutMs, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new ConsistencyException(
|
||||
"Data acquisition failed : " + e.toString() + ", read from leader has error : " + ex.toString());
|
||||
}
|
||||
return future;
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,14 +333,14 @@ public class JRaftServer {
|
||||
@Override
|
||||
public void accept(Response response, Throwable throwable) {
|
||||
if (Objects.nonNull(throwable)) {
|
||||
future.completeExceptionally(throwable);
|
||||
future.completeExceptionally(new ConsistencyException("The conformance protocol is temporarily unavailable for reading", throwable));
|
||||
return;
|
||||
}
|
||||
if (response.getSuccess()) {
|
||||
future.complete(response);
|
||||
} else {
|
||||
future.completeExceptionally(
|
||||
new ConsistencyException(response.getErrMsg()));
|
||||
new ConsistencyException("The conformance protocol is temporarily unavailable for reading, " + response.getErrMsg()));
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -392,20 +394,7 @@ public class JRaftServer {
|
||||
}
|
||||
|
||||
protected PeerId getLeader(final String raftGroupId) {
|
||||
final PeerId leader = new PeerId();
|
||||
final Configuration conf = findNodeByGroup(raftGroupId).getOptions()
|
||||
.getInitialConf();
|
||||
try {
|
||||
final Status st = cliService.getLeader(raftGroupId, conf, leader);
|
||||
if (st.isOk()) {
|
||||
return leader;
|
||||
}
|
||||
Loggers.RAFT.error("get Leader has failed : {}", st);
|
||||
}
|
||||
catch (final Throwable t) {
|
||||
Loggers.RAFT.error("get Leader has error : {}", t);
|
||||
}
|
||||
return null;
|
||||
return RouteTable.getInstance().selectLeader(raftGroupId);
|
||||
}
|
||||
|
||||
synchronized void shutdown() {
|
||||
@ -524,22 +513,8 @@ public class JRaftServer {
|
||||
Configuration oldConf = instance.getConfiguration(groupName);
|
||||
String oldLeader = Optional.ofNullable(instance.selectLeader(groupName))
|
||||
.orElse(PeerId.emptyPeer()).getEndpoint().toString();
|
||||
status = instance.refreshConfiguration(this.cliClientService, groupName,
|
||||
rpcRequestTimeoutMs);
|
||||
|
||||
if (status.isOk()) {
|
||||
Configuration conf = instance.getConfiguration(groupName);
|
||||
String leader = instance.selectLeader(groupName).getEndpoint().toString();
|
||||
NacosStateMachine machine = findTupleByGroup(groupName).machine;
|
||||
if (!Objects.equals(oldLeader, leader) || !Objects
|
||||
.equals(oldConf, conf)) {
|
||||
NotifyCenter.publishEvent(
|
||||
RaftEvent.builder().leader(leader).groupId(groupName)
|
||||
.term(machine.getTerm()).raftClusterInfo(
|
||||
JRaftUtils.toStrings(conf.getPeers())).build());
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = instance.refreshConfiguration(this.cliClientService, groupName, rpcRequestTimeoutMs);
|
||||
if (!status.isOk()) {
|
||||
Loggers.RAFT
|
||||
.error("Fail to refresh route configuration for group : {}, status is : {}",
|
||||
groupName, status);
|
||||
@ -573,7 +548,7 @@ public class JRaftServer {
|
||||
return cliService;
|
||||
}
|
||||
|
||||
public static class RaftGroupTuple {
|
||||
public class RaftGroupTuple {
|
||||
|
||||
private final LogProcessor processor;
|
||||
private final Node node;
|
||||
|
@ -32,11 +32,13 @@ import com.alibaba.nacos.consistency.snapshot.Writer;
|
||||
import com.alibaba.nacos.core.distributed.raft.utils.JRaftUtils;
|
||||
import com.alibaba.nacos.core.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alibaba.nacos.core.utils.TimerContext;
|
||||
import com.alipay.sofa.jraft.Closure;
|
||||
import com.alipay.sofa.jraft.Iterator;
|
||||
import com.alipay.sofa.jraft.Node;
|
||||
import com.alipay.sofa.jraft.RouteTable;
|
||||
import com.alipay.sofa.jraft.Status;
|
||||
import com.alipay.sofa.jraft.conf.Configuration;
|
||||
import com.alipay.sofa.jraft.core.StateMachineAdapter;
|
||||
import com.alipay.sofa.jraft.entity.LeaderChangeContext;
|
||||
import com.alipay.sofa.jraft.entity.LocalFileMetaOutter;
|
||||
@ -77,7 +79,6 @@ class NacosStateMachine extends StateMachineAdapter {
|
||||
this.server = server;
|
||||
this.processor = processor;
|
||||
this.groupId = processor.group();
|
||||
|
||||
adapterToJRaftSnapshot(processor.loadSnapshotOperate());
|
||||
}
|
||||
|
||||
@ -215,6 +216,13 @@ class NacosStateMachine extends StateMachineAdapter {
|
||||
.raftClusterInfo(allPeers()).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationCommitted(Configuration conf) {
|
||||
NotifyCenter.publishEvent(
|
||||
RaftEvent.builder().groupId(groupId)
|
||||
.raftClusterInfo(JRaftUtils.toStrings(conf.getPeers())).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(RaftException e) {
|
||||
super.onError(e);
|
||||
|
@ -19,12 +19,10 @@ package com.alibaba.nacos.core.distributed.raft;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.consistency.Config;
|
||||
import com.alibaba.nacos.consistency.cp.LogProcessor4CP;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -30,7 +30,7 @@ public class RaftEvent implements SlowEvent {
|
||||
|
||||
private String groupId;
|
||||
|
||||
private String leader;
|
||||
private String leader = null;
|
||||
|
||||
private Long term = null;
|
||||
|
||||
|
@ -49,56 +49,67 @@ public final class RaftSysConstants {
|
||||
public static final int DEFAULT_RAFT_RPC_REQUEST_TIMEOUT_MS = 5000;
|
||||
|
||||
/**
|
||||
* The maximum size of each file RPC (snapshot copy) request between nodes is 128 K by default
|
||||
* 节点之间每次文件 RPC (snapshot拷贝)请求的最大大小,默认为 128 K
|
||||
*/
|
||||
public static final int DEFAULT_MAX_BYTE_COUNT_PER_RPC = 128 * 1024;
|
||||
/**
|
||||
* The maximum number of logs sent from the leader to the followers is 1024 by default
|
||||
* 从 leader 往 follower 发送的最大日志个数,默认 1024
|
||||
*/
|
||||
public static final int DEFAULT_MAX_ENTRIES_SIZE = 1024;
|
||||
/**
|
||||
* The maximum body size of the log sent from the leader to the followers is 512K by default
|
||||
* 从 leader 往 follower 发送日志的最大 body 大小,默认 512K
|
||||
*/
|
||||
public static final int DEFAULT_MAX_BODY_SIZE = 512 * 1024;
|
||||
/**
|
||||
* The maximum size of the log storage buffer is 256K by default
|
||||
* 日志存储缓冲区最大大小,默认256K
|
||||
*/
|
||||
public static final int DEFAULT_MAX_APPEND_BUFFER_SIZE = 256 * 1024;
|
||||
/**
|
||||
* The election timer interval will be a random maximum outside the specified time, 1 second by default
|
||||
* 选举定时器间隔会在指定时间之外随机的最大范围,默认1秒
|
||||
*/
|
||||
public static final int DEFAULT_MAX_ELECTION_DELAY_MS = 1000;
|
||||
/**
|
||||
* 指定选举超时时间和心跳间隔时间之间的比值。心跳间隔等于
|
||||
* electionTimeoutMs/electionHeartbeatFactor,默认10分之一。
|
||||
* Specifies the ratio of the election timeout to the heartbeat interval. Heartbeat interval is equal to the electionTimeoutMs/electionHeartbeatFactor, default one of 10 points.
|
||||
* 指定选举超时时间和心跳间隔时间之间的比值。心跳间隔等于electionTimeoutMs/electionHeartbeatFactor,默认10分之一。
|
||||
*/
|
||||
public static final int DEFAULT_ELECTION_HEARTBEAT_FACTOR = 10;
|
||||
/**
|
||||
* The tasks submitted to the leader will accumulate one batch into the maximum batch size stored in the log, and 32 tasks will be assigned by default
|
||||
* 向 leader 提交的任务累积一个批次刷入日志存储的最大批次大小,默认 32 个任务
|
||||
*/
|
||||
public static final int DEFAULT_APPLY_BATCH = 32;
|
||||
/**
|
||||
* Call fsync when necessary when writing log, meta information, and it should always be true
|
||||
* 写入日志、元信息的时候必要的时候调用 fsync,通常都应该为 true
|
||||
*/
|
||||
public static final boolean DEFAULT_SYNC = true;
|
||||
/**
|
||||
* 写入 snapshot/raft 元信息是否调用 fsync,默认为 false,
|
||||
* 在 sync 为 true 的情况下,优选尊重 sync
|
||||
* If fsync is called by writing snapshot/raft information, the default is false. If sync is true, it is better to respect sync
|
||||
* 写入 snapshot/raft 元信息是否调用 fsync,默认为 false,在 sync 为 true 的情况下,优选尊重 sync
|
||||
*/
|
||||
public static final boolean DEFAULT_SYNC_META = false;
|
||||
/**
|
||||
* Internal disruptor buffer size, need to be appropriately adjusted for high write throughput applications, default 16384
|
||||
* 内部 disruptor buffer 大小,如果是写入吞吐量较高的应用,需要适当调高该值,默认 16384
|
||||
*/
|
||||
public static final int DEFAULT_DISRUPTOR_BUFFER_SIZE = 16384;
|
||||
/**
|
||||
* Whether to enable replicated pipeline request optimization by default
|
||||
* 是否启用复制的 pipeline 请求优化,默认打开
|
||||
*/
|
||||
public static final boolean DEFAULT_REPLICATOR_PIPELINE = true;
|
||||
/**
|
||||
* Maximum in-flight requests with pipeline requests enabled, 256 by default
|
||||
* 在启用 pipeline 请求情况下,最大 in-flight 请求数,默认256
|
||||
*/
|
||||
public static final int DEFAULT_MAX_REPLICATOR_INFLIGHT_MSGS = 256;
|
||||
/**
|
||||
* Whether LogEntry checksum is enabled
|
||||
* 是否启用 LogEntry checksum
|
||||
*/
|
||||
public static final boolean DEFAULT_ENABLE_LOG_ENTRY_CHECKSUM = false;
|
||||
|
@ -93,7 +93,6 @@ public abstract class AbstractProcessor {
|
||||
asyncCtx.sendResponse(Response.newBuilder().setErrMsg(ex.toString())
|
||||
.setSuccess(false).build());
|
||||
} else {
|
||||
|
||||
ByteString bytes = Objects.nonNull(data) ? ByteString.copyFrom(serializer.serialize(data)) : ByteString.EMPTY;
|
||||
|
||||
Response response = Response.newBuilder()
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package com.alibaba.nacos.core.distributed.raft.utils;
|
||||
|
||||
import com.alibaba.nacos.common.utils.DiskUtils;
|
||||
import com.alibaba.nacos.core.utils.DiskUtils;
|
||||
import com.alibaba.nacos.consistency.SerializeFactory;
|
||||
import com.alibaba.nacos.consistency.entity.GetRequest;
|
||||
import com.alibaba.nacos.common.utils.ThreadUtils;
|
||||
@ -34,7 +34,6 @@ import com.alipay.sofa.jraft.Status;
|
||||
import com.alipay.sofa.jraft.conf.Configuration;
|
||||
import com.alipay.sofa.jraft.entity.PeerId;
|
||||
import com.alipay.sofa.jraft.option.NodeOptions;
|
||||
import com.alipay.sofa.jraft.rpc.RaftRpcFactory;
|
||||
import com.alipay.sofa.jraft.rpc.RaftRpcServerFactory;
|
||||
import com.alipay.sofa.jraft.rpc.RpcServer;
|
||||
import com.alipay.sofa.jraft.rpc.impl.GrpcRaftRpcFactory;
|
||||
|
@ -86,6 +86,16 @@ public final class RaftExecutor {
|
||||
raftCommonExecutor.execute(r);
|
||||
}
|
||||
|
||||
public static void scheduleByCommon(Runnable r, long delayMs) {
|
||||
raftCommonExecutor.schedule(r, delayMs, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public static void scheduleAtFixedRateByCommon(Runnable command,
|
||||
long initialDelayMs,
|
||||
long periodMs) {
|
||||
raftCommonExecutor.scheduleAtFixedRate(command, initialDelayMs, periodMs, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public static ScheduledExecutorService getRaftCommonExecutor() {
|
||||
return raftCommonExecutor;
|
||||
}
|
||||
|
@ -84,17 +84,17 @@ public class RaftOptionsBuilder {
|
||||
raftOptions.setApplyBatch(
|
||||
ConvertUtils.toInt(config.getVal(APPLY_BATCH), DEFAULT_APPLY_BATCH));
|
||||
|
||||
raftOptions.setSync(ConvertUtils.toBoolean(config.getVal(SYNC), DEFAULT_SYNC));
|
||||
raftOptions.setSync(ConvertUtils.toBool(config.getVal(SYNC), DEFAULT_SYNC));
|
||||
|
||||
raftOptions.setSyncMeta(
|
||||
ConvertUtils.toBoolean(config.getVal(SYNC_META), DEFAULT_SYNC_META));
|
||||
ConvertUtils.toBool(config.getVal(SYNC_META), DEFAULT_SYNC_META));
|
||||
|
||||
raftOptions.setDisruptorBufferSize(ConvertUtils
|
||||
.toInt(config.getVal(DISRUPTOR_BUFFER_SIZE),
|
||||
DEFAULT_DISRUPTOR_BUFFER_SIZE));
|
||||
|
||||
raftOptions.setReplicatorPipeline(ConvertUtils
|
||||
.toBoolean(config.getVal(REPLICATOR_PIPELINE),
|
||||
.toBool(config.getVal(REPLICATOR_PIPELINE),
|
||||
DEFAULT_REPLICATOR_PIPELINE));
|
||||
|
||||
raftOptions.setMaxReplicatorInflightMsgs(ConvertUtils
|
||||
@ -102,7 +102,7 @@ public class RaftOptionsBuilder {
|
||||
DEFAULT_MAX_REPLICATOR_INFLIGHT_MSGS));
|
||||
|
||||
raftOptions.setEnableLogEntryChecksum(ConvertUtils
|
||||
.toBoolean(config.getVal(ENABLE_LOG_ENTRY_CHECKSUM),
|
||||
.toBool(config.getVal(ENABLE_LOG_ENTRY_CHECKSUM),
|
||||
DEFAULT_ENABLE_LOG_ENTRY_CHECKSUM));
|
||||
|
||||
return raftOptions;
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.common.file;
|
||||
package com.alibaba.nacos.core.file;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.nio.file.WatchEvent;
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.common.file;
|
||||
package com.alibaba.nacos.core.file;
|
||||
|
||||
import java.nio.file.WatchEvent;
|
||||
import java.util.concurrent.Executor;
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.common.file;
|
||||
package com.alibaba.nacos.core.file;
|
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException;
|
||||
import com.alibaba.nacos.common.executor.ExecutorFactory;
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.core.monitor;
|
||||
|
||||
import io.micrometer.core.instrument.*;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public final class MetricsMonitor {
|
||||
|
||||
private static final DistributionSummary RAFT_READ_INDEX_FAILED;
|
||||
private static final DistributionSummary RAFT_FROM_LEADER;
|
||||
private static final Timer RAFT_APPLY_LOG_TIMER;
|
||||
private static final Timer RAFT_APPLY_READ_TIMER;
|
||||
|
||||
static {
|
||||
RAFT_READ_INDEX_FAILED = NacosMeterRegistry.summary("protocol", "raft_read_index_failed");
|
||||
RAFT_FROM_LEADER = NacosMeterRegistry.summary("protocol", "raft_read_from_leader");
|
||||
|
||||
RAFT_APPLY_LOG_TIMER = NacosMeterRegistry.timer("protocol", "raft_apply_log_timer");
|
||||
RAFT_APPLY_READ_TIMER = NacosMeterRegistry.timer("protocol", "raft_apply_read_timer");
|
||||
}
|
||||
|
||||
public static void raftReadIndexFailed() {
|
||||
RAFT_READ_INDEX_FAILED.record(1);
|
||||
}
|
||||
|
||||
public static void raftReadFromLeader() {
|
||||
RAFT_FROM_LEADER.record(1);
|
||||
}
|
||||
|
||||
public static Timer getRaftApplyLogTimer() {
|
||||
return RAFT_APPLY_LOG_TIMER;
|
||||
}
|
||||
|
||||
public static Timer getRaftApplyReadTimer() {
|
||||
return RAFT_APPLY_READ_TIMER;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.core.monitor;
|
||||
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import io.micrometer.core.instrument.ImmutableTag;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Metrics unified usage center
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
public final class NacosMeterRegistry {
|
||||
|
||||
private static final CompositeMeterRegistry METER_REGISTRY = new CompositeMeterRegistry();
|
||||
|
||||
public static DistributionSummary summary(String module, String name) {
|
||||
ImmutableTag moduleTag = new ImmutableTag("module", module);
|
||||
List<Tag> tags = new ArrayList<>();
|
||||
tags.add(moduleTag);
|
||||
tags.add(new ImmutableTag("name", name));
|
||||
return METER_REGISTRY.summary("nacos_monitor", tags);
|
||||
}
|
||||
|
||||
public static Timer timer(String module, String name) {
|
||||
ImmutableTag moduleTag = new ImmutableTag("module", module);
|
||||
List<Tag> tags = new ArrayList<>();
|
||||
tags.add(moduleTag);
|
||||
tags.add(new ImmutableTag("name", name));
|
||||
return METER_REGISTRY.timer("nacos_monitor", tags);
|
||||
}
|
||||
|
||||
}
|
@ -158,6 +158,7 @@ public class DefaultPublisher extends Thread implements EventPublisher {
|
||||
|
||||
void receiveEvent(Event event) {
|
||||
final long currentEventSequence = event.sequence();
|
||||
final String sourceName = event.getClass().getName();
|
||||
|
||||
// Notification single event listener
|
||||
for (Subscribe subscribe : subscribes) {
|
||||
@ -169,6 +170,12 @@ public class DefaultPublisher extends Thread implements EventPublisher {
|
||||
event.getClass());
|
||||
continue;
|
||||
}
|
||||
|
||||
final String targetName = subscribe.subscribeType().getName();
|
||||
if (!Objects.equals(sourceName, targetName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
notifySubscriber(subscribe, event);
|
||||
}
|
||||
|
||||
@ -188,13 +195,6 @@ public class DefaultPublisher extends Thread implements EventPublisher {
|
||||
@Override
|
||||
public void notifySubscriber(final Subscribe subscribe, final Event event) {
|
||||
|
||||
final String sourceName = event.getClass().getName();
|
||||
final String targetName = subscribe.subscribeType().getName();
|
||||
|
||||
if (!Objects.equals(sourceName, targetName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.debug("[NotifyCenter] the {} will received by {}", event,
|
||||
subscribe);
|
||||
|
||||
|
@ -18,7 +18,6 @@ package com.alibaba.nacos.core.notify;
|
||||
|
||||
import com.alibaba.nacos.common.JustForTest;
|
||||
import com.alibaba.nacos.common.utils.ConcurrentHashSet;
|
||||
import com.alibaba.nacos.common.utils.LoggerUtils;
|
||||
import com.alibaba.nacos.common.utils.ShutdownUtils;
|
||||
import com.alibaba.nacos.core.notify.listener.SmartSubscribe;
|
||||
import com.alibaba.nacos.core.notify.listener.Subscribe;
|
||||
@ -28,7 +27,6 @@ import org.slf4j.LoggerFactory;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -208,7 +206,12 @@ public class NotifyCenter {
|
||||
* @param event
|
||||
*/
|
||||
public static boolean publishEvent(final Event event) {
|
||||
return publishEvent(event.getClass(), event);
|
||||
try {
|
||||
return publishEvent(event.getClass(), event);
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("There was an exception to the message publishing : {}", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,9 +17,7 @@
|
||||
package com.alibaba.nacos.core.utils;
|
||||
|
||||
import com.alibaba.nacos.common.JustForTest;
|
||||
import com.alibaba.nacos.common.utils.DiskUtils;
|
||||
import com.alibaba.nacos.common.utils.IoUtils;
|
||||
import com.alibaba.nacos.common.utils.ShutdownUtils;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import com.sun.management.OperatingSystemMXBean;
|
||||
import org.springframework.beans.BeansException;
|
||||
|
@ -18,6 +18,8 @@ package com.alibaba.nacos.core.utils;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
@ -40,4 +42,34 @@ public final class ClassUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getName(Object obj) {
|
||||
Objects.requireNonNull(obj, "obj");
|
||||
return obj.getClass().getName();
|
||||
}
|
||||
|
||||
public static String getCanonicalName(Object obj) {
|
||||
Objects.requireNonNull(obj, "obj");
|
||||
return obj.getClass().getCanonicalName();
|
||||
}
|
||||
|
||||
public static String getSimplaName(Object obj) {
|
||||
Objects.requireNonNull(obj, "obj");
|
||||
return obj.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
public static String getName(Class cls) {
|
||||
Objects.requireNonNull(cls, "cls");
|
||||
return cls.getName();
|
||||
}
|
||||
|
||||
public static String getCanonicalName(Class cls) {
|
||||
Objects.requireNonNull(cls, "cls");
|
||||
return cls.getCanonicalName();
|
||||
}
|
||||
|
||||
public static String getSimplaName(Class cls) {
|
||||
Objects.requireNonNull(cls, "cls");
|
||||
return cls.getSimpleName();
|
||||
}
|
||||
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.common.utils;
|
||||
package com.alibaba.nacos.core.utils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
@ -28,7 +28,6 @@ import java.io.InputStreamReader;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -41,6 +40,7 @@ import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import com.alibaba.nacos.common.utils.ByteUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.output.NullOutputStream;
|
@ -16,13 +16,19 @@
|
||||
|
||||
package com.alibaba.nacos.core.utils;
|
||||
|
||||
import com.alibaba.nacos.common.utils.LoggerUtils;
|
||||
import com.alibaba.nacos.common.utils.Pair;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Simple task time calculation
|
||||
* Simple task time calculation,Currently only the task time statistics task that
|
||||
* supports synchronizing code blocks is supported
|
||||
*
|
||||
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||
*/
|
||||
@ -30,15 +36,33 @@ public class TimerContext {
|
||||
|
||||
private static final ThreadLocal<Pair<String, Long>> TIME_RECORD = new ThreadLocal<>();
|
||||
|
||||
public static void start(String name) {
|
||||
public static void start(final String name) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
TIME_RECORD.set(Pair.with(name, startTime));
|
||||
}
|
||||
|
||||
public static void end(final Logger logger) {
|
||||
end(logger, LoggerUtils.DEBUG);
|
||||
}
|
||||
|
||||
public static void end(final Logger logger, final String level) {
|
||||
long endTime = System.currentTimeMillis();
|
||||
Pair<String, Long> record = TIME_RECORD.get();
|
||||
logger.info("{} cost time : {} ms", record.getFirst(), (endTime - record.getSecond()));
|
||||
if (StringUtils.equals(level, LoggerUtils.DEBUG)) {
|
||||
LoggerUtils.printIfDebugEnabled(logger, "{} cost time : {} ms", record.getFirst(), (endTime - record.getSecond()));
|
||||
}
|
||||
if (StringUtils.equals(level, LoggerUtils.INFO)) {
|
||||
LoggerUtils.printIfInfoEnabled(logger, "{} cost time : {} ms", record.getFirst(), (endTime - record.getSecond()));
|
||||
}
|
||||
if (StringUtils.equals(level, LoggerUtils.TRACE)) {
|
||||
LoggerUtils.printIfTraceEnabled(logger, "{} cost time : {} ms", record.getFirst(), (endTime - record.getSecond()));
|
||||
}
|
||||
if (StringUtils.equals(level, LoggerUtils.ERROR)) {
|
||||
LoggerUtils.printIfErrorEnabled(logger, "{} cost time : {} ms", record.getFirst(), (endTime - record.getSecond()));
|
||||
}
|
||||
if (StringUtils.equals(level, LoggerUtils.WARN)) {
|
||||
LoggerUtils.printIfWarnEnabled(logger, "{} cost time : {} ms", record.getFirst(), (endTime - record.getSecond()));
|
||||
}
|
||||
TIME_RECORD.remove();
|
||||
}
|
||||
|
||||
@ -51,10 +75,28 @@ public class TimerContext {
|
||||
}
|
||||
}
|
||||
|
||||
public static <V> V run(final Callable<V> job, final String name, final Logger logger) throws Exception {
|
||||
public static <V> V run(final Supplier<V> job, final String name, final Logger logger) {
|
||||
start(name);
|
||||
try {
|
||||
return job.call();
|
||||
return job.get();
|
||||
} finally {
|
||||
end(logger);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T, R> R run(final Function<T, R> job, T args, final String name, final Logger logger) {
|
||||
start(name);
|
||||
try {
|
||||
return job.apply(args);
|
||||
} finally {
|
||||
end(logger);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void run(final Consumer<T> job, T args, final String name, final Logger logger) {
|
||||
start(name);
|
||||
try {
|
||||
job.accept(args);
|
||||
} finally {
|
||||
end(logger);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user