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:
TsingLiang 2020-06-01 14:09:12 +08:00 committed by GitHub
commit a8c5a8da26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
108 changed files with 4054 additions and 1826 deletions

View File

@ -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);
}
}
}

View File

@ -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>

View File

@ -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);

View File

@ -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() {

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View 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>
* &#064;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");
}
}

View File

@ -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;

View File

@ -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() {

View File

@ -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
}

View File

@ -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;
}

View File

@ -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"));
}
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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";
}

View File

@ -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");

View File

@ -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;

View File

@ -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);
/**
* 数据不存在
*/

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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,

View File

@ -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);
}
}

View File

@ -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
*/

View File

@ -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)) {

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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间隔

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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);
}
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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.

View File

@ -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));
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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";

View File

@ -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<>();

View File

@ -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

View File

@ -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>

View File

@ -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
*/

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -30,7 +30,7 @@ public class RaftEvent implements SlowEvent {
private String groupId;
private String leader;
private String leader = null;
private Long term = null;

View File

@ -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;

View File

@ -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()

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;
}
}
/**

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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 calculationCurrently 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