diff --git a/api/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java b/api/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java index a0095c04a..3d7e24fd4 100644 --- a/api/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java +++ b/api/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java @@ -24,6 +24,8 @@ public class PropertyKeyConst { public final static String ENDPOINT = "endpoint"; + public final static String ENDPOINT_PORT = "endpointPort"; + public final static String NAMESPACE = "namespace"; public final static String ACCESS_KEY = "accessKey"; @@ -39,7 +41,17 @@ public class PropertyKeyConst { public final static String ENCODE = "encode"; public final static String NAMING_LOAD_CACHE_AT_START = "namingLoadCacheAtStart"; + public final static String NAMING_CLIENT_BEAT_THREAD_COUNT = "namingClientBeatThreadCount"; + public final static String NAMING_POLLING_THREAD_COUNT = "namingPollingThreadCount"; + public static class SystemEnv { + + public static final String ALIBABA_ALIWARE_ENDPOINT_PORT = "ALIBABA_ALIWARE_ENDPOINT_PORT"; + + public static final String ALIBABA_ALIWARE_NAMESPACE = "ALIBABA_ALIWARE_NAMESPACE"; + + public static final String ALIBABA_ALIWARE_ENDPOINT_URL = "ALIBABA_ALIWARE_ENDPOINT_URL"; + } } diff --git a/api/src/main/java/com/alibaba/nacos/api/SystemPropertyKeyConst.java b/api/src/main/java/com/alibaba/nacos/api/SystemPropertyKeyConst.java new file mode 100644 index 000000000..4b41e6c8a --- /dev/null +++ b/api/src/main/java/com/alibaba/nacos/api/SystemPropertyKeyConst.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * 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.api; + +/** + * Properties that are preferred to which in {@link PropertyKeyConst} + * + * @author pbting + * @date 2019-02-22 3:38 PM + */ +public interface SystemPropertyKeyConst { + + String NAMING_SERVER_PORT = "nacos.naming.exposed.port"; + + String NAMING_WEB_CONTEXT = "nacos.naming.web.context"; + + String NACOS_NAMING_REQUEST_MODULE = "nacos.naming.request.module"; +} diff --git a/client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java b/client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java index f440e99e9..aa304a472 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java @@ -34,6 +34,7 @@ import com.alibaba.nacos.client.config.utils.ParamUtils; import com.alibaba.nacos.client.config.utils.TenantUtil; import com.alibaba.nacos.client.utils.LogUtils; import com.alibaba.nacos.client.utils.StringUtils; +import com.alibaba.nacos.client.utils.TemplateUtils; import org.slf4j.Logger; import java.io.IOException; @@ -42,6 +43,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; +import java.util.concurrent.Callable; /** * Config Impl @@ -73,19 +75,33 @@ public class NacosConfigService implements ConfigService { } else { encode = encodeTmp.trim(); } - String namespaceTmp = properties.getProperty(PropertyKeyConst.NAMESPACE); - if (StringUtils.isBlank(namespaceTmp)) { - namespace = TenantUtil.getUserTenant(); - properties.put(PropertyKeyConst.NAMESPACE, namespace); - } else { - namespace = namespaceTmp; - properties.put(PropertyKeyConst.NAMESPACE, namespace); - } + initNamespace(properties); agent = new MetricsHttpAgent(new ServerHttpAgent(properties)); agent.start(); worker = new ClientWorker(agent, configFilterChainManager); } + private void initNamespace(Properties properties) { + String namespaceTmp = properties.getProperty(PropertyKeyConst.NAMESPACE); + + namespaceTmp = TemplateUtils.stringBlankAndThenExecute(namespaceTmp, new Callable() { + @Override + public String call() { + return TenantUtil.getUserTenant(); + } + }); + + namespaceTmp = TemplateUtils.stringBlankAndThenExecute(namespaceTmp, new Callable() { + @Override + public String call() { + String namespace = System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_NAMESPACE); + return StringUtils.isNotBlank(namespace) ? namespace : ""; + } + }); + namespace = namespaceTmp; + properties.put(PropertyKeyConst.NAMESPACE, namespace); + } + @Override public String getConfig(String dataId, String group, long timeoutMs) throws NacosException { return getConfigInner(namespace, dataId, group, timeoutMs); diff --git a/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java b/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java index 72c15f12a..1b44fce4e 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java @@ -24,6 +24,7 @@ import com.alibaba.nacos.client.config.impl.ServerListManager; import com.alibaba.nacos.client.config.impl.SpasAdapter; import com.alibaba.nacos.client.config.utils.IOUtils; import com.alibaba.nacos.client.identify.STSConfig; +import com.alibaba.nacos.client.utils.TemplateUtils; import com.alibaba.nacos.client.utils.JSONUtils; import com.alibaba.nacos.client.utils.LogUtils; import com.alibaba.nacos.client.utils.ParamUtil; @@ -41,6 +42,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Properties; +import java.util.concurrent.Callable; /** * Server Agent @@ -197,29 +199,29 @@ public class ServerHttpAgent implements HttpAgent { public ServerHttpAgent(ServerListManager mgr, Properties properties) { serverListMgr = mgr; - String ak = properties.getProperty(PropertyKeyConst.ACCESS_KEY); - if (StringUtils.isBlank(ak)) { - accessKey = SpasAdapter.getAk(); - } else { - accessKey = ak; - } - - String sk = properties.getProperty(PropertyKeyConst.SECRET_KEY); - if (StringUtils.isBlank(sk)) { - secretKey = SpasAdapter.getSk(); - } else { - secretKey = sk; - } + init(properties); } public ServerHttpAgent(Properties properties) throws NacosException { - String encodeTmp = properties.getProperty(PropertyKeyConst.ENCODE); - if (StringUtils.isBlank(encodeTmp)) { - encode = Constants.ENCODE; - } else { - encode = encodeTmp.trim(); - } serverListMgr = new ServerListManager(properties); + init(properties); + } + + private void init(Properties properties) { + initEncode(properties); + initAkSk(properties); + } + + private void initEncode(Properties properties) { + encode = TemplateUtils.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.ENCODE), new Callable() { + @Override + public String call() throws Exception { + return Constants.ENCODE; + } + }); + } + + private void initAkSk(Properties properties) { String ak = properties.getProperty(PropertyKeyConst.ACCESS_KEY); if (StringUtils.isBlank(ak)) { accessKey = SpasAdapter.getAk(); @@ -273,8 +275,9 @@ public class ServerHttpAgent implements HttpAgent { } } String stsResponse = getSTSResponse(); - STSCredential stsCredentialTmp = (STSCredential)JSONUtils.deserializeObject(stsResponse, - new TypeReference() {}); + STSCredential stsCredentialTmp = (STSCredential) JSONUtils.deserializeObject(stsResponse, + new TypeReference() { + }); sTSCredential = stsCredentialTmp; LOGGER.info("[getSTSCredential] code:{}, accessKeyId:{}, lastUpdated:{}, expiration:{}", sTSCredential.getCode(), sTSCredential.getAccessKeyId(), sTSCredential.getLastUpdated(), sTSCredential.getExpiration()); @@ -291,7 +294,7 @@ public class ServerHttpAgent implements HttpAgent { int respCode; String response; try { - conn = (HttpURLConnection)new URL(securityCredentialsUrl).openConnection(); + conn = (HttpURLConnection) new URL(securityCredentialsUrl).openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(ParamUtil.getConnectTimeout() > 100 ? ParamUtil.getConnectTimeout() : 100); conn.setReadTimeout(1000); diff --git a/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java b/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java index b0dbd03af..6907bec1a 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/impl/ServerListManager.java @@ -20,22 +20,15 @@ import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.client.config.impl.EventDispatcher.ServerlistChangeEvent; import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult; import com.alibaba.nacos.client.config.utils.IOUtils; -import com.alibaba.nacos.client.utils.EnvUtil; -import com.alibaba.nacos.client.utils.LogUtils; -import com.alibaba.nacos.client.utils.ParamUtil; -import com.alibaba.nacos.client.utils.StringUtils; +import com.alibaba.nacos.client.utils.*; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.slf4j.Logger; import java.io.IOException; import java.io.StringReader; import java.net.HttpURLConnection; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Properties; -import java.util.Random; +import java.util.*; +import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; /** @@ -93,6 +86,8 @@ public class ServerListManager { public ServerListManager(String endpoint, String namespace) throws NacosException { isFixed = false; isStarted = false; + endpoint = initEndpoint(endpoint); + if (StringUtils.isBlank(endpoint)) { throw new NacosException(NacosException.CLIENT_INVALID_PARAM, "endpoint is blank"); } @@ -158,10 +153,8 @@ public class ServerListManager { } private void initParam(Properties properties) { - String endpointTmp = properties.getProperty(PropertyKeyConst.ENDPOINT); - if (!StringUtils.isBlank(endpointTmp)) { - endpoint = endpointTmp; - } + endpoint = initEndpoint(properties.getProperty(PropertyKeyConst.ENDPOINT)); + String contentPathTmp = properties.getProperty(PropertyKeyConst.CONTEXT_PATH); if (!StringUtils.isBlank(contentPathTmp)) { contentPath = contentPathTmp; @@ -172,6 +165,21 @@ public class ServerListManager { } } + private String initEndpoint(String endpointTmp) { + String endpointPortTmp = System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT); + if (StringUtils.isNotBlank(endpointPortTmp)) { + endpointPort = Integer.parseInt(endpointPortTmp); + } + + return TemplateUtils.stringBlankAndThenExecute(endpointTmp, new Callable() { + @Override + public String call() { + String endpointUrl = System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL); + return StringUtils.isNotBlank(endpointUrl) ? endpointUrl : ""; + } + }); + } + public synchronized void start() throws NacosException { if (isStarted || isFixed) { diff --git a/client/src/main/java/com/alibaba/nacos/client/identify/Constants.java b/client/src/main/java/com/alibaba/nacos/client/identify/Constants.java index 339103f0c..a94110720 100644 --- a/client/src/main/java/com/alibaba/nacos/client/identify/Constants.java +++ b/client/src/main/java/com/alibaba/nacos/client/identify/Constants.java @@ -25,6 +25,8 @@ public class Constants { public static final String SECRET_KEY = "secretKey"; + public static final String TENANT_ID = "tenantId"; + public static final String PROPERTIES_FILENAME = "spas.properties"; public static final String CREDENTIAL_PATH = "/home/admin/.spas_key/"; @@ -37,10 +39,14 @@ public class Constants { public static final String DOCKER_SECRET_KEY = "env_spas_secretKey"; + public static final String DOCKER_TENANT_ID = "ebv_spas_tenantId"; + public static final String ENV_ACCESS_KEY = "spas_accessKey"; public static final String ENV_SECRET_KEY = "spas_secretKey"; + public static final String ENV_TENANT_ID = "tenant.id"; + public static final String NO_APP_NAME = ""; } diff --git a/client/src/main/java/com/alibaba/nacos/client/identify/CredentialWatcher.java b/client/src/main/java/com/alibaba/nacos/client/identify/CredentialWatcher.java index 4aa493676..47c39b6e3 100644 --- a/client/src/main/java/com/alibaba/nacos/client/identify/CredentialWatcher.java +++ b/client/src/main/java/com/alibaba/nacos/client/identify/CredentialWatcher.java @@ -19,11 +19,7 @@ import com.alibaba.nacos.client.utils.LogUtils; import com.alibaba.nacos.client.utils.StringUtils; import org.slf4j.Logger; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.net.URL; import java.util.Properties; import java.util.Timer; @@ -144,6 +140,7 @@ public class CredentialWatcher { String accessKey = null; String secretKey = null; + String tenantId = null; if (propertiesIS == null) { propertyPath = null; accessKey = System.getenv(Constants.ENV_ACCESS_KEY); @@ -183,6 +180,9 @@ public class CredentialWatcher { if (properties.containsKey(Constants.SECRET_KEY)) { secretKey = properties.getProperty(Constants.SECRET_KEY); } + if (properties.containsKey(Constants.TENANT_ID)) { + tenantId = properties.getProperty(Constants.TENANT_ID); + } } else { if (properties.containsKey(Constants.DOCKER_ACCESS_KEY)) { accessKey = properties.getProperty(Constants.DOCKER_ACCESS_KEY); @@ -190,6 +190,10 @@ public class CredentialWatcher { if (properties.containsKey(Constants.DOCKER_SECRET_KEY)) { secretKey = properties.getProperty(Constants.DOCKER_SECRET_KEY); } + + if (properties.containsKey(Constants.DOCKER_TENANT_ID)) { + tenantId = properties.getProperty(Constants.DOCKER_TENANT_ID); + } } } @@ -200,7 +204,11 @@ public class CredentialWatcher { secretKey = secretKey.trim(); } - Credentials credential = new Credentials(accessKey, secretKey); + if (tenantId != null) { + tenantId = tenantId.trim(); + } + + Credentials credential = new Credentials(accessKey, secretKey, tenantId); if (!credential.valid()) { SpasLogger.warn("[1] Credential file missing required property {} Credential file missing {} or {}", appName, Constants.ACCESS_KEY, Constants.SECRET_KEY); diff --git a/client/src/main/java/com/alibaba/nacos/client/identify/Credentials.java b/client/src/main/java/com/alibaba/nacos/client/identify/Credentials.java index a271561da..36f698c95 100644 --- a/client/src/main/java/com/alibaba/nacos/client/identify/Credentials.java +++ b/client/src/main/java/com/alibaba/nacos/client/identify/Credentials.java @@ -26,13 +26,16 @@ public class Credentials implements SpasCredential { private volatile String secretKey; - public Credentials(String accessKey, String secretKey) { + private volatile String tenantId; + + public Credentials(String accessKey, String secretKey, String tenantId) { this.accessKey = accessKey; this.secretKey = secretKey; + this.tenantId = tenantId; } public Credentials() { - this(null, null); + this(null, null, null); } public String getAccessKey() { @@ -51,16 +54,24 @@ public class Credentials implements SpasCredential { this.secretKey = secretKey; } + public String getTenantId() { + return tenantId; + } + + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + public boolean valid() { - return accessKey != null && !accessKey.isEmpty() && secretKey != null && !secretKey.isEmpty(); + return accessKey != null && !accessKey.isEmpty() && secretKey != null + && !secretKey.isEmpty(); } public boolean identical(Credentials other) { - return this == other || - (other != null && - (accessKey == null && other.accessKey == null || accessKey != null && accessKey.equals(other.accessKey)) - && - (secretKey == null && other.secretKey == null || secretKey != null && secretKey.equals( - other.secretKey))); + return this == other || (other != null + && (accessKey == null && other.accessKey == null + || accessKey != null && accessKey.equals(other.accessKey)) + && (secretKey == null && other.secretKey == null + || secretKey != null && secretKey.equals(other.secretKey))); } } diff --git a/client/src/main/java/com/alibaba/nacos/client/logging/log4j2/Log4J2NacosLogging.java b/client/src/main/java/com/alibaba/nacos/client/logging/log4j2/Log4J2NacosLogging.java index 0fd9574eb..c901d07f3 100644 --- a/client/src/main/java/com/alibaba/nacos/client/logging/log4j2/Log4J2NacosLogging.java +++ b/client/src/main/java/com/alibaba/nacos/client/logging/log4j2/Log4J2NacosLogging.java @@ -26,16 +26,22 @@ import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.composite.CompositeConfiguration; +import org.apache.logging.log4j.core.lookup.Interpolator; +import org.apache.logging.log4j.core.lookup.StrSubstitutor; +import org.apache.logging.log4j.util.PropertiesUtil; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import static org.apache.logging.log4j.core.config.ConfigurationFactory.CONFIGURATION_FILE_PROPERTY; + /** * Support for Log4j version 2.7 or higher * @@ -52,6 +58,8 @@ public class Log4J2NacosLogging extends AbstractNacosLogging { private static final String JSON_PARSER_CLASS_NAME = "com.fasterxml.jackson.databind.ObjectMapper"; + private final StrSubstitutor strSubstitutor = new StrSubstitutor(new Interpolator()); + private Set locationList = new HashSet(); public Log4J2NacosLogging() { @@ -63,9 +71,13 @@ public class Log4J2NacosLogging extends AbstractNacosLogging { @Override public void loadConfiguration() { - String config = findConfig(getCurrentlySupportedConfigLocations()); - if (config != null) { - locationList.add(config); + if (locationList.isEmpty()) { + return; + } + + List configList = findConfig(getCurrentlySupportedConfigLocations()); + if (configList != null) { + locationList.addAll(configList); } final List configurations = new ArrayList(); @@ -112,22 +124,35 @@ public class Log4J2NacosLogging extends AbstractNacosLogging { List supportedConfigLocations = new ArrayList(); if (ClassUtils.isPresent(YAML_PARSER_CLASS_NAME)) { - Collections.addAll(supportedConfigLocations, "log4j2.yaml", "log4j2.yml"); + Collections.addAll(supportedConfigLocations, "log4j2.yaml", "log4j2.yml", "log4j2-test.yaml", + "log4j2-test.yml"); } if (ClassUtils.isPresent(JSON_PARSER_CLASS_NAME)) { - Collections.addAll(supportedConfigLocations, "log4j2.json", "log4j2.jsn"); + Collections.addAll(supportedConfigLocations, "log4j2.json", "log4j2.jsn", "log4j2-test.json", + "log4j2-test.jsn"); } + supportedConfigLocations.add("log4j2.xml"); + supportedConfigLocations.add("log4j2-test.xml"); return supportedConfigLocations.toArray(new String[supportedConfigLocations.size()]); } - private String findConfig(String[] locations) { + private List findConfig(String[] locations) { + final String configLocationStr = this.strSubstitutor.replace(PropertiesUtil.getProperties() + .getStringProperty(CONFIGURATION_FILE_PROPERTY)); + + if (configLocationStr != null) { + return Arrays.asList(configLocationStr.split(",")); + } + for (String location : locations) { ClassLoader defaultClassLoader = ClassUtils.getDefaultClassLoader(); if (defaultClassLoader != null && defaultClassLoader.getResource(location) != null) { - return "classpath:" + location; + List list = new ArrayList(); + list.add("classpath:" + location); + return list; } } return null; diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java b/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java index 4d50e675f..19de1af60 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.client.naming; import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.SystemPropertyKeyConst; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.naming.NamingService; @@ -24,6 +25,7 @@ import com.alibaba.nacos.api.naming.pojo.Instance; import com.alibaba.nacos.api.naming.pojo.ListView; import com.alibaba.nacos.api.naming.pojo.ServiceInfo; import com.alibaba.nacos.api.selector.AbstractSelector; +import com.alibaba.nacos.client.identify.CredentialService; import com.alibaba.nacos.client.naming.beat.BeatInfo; import com.alibaba.nacos.client.naming.beat.BeatReactor; import com.alibaba.nacos.client.naming.core.Balancer; @@ -33,6 +35,8 @@ import com.alibaba.nacos.client.naming.net.NamingProxy; import com.alibaba.nacos.client.naming.utils.CollectionUtils; import com.alibaba.nacos.client.naming.utils.StringUtils; import com.alibaba.nacos.client.naming.utils.UtilAndComs; +import com.alibaba.nacos.client.utils.LogUtils; +import com.alibaba.nacos.client.utils.TemplateUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.math.NumberUtils; @@ -40,13 +44,13 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; +import java.util.concurrent.Callable; /** * @author nkorange */ @SuppressWarnings("PMD.ServiceOrDaoClassShouldEndWithImplRule") public class NacosNamingService implements NamingService { - /** * Each Naming instance should have different namespace. */ @@ -68,74 +72,179 @@ public class NacosNamingService implements NamingService { private NamingProxy serverProxy; - private void init() { + public NacosNamingService(String serverList) { + Properties properties = new Properties(); + properties.setProperty(PropertyKeyConst.SERVER_ADDR, serverList); - namespace = System.getProperty(PropertyKeyConst.NAMESPACE); + init(properties); + } - if (StringUtils.isEmpty(namespace)) { - namespace = UtilAndComs.DEFAULT_NAMESPACE_ID; + public NacosNamingService(Properties properties) { + + init(properties); + } + + private void init(Properties properties) { + + serverList = properties.getProperty(PropertyKeyConst.SERVER_ADDR); + + initNamespace(properties); + initEndpoint(properties); + initWebRootContext(); + initCacheDir(); + initLogName(properties); + + eventDispatcher = new EventDispatcher(); + serverProxy = new NamingProxy(namespace, endpoint, serverList); + serverProxy.setProperties(properties); + beatReactor = new BeatReactor(serverProxy, initClientBeatThreadCount(properties)); + hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir, isLoadCacheAtStart(properties), initPollingThreadCount(properties)); + } + + private int initClientBeatThreadCount(Properties properties) { + if (properties == null) { + + return UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT; } + int clientBeatThreadCount = NumberUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_CLIENT_BEAT_THREAD_COUNT), + UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT); + + return clientBeatThreadCount; + } + + private int initPollingThreadCount(Properties properties) { + if (properties == null) { + + return UtilAndComs.DEFAULT_POLLING_THREAD_COUNT; + } + + int pollingThreadCount = NumberUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_POLLING_THREAD_COUNT), + UtilAndComs.DEFAULT_POLLING_THREAD_COUNT); + + return pollingThreadCount; + } + + private boolean isLoadCacheAtStart(Properties properties) { + boolean loadCacheAtStart = false; + if (properties != null && StringUtils.isNotEmpty(properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START))) { + loadCacheAtStart = BooleanUtils.toBoolean( + properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START)); + } + + return loadCacheAtStart; + } + + private void initLogName(Properties properties) { logName = System.getProperty(UtilAndComs.NACOS_NAMING_LOG_NAME); if (StringUtils.isEmpty(logName)) { - logName = "naming.log"; - } + if (properties != null && StringUtils.isNotEmpty(properties.getProperty(UtilAndComs.NACOS_NAMING_LOG_NAME))) { + logName = properties.getProperty(UtilAndComs.NACOS_NAMING_LOG_NAME); + } else { + logName = "naming.log"; + } + } + } + + private void initCacheDir() { cacheDir = System.getProperty("com.alibaba.nacos.naming.cache.dir"); if (StringUtils.isEmpty(cacheDir)) { cacheDir = System.getProperty("user.home") + "/nacos/naming/" + namespace; } } - public NacosNamingService(String serverList) { + private void initEndpoint(Properties properties) { + if (properties == null) { - this.serverList = serverList; - init(); - eventDispatcher = new EventDispatcher(); - serverProxy = new NamingProxy(namespace, endpoint, serverList); - beatReactor = new BeatReactor(serverProxy); - hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir); + return; + } + + String endpointUrl = TemplateUtils.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.ENDPOINT), new Callable() { + @Override + public String call() { + return System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL); + } + }); + + if (com.alibaba.nacos.client.utils.StringUtils.isNotBlank(endpointUrl)) { + return; + } + + String endpointPort = TemplateUtils.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.ENDPOINT_PORT), new Callable() { + @Override + public String call() { + + return System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT); + } + }); + endpointPort = TemplateUtils.stringEmptyAndThenExecute(endpointPort, new Callable() { + @Override + public String call() { + return "8080"; + } + }); + + endpoint = endpointUrl + ":" + endpointPort; } - public NacosNamingService(Properties properties) { + private void initNamespace(Properties properties) { + String tmpNamespace = null; - init(); - - serverList = properties.getProperty(PropertyKeyConst.SERVER_ADDR); - - if (StringUtils.isNotEmpty(properties.getProperty(PropertyKeyConst.NAMESPACE))) { - namespace = properties.getProperty(PropertyKeyConst.NAMESPACE); + if (properties != null) { + tmpNamespace = properties.getProperty(PropertyKeyConst.NAMESPACE); } - if (StringUtils.isNotEmpty(properties.getProperty(UtilAndComs.NACOS_NAMING_LOG_NAME))) { - logName = properties.getProperty(UtilAndComs.NACOS_NAMING_LOG_NAME); - } + tmpNamespace = TemplateUtils.stringEmptyAndThenExecute(tmpNamespace, new Callable() { + @Override + public String call() { + String namespace = System.getProperty(PropertyKeyConst.NAMESPACE); + LogUtils.NAMING_LOGGER.info("initializer namespace from System Property :" + namespace); + return namespace; + } + }); - if (StringUtils.isNotEmpty(properties.getProperty(PropertyKeyConst.ENDPOINT))) { - endpoint = properties.getProperty(PropertyKeyConst.ENDPOINT) + ":" + - properties.getProperty("address.server.port", "8080"); - } - cacheDir = System.getProperty("user.home") + "/nacos/naming/" + namespace; + tmpNamespace = TemplateUtils.stringEmptyAndThenExecute(tmpNamespace, new Callable() { + @Override + public String call() { + String namespace = System.getenv(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_NAMESPACE); + LogUtils.NAMING_LOGGER.info("initializer namespace from System Environment :" + namespace); + return namespace; + } + }); - boolean loadCacheAtStart = false; - if (StringUtils.isNotEmpty(properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START))) { - loadCacheAtStart = BooleanUtils.toBoolean( - properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START)); - } + tmpNamespace = TemplateUtils.stringEmptyAndThenExecute(tmpNamespace, new Callable() { + @Override + public String call() { + String namespace = CredentialService.getInstance().getCredential().getTenantId(); + LogUtils.NAMING_LOGGER.info("initializer namespace from Credential Module " + namespace); + return namespace; + } + }); - int clientBeatThreadCount = NumberUtils.toInt( - properties.getProperty(PropertyKeyConst.NAMING_CLIENT_BEAT_THREAD_COUNT), - UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT); + tmpNamespace = TemplateUtils.stringEmptyAndThenExecute(tmpNamespace, new Callable() { + @Override + public String call() { + return UtilAndComs.DEFAULT_NAMESPACE_ID; + } + }); + namespace = tmpNamespace; + } - int pollingThreadCount = NumberUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_POLLING_THREAD_COUNT), - UtilAndComs.DEFAULT_POLLING_THREAD_COUNT); - - eventDispatcher = new EventDispatcher(); - serverProxy = new NamingProxy(namespace, endpoint, serverList); - beatReactor = new BeatReactor(serverProxy, clientBeatThreadCount); - hostReactor = new HostReactor(eventDispatcher, serverProxy, cacheDir, loadCacheAtStart, pollingThreadCount); + private void initWebRootContext() { + // support the web context with ali-yun if the app deploy by EDAS + final String webContext = System.getProperty(SystemPropertyKeyConst.NAMING_WEB_CONTEXT); + TemplateUtils.stringNotEmptyAndThenExecute(webContext, new Runnable() { + @Override + public void run() { + UtilAndComs.WEB_CONTEXT = webContext.indexOf("/") > -1 ? webContext + : "/" + webContext; + UtilAndComs.NACOS_URL_BASE = UtilAndComs.WEB_CONTEXT + "/v1/ns"; + UtilAndComs.NACOS_URL_INSTANCE = UtilAndComs.NACOS_URL_BASE + "/instance"; + } + }); } @Override diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/net/HttpClient.java b/client/src/main/java/com/alibaba/nacos/client/naming/net/HttpClient.java index c11e24a23..8a761852f 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/net/HttpClient.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/net/HttpClient.java @@ -30,16 +30,22 @@ import java.net.URLEncoder; import java.util.*; import java.util.zip.GZIPInputStream; -import static com.alibaba.nacos.client.utils.LogUtils.*; +import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER; /** * @author nkorange */ public class HttpClient { - public static final int TIME_OUT_MILLIS = Integer.getInteger("com.alibaba.nacos.client.naming.ctimeout", 50000); - public static final int CON_TIME_OUT_MILLIS = Integer.getInteger("com.alibaba.nacos.client.naming.ctimeout", 3000); - private static final boolean ENABLE_HTTPS = Boolean.getBoolean("com.alibaba.nacos.client.naming.tls.enable"); + public static final int TIME_OUT_MILLIS = Integer + .getInteger("com.alibaba.nacos.client.naming.ctimeout", 50000); + public static final int CON_TIME_OUT_MILLIS = Integer + .getInteger("com.alibaba.nacos.client.naming.ctimeout", 3000); + private static final boolean ENABLE_HTTPS = Boolean + .getBoolean("com.alibaba.nacos.client.naming.tls.enable"); + + private static final String POST = "POST"; + private static final String PUT = "PUT"; static { // limit max redirection @@ -67,10 +73,19 @@ public class HttpClient { conn = (HttpURLConnection) new URL(url).openConnection(); + setHeaders(conn, headers, encoding); conn.setConnectTimeout(CON_TIME_OUT_MILLIS); conn.setReadTimeout(TIME_OUT_MILLIS); conn.setRequestMethod(method); - setHeaders(conn, headers, encoding); + conn.setDoOutput(true); + if (POST.equals(method) || PUT.equals(method)) { + // fix: apache http nio framework must set some content to request body + byte[] b = encodedContent.getBytes(); + conn.setRequestProperty("Content-Length", String.valueOf(b.length)); + conn.getOutputStream().write(b, 0, b.length); + conn.getOutputStream().flush(); + conn.getOutputStream().close(); + } conn.connect(); NAMING_LOGGER.debug("Request from server: " + url); return getResult(conn); @@ -78,7 +93,7 @@ public class HttpClient { try { if (conn != null) { NAMING_LOGGER.warn("failed to request " + conn.getURL() + " from " - + InetAddress.getByName(conn.getURL().getHost()).getHostAddress()); + + InetAddress.getByName(conn.getURL().getHost()).getHostAddress()); } } catch (Exception e1) { NAMING_LOGGER.error("[NA] failed to request ", e1); @@ -159,11 +174,13 @@ public class HttpClient { private static String encodingParams(Map params, String encoding) throws UnsupportedEncodingException { StringBuilder sb = new StringBuilder(); + throws UnsupportedEncodingException { if (null == params || params.isEmpty()) { return null; } params.put("encoding", encoding); + StringBuilder sb = new StringBuilder(); for (Map.Entry entry : params.entrySet()) { if (StringUtils.isEmpty(entry.getValue())) { @@ -175,6 +192,9 @@ public class HttpClient { sb.append("&"); } + if (sb.length() > 0) { + sb = sb.deleteCharAt(sb.length() - 1); + } return sb.toString(); } diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/net/NamingProxy.java b/client/src/main/java/com/alibaba/nacos/client/naming/net/NamingProxy.java index 2f14dc127..e57e5cc34 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/net/NamingProxy.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/net/NamingProxy.java @@ -18,6 +18,9 @@ package com.alibaba.nacos.client.naming.net; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; +import com.alibaba.nacos.api.PropertyKeyConst; +import com.alibaba.nacos.api.SystemPropertyKeyConst; +import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.naming.CommonParams; import com.alibaba.nacos.api.naming.pojo.Instance; @@ -25,9 +28,12 @@ import com.alibaba.nacos.api.naming.pojo.ListView; import com.alibaba.nacos.api.selector.AbstractSelector; import com.alibaba.nacos.api.selector.ExpressionSelector; import com.alibaba.nacos.api.selector.SelectorType; +import com.alibaba.nacos.client.config.impl.SpasAdapter; import com.alibaba.nacos.client.monitor.MetricsMonitor; import com.alibaba.nacos.client.naming.beat.BeatInfo; import com.alibaba.nacos.client.naming.utils.*; +import com.alibaba.nacos.client.naming.utils.*; +import com.alibaba.nacos.client.utils.TemplateUtils; import com.alibaba.nacos.common.util.HttpMethod; import com.alibaba.nacos.common.util.UuidUtils; @@ -49,6 +55,8 @@ public class NamingProxy { private static final int DEFAULT_SERVER_PORT = 8848; + private int serverPort = DEFAULT_SERVER_PORT; + private String namespaceId; private String endpoint; @@ -63,7 +71,7 @@ public class NamingProxy { private long vipSrvRefInterMillis = TimeUnit.SECONDS.toMillis(30); - private ScheduledExecutorService executorService; + private Properties properties; public NamingProxy(String namespaceId, String endpoint, String serverList) { @@ -76,7 +84,15 @@ public class NamingProxy { } } - executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() { + initRefreshSrvIfNeed(); + } + + private void initRefreshSrvIfNeed() { + if (StringUtils.isEmpty(endpoint)) { + return; + } + + ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); @@ -106,6 +122,7 @@ public class NamingProxy { "Accept-Encoding", "gzip,deflate,sdch", "Connection", "Keep-Alive", "RequestId", UuidUtils.generateUuid()); + List headers = builderHeaders(); HttpClient.HttpResult result = HttpClient.httpGet(urlString, headers, null, UtilAndComs.ENCODING); if (HttpURLConnection.HTTP_OK != result.code) { @@ -305,17 +322,19 @@ public class NamingProxy { throws NacosException { long start = System.currentTimeMillis(); long end = 0; + checkSignature(params); List headers = Arrays.asList("Client-Version", UtilAndComs.VERSION, "User-Agent", UtilAndComs.VERSION, "Accept-Encoding", "gzip,deflate,sdch", "Connection", "Keep-Alive", "RequestId", UuidUtils.generateUuid()); + List headers = builderHeaders(); String url; if (!curServer.contains(UtilAndComs.SERVER_ADDR_IP_SPLITER)) { - curServer = curServer + UtilAndComs.SERVER_ADDR_IP_SPLITER + DEFAULT_SERVER_PORT; + curServer = curServer + UtilAndComs.SERVER_ADDR_IP_SPLITER + serverPort; } url = HttpClient.getPrefix() + curServer + api; @@ -384,8 +403,86 @@ public class NamingProxy { } + private void checkSignature(Map params) { + String ak = getAccessKey(); + String sk = getSecretKey(); + if (StringUtils.isEmpty(ak) && StringUtils.isEmpty(sk)) { + return; + } + + try { + String app = System.getProperty("project.name"); + String signData = getSignData(params.get("serviceName")); + String signature = SignUtil.sign(signData, sk); + params.put("signature", signature); + params.put("data", signData); + params.put("ak", ak); + params.put("app", app); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public List builderHeaders() { + List headers = Arrays.asList("Client-Version", UtilAndComs.VERSION, + "Accept-Encoding", "gzip,deflate,sdch", + "Connection", "Keep-Alive", + "RequestId", UuidUtils.generateUuid(), "Request-Module", "Naming"); + return headers; + } + + private static String getSignData(String serviceName) { + return StringUtils.isNotEmpty(serviceName) + ? System.currentTimeMillis() + "@@" + serviceName + : String.valueOf(System.currentTimeMillis()); + } + + public String getAccessKey() { + if (properties == null) { + + return SpasAdapter.getAk(); + } + + return TemplateUtils.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.ACCESS_KEY), new Callable() { + + @Override + public String call() { + return SpasAdapter.getAk(); + } + }); + } + + public String getSecretKey() { + if (properties == null) { + + return SpasAdapter.getSk(); + } + + return TemplateUtils.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.SECRET_KEY), new Callable() { + @Override + public String call() throws Exception { + return SpasAdapter.getSk(); + } + }); + } + + public void setProperties(Properties properties) { + this.properties = properties; + setServerPort(DEFAULT_SERVER_PORT); + } + public String getNamespaceId() { return namespaceId; } + + public void setServerPort(int serverPort) { + this.serverPort = serverPort; + + String sp = System.getProperty(SystemPropertyKeyConst.NAMING_SERVER_PORT); + if (com.alibaba.nacos.client.utils.StringUtils.isNotBlank(sp)) { + this.serverPort = Integer.parseInt(sp); + } + } + } diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/utils/SignUtil.java b/client/src/main/java/com/alibaba/nacos/client/naming/utils/SignUtil.java new file mode 100644 index 000000000..e77f6929a --- /dev/null +++ b/client/src/main/java/com/alibaba/nacos/client/naming/utils/SignUtil.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * 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.client.naming.utils; + +import com.alibaba.nacos.client.identify.Base64; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.Charset; + +/** + * @author pbting + * @date 2019-01-22 10:20 PM + */ +public class SignUtil { + public static final Charset UTF8 = Charset.forName("UTF-8"); + + public SignUtil() { + } + + public static String sign(String data, String key) throws Exception { + try { + byte[] signature = sign(data.getBytes(UTF8), key.getBytes(UTF8), + SignUtil.SigningAlgorithm.HmacSHA1); + return new String(Base64.encodeBase64(signature)); + } catch (Exception var3) { + throw new Exception( + "Unable to calculate a request signature: " + var3.getMessage(), + var3); + } + } + + private static byte[] sign(byte[] data, byte[] key, + SignUtil.SigningAlgorithm algorithm) throws Exception { + try { + Mac mac = Mac.getInstance(algorithm.toString()); + mac.init(new SecretKeySpec(key, algorithm.toString())); + return mac.doFinal(data); + } catch (Exception var4) { + throw new Exception( + "Unable to calculate a request signature: " + var4.getMessage(), + var4); + } + } + + public enum SigningAlgorithm { + // Hmac SHA1 algorithm + HmacSHA1; + + SigningAlgorithm() { + } + } +} diff --git a/client/src/main/java/com/alibaba/nacos/client/naming/utils/UtilAndComs.java b/client/src/main/java/com/alibaba/nacos/client/naming/utils/UtilAndComs.java index 1a1142ef0..3035b0e00 100644 --- a/client/src/main/java/com/alibaba/nacos/client/naming/utils/UtilAndComs.java +++ b/client/src/main/java/com/alibaba/nacos/client/naming/utils/UtilAndComs.java @@ -22,6 +22,12 @@ public class UtilAndComs { public static final String VERSION = "Nacos-Java-Client:v1.0.0"; + public static String WEB_CONTEXT = "/nacos"; + + public static String NACOS_URL_BASE = WEB_CONTEXT + "/v1/ns"; + + public static String NACOS_URL_INSTANCE = NACOS_URL_BASE + "/instance"; + public static final String ENCODING = "UTF-8"; public static final String ENV_LIST_KEY = "envList"; @@ -30,10 +36,6 @@ public class UtilAndComs { public static final String FAILOVER_SWITCH = "00-00---000-VIPSRV_FAILOVER_SWITCH-000---00-00"; - public static final String NACOS_URL_BASE = "/nacos/v1/ns"; - - public static final String NACOS_URL_INSTANCE = NACOS_URL_BASE + "/instance"; - public static final String DEFAULT_NAMESPACE_ID = "public"; public static final int REQUEST_DOMAIN_RETRY_COUNT = 3; @@ -44,9 +46,11 @@ public class UtilAndComs { public static final String SERVER_ADDR_IP_SPLITER = ":"; - public static final int DEFAULT_CLIENT_BEAT_THREAD_COUNT = Runtime.getRuntime().availableProcessors() > 1 ? - Runtime.getRuntime().availableProcessors() / 2 : 1; + public static final int DEFAULT_CLIENT_BEAT_THREAD_COUNT = Runtime.getRuntime() + .availableProcessors() > 1 ? Runtime.getRuntime().availableProcessors() / 2 + : 1; - public static final int DEFAULT_POLLING_THREAD_COUNT = Runtime.getRuntime().availableProcessors() > 1 ? - Runtime.getRuntime().availableProcessors() / 2 : 1; + public static final int DEFAULT_POLLING_THREAD_COUNT = Runtime.getRuntime() + .availableProcessors() > 1 ? Runtime.getRuntime().availableProcessors() / 2 + : 1; } diff --git a/client/src/main/java/com/alibaba/nacos/client/utils/StringUtils.java b/client/src/main/java/com/alibaba/nacos/client/utils/StringUtils.java index b59a49cdc..0e4e1ec4e 100644 --- a/client/src/main/java/com/alibaba/nacos/client/utils/StringUtils.java +++ b/client/src/main/java/com/alibaba/nacos/client/utils/StringUtils.java @@ -37,6 +37,11 @@ public class StringUtils { return true; } + public static boolean isNotBlank(String str) { + + return !isBlank(str); + } + public static boolean isNotEmpty(String str) { return !StringUtils.isEmpty(str); } diff --git a/client/src/main/java/com/alibaba/nacos/client/utils/TemplateUtils.java b/client/src/main/java/com/alibaba/nacos/client/utils/TemplateUtils.java new file mode 100644 index 000000000..7e2384473 --- /dev/null +++ b/client/src/main/java/com/alibaba/nacos/client/utils/TemplateUtils.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2019 the original author or authors. + * + * 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.client.utils; + +import java.util.concurrent.Callable; + +/** + * @author pbting + * @date 2019-03-04 1:31 PM + */ +public class TemplateUtils { + + public static final void stringNotEmptyAndThenExecute(String source, Runnable runnable) { + + if (StringUtils.isNotEmpty(source)) { + + try { + runnable.run(); + } catch (Exception e) { + LogUtils.NAMING_LOGGER.error("string empty and then execute cause an exception.", e); + } + } + } + + public static final String stringEmptyAndThenExecute(String source, Callable callable) { + + if (StringUtils.isEmpty(source)) { + + try { + return callable.call(); + } catch (Exception e) { + LogUtils.NAMING_LOGGER.error("string empty and then execute cause an exception.", e); + } + } + + return source.trim(); + } + + public static final String stringBlankAndThenExecute(String source, Callable callable) { + + if (StringUtils.isBlank(source)) { + + try { + return callable.call(); + } catch (Exception e) { + LogUtils.NAMING_LOGGER.error("string empty and then execute cause an exception.", e); + } + } + + return source.trim(); + } +} diff --git a/naming/pom.xml b/naming/pom.xml index 0f55ba330..374ce2ed4 100644 --- a/naming/pom.xml +++ b/naming/pom.xml @@ -204,9 +204,9 @@ src/main/resources - - - + + application.properties +