[SCB-2081]add ssl support
diff --git a/clients/http-client-common/pom.xml b/clients/http-client-common/pom.xml
index b585b1a..4f4ff52 100644
--- a/clients/http-client-common/pom.xml
+++ b/clients/http-client-common/pom.xml
@@ -58,6 +58,11 @@
     </dependency>
 
     <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>foundation-ssl</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <scope>test</scope>
diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpConfiguration.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpConfiguration.java
new file mode 100644
index 0000000..59b6b4c
--- /dev/null
+++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpConfiguration.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.servicecomb.http.client.common;
+
+import org.apache.servicecomb.foundation.ssl.SSLCustom;
+import org.apache.servicecomb.foundation.ssl.SSLOption;
+
+public interface HttpConfiguration {
+  class SSLProperties {
+    private boolean enabled;
+
+    private SSLOption sslOption;
+
+    private SSLCustom sslCustom;
+
+    public boolean isEnabled() {
+      return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+      this.enabled = enabled;
+    }
+
+    public SSLOption getSslOption() {
+      return sslOption;
+    }
+
+    public void setSslOption(SSLOption sslOption) {
+      this.sslOption = sslOption;
+    }
+
+    public SSLCustom getSslCustom() {
+      return sslCustom;
+    }
+
+    public void setSslCustom(SSLCustom sslCustom) {
+      this.sslCustom = sslCustom;
+    }
+  }
+}
diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportFactory.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportFactory.java
index a3a61f4..3fa5f73 100644
--- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportFactory.java
+++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportFactory.java
@@ -17,14 +17,61 @@
 
 package org.apache.servicecomb.http.client.common;
 
-public class HttpTransportFactory {
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.servicecomb.foundation.ssl.SSLManager;
 
-  private static final HttpTransport httpTransport = new HttpTransportImpl();
+public class HttpTransportFactory {
+  // All parameters set to 5 seconds now.
+  public static final int CONNECT_TIMEOUT = 5000;
+
+  public static final int CONNECTION_REQUEST_TIMEOUT = 5000;
+
+  public static final int SOCKET_TIMEOUT = 5000;
+
+  public static final int MAX_TOTAL = 100;
+
+  public static final int DEFAULT_MAX_PER_ROUTE = 10;
 
   private HttpTransportFactory() {
   }
 
-  public static HttpTransport getDefaultHttpTransport() {
-    return httpTransport;
+  public static HttpTransport createHttpTransport(HttpConfiguration.SSLProperties sslProperties) {
+    RequestConfig config = RequestConfig.custom()
+        .setConnectTimeout(CONNECT_TIMEOUT)
+        .setConnectionRequestTimeout(
+            CONNECTION_REQUEST_TIMEOUT)
+        .setSocketTimeout(SOCKET_TIMEOUT).build();
+
+    //register http/https socket factory
+    RegistryBuilder<ConnectionSocketFactory> builder = RegistryBuilder.<ConnectionSocketFactory>create();
+    builder.register("http", PlainConnectionSocketFactory.INSTANCE);
+    if (sslProperties.isEnabled()) {
+      builder.register("https",
+          new SSLConnectionSocketFactory(
+              SSLManager.createSSLContext(sslProperties.getSslOption(), sslProperties.getSslCustom()),
+              NoopHostnameVerifier.INSTANCE));
+    }
+    Registry<ConnectionSocketFactory> connectionSocketFactoryRegistry = builder.build();
+
+    //connection pool management
+    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(
+        connectionSocketFactoryRegistry);
+    connectionManager.setMaxTotal(MAX_TOTAL);
+    connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
+
+    HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().
+        setDefaultRequestConfig(config).
+        setConnectionManager(connectionManager).
+        disableCookieManagement();
+
+    return new HttpTransportImpl(httpClientBuilder.build());
   }
 }
diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportImpl.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportImpl.java
index b205234..06f714d 100644
--- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportImpl.java
+++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportImpl.java
@@ -21,7 +21,6 @@
 import java.util.Map;
 
 import org.apache.http.client.HttpClient;
-import org.apache.http.impl.client.HttpClients;
 import org.apache.http.util.EntityUtils;
 
 /**
@@ -33,12 +32,12 @@
 
   private static final String HEADER_USER_AGENT = "User-Agent";
 
-  protected HttpClient httpClient;
+  private HttpClient httpClient;
 
   private Map<String, String> globalHeaders;
 
-  public HttpTransportImpl() {
-    httpClient = HttpClients.createDefault();
+  public HttpTransportImpl(HttpClient httpClient) {
+    this.httpClient = httpClient;
   }
 
   public HttpClient getHttpClient() {
diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/TLSConfig.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/TLSConfig.java
deleted file mode 100644
index 054b563..0000000
--- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/TLSConfig.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.servicecomb.http.client.common;
-
-public class TLSConfig {
-
-  private KeyStoreInstanceType keyStoreType;
-
-  //trust certificate
-  private String trustStore;
-
-  //trust certificate password
-  private String trustStoreValue;
-
-  //identity certificate
-  private String keyStore;
-
-  //identity certificate password
-  private String keyStoreValue;
-
-  public TLSConfig() {
-
-  }
-
-  public TLSConfig(KeyStoreInstanceType keyStoreType, String trustStore, String trustStoreValue, String keyStore,
-      String keyStoreValue) {
-    this.keyStoreType = keyStoreType;
-    this.trustStore = trustStore;
-    this.trustStoreValue = trustStoreValue;
-    this.keyStore = keyStore;
-    this.keyStoreValue = keyStoreValue;
-  }
-
-  public KeyStoreInstanceType getKeyStoreType() {
-    return keyStoreType;
-  }
-
-  public void setKeyStoreType(KeyStoreInstanceType keyStoreType) {
-    this.keyStoreType = keyStoreType;
-  }
-
-  public String getTrustStore() {
-    return trustStore;
-  }
-
-  public void setTrustStore(String trustStore) {
-    this.trustStore = trustStore;
-  }
-
-  public String getTrustStoreValue() {
-    return trustStoreValue;
-  }
-
-  public void setTrustStoreValue(String trustStoreValue) {
-    this.trustStoreValue = trustStoreValue;
-  }
-
-  public String getKeyStore() {
-    return keyStore;
-  }
-
-  public void setKeyStore(String keyStore) {
-    this.keyStore = keyStore;
-  }
-
-  public String getKeyStoreValue() {
-    return keyStoreValue;
-  }
-
-  public void setKeyStoreValue(String keyStoreValue) {
-    this.keyStoreValue = keyStoreValue;
-  }
-
-  //keyStore type
-  public enum KeyStoreInstanceType {
-    JKS,
-    JCEKS,
-    PKCS12,
-    PKCS11,
-    DKS
-  }
-}
diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/TLSHttpsTransport.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/TLSHttpsTransport.java
deleted file mode 100644
index d544662..0000000
--- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/TLSHttpsTransport.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.servicecomb.http.client.common;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.config.Registry;
-import org.apache.http.config.RegistryBuilder;
-import org.apache.http.conn.socket.ConnectionSocketFactory;
-import org.apache.http.conn.socket.PlainConnectionSocketFactory;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
-import org.apache.http.ssl.SSLContexts;
-
-/**
- * Created by   on 2019/10/31.
- */
-public class TLSHttpsTransport extends HttpTransportImpl {
-
-  private static final int DEFAULT_MAX_CONNECTIONS = 1000;
-
-  private static final int DEFAULT_MAX_PER_ROUTE = 500;
-
-  private static final int DEFAULT_REQUEST_TIMEOUT = 5000;
-
-  private static final int DEFAULT_CONNECTION_TIMEOUT = 5000;
-
-  public TLSHttpsTransport() {
-
-  }
-
-  /**
-   * configure the certificate to httpClient
-   * @param tlsConfig
-   */
-  public TLSHttpsTransport(TLSConfig tlsConfig) {
-
-    // create keyStore and trustStore
-    KeyStore keyStore = getKeyStore(tlsConfig.getKeyStore(), tlsConfig.getKeyStoreType().name(),
-        tlsConfig.getKeyStoreValue());
-    KeyStore trustStore = getKeyStore(tlsConfig.getTrustStore(), TLSConfig.KeyStoreInstanceType.JKS.name(),
-        tlsConfig.getTrustStoreValue());
-
-    // initialize SSLContext
-    SSLContext sslContext = getSSLContext(keyStore, tlsConfig.getKeyStoreValue(), trustStore);
-
-    assert sslContext != null;
-    //register http/https socket factory
-    Registry<ConnectionSocketFactory> connectionSocketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
-        .register("http", PlainConnectionSocketFactory.INSTANCE)
-        .register("https", new SSLConnectionSocketFactory(sslContext))
-        .build();
-
-    //connection pool management
-    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(
-        connectionSocketFactoryRegistry);
-    connectionManager.setMaxTotal(DEFAULT_MAX_CONNECTIONS);
-    connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
-
-    //request parameter configuration
-    RequestConfig config = RequestConfig.custom().
-        setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT).
-        setConnectionRequestTimeout(DEFAULT_CONNECTION_TIMEOUT).
-        setSocketTimeout(DEFAULT_REQUEST_TIMEOUT).
-        build();
-
-    // construct httpClient
-    HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().
-        setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext)).
-        setConnectionManager(connectionManager).
-        setDefaultRequestConfig(config);
-
-    this.httpClient = httpClientBuilder.build();
-  }
-
-  private KeyStore getKeyStore(String keyStorePath, String keyStoreType, String keyStoreValue) {
-    try {
-      KeyStore keyStore = KeyStore.getInstance(keyStoreType);
-      InputStream inputStream = new FileInputStream(keyStorePath);
-      keyStore.load(inputStream, keyStoreValue.toCharArray());
-      return keyStore;
-    } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
-      e.printStackTrace();
-    }
-    return null;
-  }
-
-  private SSLContext getSSLContext(KeyStore keyStore, String keyStoreValue, KeyStore trustStore) {
-    try {
-      KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
-      keyManagerFactory.init(keyStore, keyStoreValue.toCharArray());
-      KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
-
-      TrustManagerFactory trustManagerFactory = TrustManagerFactory
-          .getInstance(TrustManagerFactory.getDefaultAlgorithm());
-      trustManagerFactory.init(trustStore);
-      TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
-
-      SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(new TrustSelfSignedStrategy()).build();
-      sslContext.init(keyManagers, trustManagers, new SecureRandom());
-      return sslContext;
-    } catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
-      e.printStackTrace();
-    }
-    return null;
-  }
-}
diff --git a/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/HttpTransportImplTest.java b/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/HttpTransportImplTest.java
index e7fe921..b71aae8 100644
--- a/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/HttpTransportImplTest.java
+++ b/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/HttpTransportImplTest.java
@@ -50,8 +50,7 @@
 
     when(httpClient.execute(Mockito.any())).thenReturn(httpResponse);
 
-    HttpTransportImpl httpTransport = new HttpTransportImpl();
-    httpTransport.setHttpClient(httpClient);
+    HttpTransportImpl httpTransport = new HttpTransportImpl(httpClient);
     Map<String, String> extraHeaders = new HashMap<>();
     extraHeaders.put("test", "testContext");
     httpTransport.addHeaders(extraHeaders);
diff --git a/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/TLSHttpsTransportTest.java b/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/TLSHttpsTransportTest.java
deleted file mode 100644
index 185ac3d..0000000
--- a/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/TLSHttpsTransportTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.servicecomb.http.client.common;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * Created by   on 2019/10/31.
- */
-public class TLSHttpsTransportTest {
-
-  /**
-   * test TLS HttpTransport
-   */
-  @Test
-  public void TestTLSConfig() {
-
-    TLSConfig tlsConfig = new TLSConfig();
-
-    tlsConfig.setKeyStoreType(TLSConfig.KeyStoreInstanceType.PKCS12);
-    tlsConfig.setKeyStore(this.getClass().getResource("/tls/client.p12").getFile().toString());
-    tlsConfig.setKeyStoreValue("123456");
-
-    tlsConfig.setTrustStore(this.getClass().getResource("/tls/server.jks").getFile().toString());
-    tlsConfig.setTrustStoreValue("123456");
-
-    HttpTransport tlsHttpTransport = new TLSHttpsTransport(tlsConfig);
-
-    Assert.assertNotNull(tlsHttpTransport);
-  }
-}
diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AbstractTask.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AbstractTask.java
index 592db3c..a8ead0c 100644
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AbstractTask.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AbstractTask.java
@@ -82,4 +82,8 @@
       LOGGER.error("execute task rejected {}", task.getClass().getName(), e);
     }
   }
+
+  public void stop() {
+    this.taskPool.shutdownNow();
+  }
 }
diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AddressManager.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AddressManager.java
new file mode 100644
index 0000000..01f26f6
--- /dev/null
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AddressManager.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.servicecomb.service.center.client;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.servicecomb.http.client.common.HttpUtils;
+
+public class AddressManager {
+  private final String projectName;
+
+  private final List<String> addresses;
+
+  private int index;
+
+  public AddressManager(String projectName, List<String> addresses) {
+    this.projectName = projectName;
+    this.addresses = new ArrayList<>(addresses.size());
+    addresses.forEach((address -> this.addresses.add(formatAddress(address))));
+    this.index = new Random().nextInt(addresses.size());
+  }
+
+  private String formatAddress(String address) {
+    try {
+      return address + "/v4/" + HttpUtils.encodeURLParam(this.projectName);
+    } catch (Exception e) {
+      throw new IllegalStateException("not possible");
+    }
+  }
+
+  public String nextAddress() {
+    synchronized (this) {
+      this.index++;
+      if (this.index >= addresses.size()) {
+        this.index = 0;
+      }
+    }
+    return address();
+  }
+
+  public String address() {
+    synchronized (this) {
+      return addresses.get(index);
+    }
+  }
+}
diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterClient.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterClient.java
index 5c168f1..5fe6a4f 100755
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterClient.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterClient.java
@@ -26,12 +26,11 @@
 

 import org.apache.http.HttpStatus;

 import org.apache.http.client.utils.URIBuilder;

+import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties;

 import org.apache.servicecomb.http.client.common.HttpResponse;

 import org.apache.servicecomb.http.client.common.HttpTransport;

 import org.apache.servicecomb.http.client.common.HttpTransportFactory;

 import org.apache.servicecomb.http.client.common.HttpUtils;

-import org.apache.servicecomb.http.client.common.TLSConfig;

-import org.apache.servicecomb.http.client.common.TLSHttpsTransport;

 import org.apache.servicecomb.service.center.client.exception.OperationException;

 import org.apache.servicecomb.service.center.client.model.CreateMicroserviceInstanceRequest;

 import org.apache.servicecomb.service.center.client.model.CreateMicroserviceRequest;

@@ -60,76 +59,21 @@
 

   private ServiceCenterRawClient httpClient;

 

-  /**

-   * Use default config parameter

-   */

-  public ServiceCenterClient() {

-    this(new ServiceCenterRawClient());

+  public ServiceCenterClient(ServiceCenterRawClient httpClient) {

+    this.httpClient = httpClient;

   }

 

-  /**

-   * Add TLS config of client

-   * @param tlsConfig

-   */

-  public ServiceCenterClient(TLSConfig tlsConfig) {

-    this(tlsConfig, null);

-  }

-

-  /**

-   * Add extraGlobalHeaders to http request

-   * @param extraGlobalHeaders

-   */

-  public ServiceCenterClient(Map<String, String> extraGlobalHeaders) {

-    this(null, 0, null, null, null, extraGlobalHeaders);

-  }

-

-  /**

-   * Add TLS config and extraGlobalHeaders

-   * @param tlsConfig

-   * @param extraGlobalHeaders

-   */

-  public ServiceCenterClient(TLSConfig tlsConfig, Map<String, String> extraGlobalHeaders) {

-    this(null, 0, null, null, tlsConfig, extraGlobalHeaders);

-  }

-

-  /**

-   * Customized host,port,

-   * @param host

-   * @param port

-   */

-  public ServiceCenterClient(String host, int port) {

-    this(host, port, null, null, null, null);

-  }

-

-  /**

-   * Customized host, port, projectName, tenantName, TLSConf, headers and any one parameter can be null.

-   * @param host

-   * @param port

-   * @param projectName

-   * @param tenantName

-   * @param tlsConfig

-   * @param extraGlobalHeaders

-   */

-  public ServiceCenterClient(String host, int port, String projectName, String tenantName, TLSConfig tlsConfig,

+  public ServiceCenterClient(AddressManager addressManager, SSLProperties sslProperties, String tenantName,

       Map<String, String> extraGlobalHeaders) {

-    HttpTransport httpTransport = HttpTransportFactory.getDefaultHttpTransport();

-    if (tlsConfig != null) {

-      httpTransport = new TLSHttpsTransport(tlsConfig);

-    }

+    HttpTransport httpTransport = HttpTransportFactory.createHttpTransport(sslProperties);

     httpTransport.addHeaders(extraGlobalHeaders);

 

     this.httpClient = new ServiceCenterRawClient.Builder()

-        .setHost(host)

-        .setPort(port)

-        .setProjectName(projectName)

         .setTenantName(tenantName)

+        .setAddressManager(addressManager)

         .setHttpTransport(httpTransport).build();

   }

 

-  public ServiceCenterClient(ServiceCenterRawClient serviceCenterRawClient) {

-    this.httpClient = serviceCenterRawClient;

-  }

-

   @Override

   public MicroserviceInstancesResponse getServiceCenterInstances() {

     try {

@@ -216,7 +160,6 @@
   }

 

   @Override

-  @SuppressWarnings("unchecked")

   public Microservice getMicroserviceByServiceId(String serviceId) {

     try {

       HttpResponse response = httpClient.getHttpRequest("/registry/microservices/" + serviceId, null, null);

diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java
new file mode 100644
index 0000000..ae420e2
--- /dev/null
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterConfiguration.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.servicecomb.service.center.client;
+
+public interface ServiceCenterConfiguration {
+  class AddressProperties {
+    private boolean address;
+
+    public boolean isAddress() {
+      return address;
+    }
+
+    public void setAddress(boolean address) {
+      this.address = address;
+    }
+  }
+
+  class AKSKProperties {
+    private boolean enabled;
+
+    private String accessKey;
+
+    private String secretKey;
+
+    private String cipher;
+
+    private String project;
+
+    public boolean isEnabled() {
+      return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+      this.enabled = enabled;
+    }
+
+    public String getAccessKey() {
+      return accessKey;
+    }
+
+    public void setAccessKey(String accessKey) {
+      this.accessKey = accessKey;
+    }
+
+    public String getSecretKey() {
+      return secretKey;
+    }
+
+    public void setSecretKey(String secretKey) {
+      this.secretKey = secretKey;
+    }
+
+    public String getCipher() {
+      return cipher;
+    }
+
+    public void setCipher(String cipher) {
+      this.cipher = cipher;
+    }
+
+    public String getProject() {
+      return project;
+    }
+
+    public void setProject(String project) {
+      this.project = project;
+    }
+  }
+}
diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java
index bf1f779..60c45d1 100644
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java
@@ -114,6 +114,17 @@
               .findMicroserviceInstance(myself.getServiceId(), k.appId, k.serviceName, ALL_VERSION, v.revision);
           if (instancesResponse.isModified()) {
             // java chassis 实现了空实例保护,这里暂时不实现。
+            LOGGER.info("Instance changed event, "
+                    + "current: revision={}, instances={}; "
+                    + "origin: revision={}, instances={}; "
+                    + "appId={}, serviceName={}",
+                instancesResponse.getRevision(),
+                instanceToString(instancesResponse.getMicroserviceInstancesResponse().getInstances()),
+                v.revision,
+                instanceToString(v.instancesCache),
+                k.appId,
+                k.serviceName
+            );
             v.instancesCache = instancesResponse.getMicroserviceInstancesResponse().getInstances();
             v.revision = instancesResponse.getRevision();
             eventBus.post(new InstanceChangedEvent(k.appId, k.serviceName,
@@ -126,5 +137,21 @@
 
       startTask(new BackOffSleepTask(POLL_INTERVAL, new PullInstanceTask()));
     }
+
+    private String instanceToString(List<MicroserviceInstance> instances) {
+      if (instances == null) {
+        return "";
+      }
+
+      StringBuilder sb = new StringBuilder();
+      for (MicroserviceInstance instance : instances) {
+        for (String endpoint : instance.getEndpoints()) {
+          sb.append(endpoint.length() > 20 ? endpoint.substring(0, 20) : endpoint);
+          sb.append("|");
+        }
+      }
+      sb.append("#");
+      return sb.toString();
+    }
   }
 }
diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java
index fc30c93..d7748ee 100755
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java
@@ -24,64 +24,25 @@
 import org.apache.servicecomb.http.client.common.HttpRequest;

 import org.apache.servicecomb.http.client.common.HttpResponse;

 import org.apache.servicecomb.http.client.common.HttpTransport;

-import org.apache.servicecomb.http.client.common.HttpTransportFactory;

-import org.apache.servicecomb.http.client.common.TLSConfig;

-import org.apache.servicecomb.http.client.common.TLSHttpsTransport;

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

 

-/**

- * Created by   on 2019/10/16.

- */

 public class ServiceCenterRawClient {

-

-  private static final String DEFAULT_HOST = "localhost";

-

-  private static final int DEFAULT_PORT = 30100;

-

-  private static final String PROJECT_NAME = "default";

-

-  private static final String V4_PREFIX = "v4";

+  private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCenterRawClient.class);

 

   private static final String HEADER_TENANT_NAME = "x-domain-name";

 

-  private static final String DEFAULT_HEADER_TENANT_NAME = "default";

-

-  private String basePath;

-

-  private String host;

-

-  private int port;

-

-  private String projectName;

-

   private String tenantName;

 

   private HttpTransport httpTransport;

 

-  public ServiceCenterRawClient() {

-    this(DEFAULT_HOST, DEFAULT_PORT, PROJECT_NAME, HttpTransportFactory.getDefaultHttpTransport(),

-        DEFAULT_HEADER_TENANT_NAME);

-  }

+  private AddressManager addressManager;

 

-  private ServiceCenterRawClient(String host, int port, String projectName, HttpTransport httpTransport,

-      String tenantName) {

-    this.host = host;

-    this.port = port;

-    this.projectName = projectName;

+  private ServiceCenterRawClient(String tenantName, HttpTransport httpTransport,

+      AddressManager addressManager) {

     this.httpTransport = httpTransport;

     this.tenantName = tenantName;

-

-    // check that host has scheme or not

-    String hostLowercase = host.toLowerCase();

-    if (!hostLowercase.startsWith("https://") && !hostLowercase.startsWith("http://")) {

-      // no protocol in host, use default 'http'

-      if (httpTransport instanceof TLSHttpsTransport) {

-        host = "https://" + host;

-      } else {

-        host = "http://" + host;

-      }

-    }

-

-    this.basePath = host + ":" + port + "/" + V4_PREFIX + "/" + projectName;

+    this.addressManager = addressManager;

   }

 

   public HttpResponse getHttpRequest(String url, Map<String, String> headers, String content) throws IOException {

@@ -106,88 +67,51 @@
       headers = new HashMap<>();

     }

     headers.put(HEADER_TENANT_NAME, tenantName);

-    HttpRequest httpRequest = new HttpRequest(basePath + url, headers, content, method);

-    return httpTransport.doRequest(httpRequest);

+    HttpRequest httpRequest = new HttpRequest(addressManager.address() + url, headers, content, method);

+

+    try {

+      return httpTransport.doRequest(httpRequest);

+    } catch (IOException e) {

+      LOGGER.warn("send request to {} failed and retry to {} once. ", addressManager.address(),

+          addressManager.nextAddress(), e);

+      httpRequest = new HttpRequest(addressManager.address() + url, headers, content, method);

+      try {

+        return httpTransport.doRequest(httpRequest);

+      } catch (IOException ioException) {

+        LOGGER.warn("retry to {} failed again, and change next address {}. ", addressManager.address()

+            , addressManager.nextAddress());

+        throw ioException;

+      }

+    }

   }

 

   public static class Builder {

-    private String host;

-

-    private int port;

-

-    private String projectName;

-

     private String tenantName;

 

-    private HttpTransport httpTransport = HttpTransportFactory.getDefaultHttpTransport();

+    private HttpTransport httpTransport;

+

+    private AddressManager addressManager;

 

     public Builder() {

-      this.host = DEFAULT_HOST;

-      this.port = DEFAULT_PORT;

-      this.projectName = PROJECT_NAME;

-      this.tenantName = DEFAULT_HEADER_TENANT_NAME;

     }

 

-    public String getProjectName() {

-      return projectName;

-    }

-

-    public Builder setProjectName(String projectName) {

-      if (projectName == null) {

-        projectName = PROJECT_NAME;

-      }

-      this.projectName = projectName;

+    public Builder setTenantName(String tenantName) {

+      this.tenantName = tenantName;

       return this;

     }

 

-    public int getPort() {

-      return port;

-    }

-

-    public Builder setPort(int port) {

-      if (port <= 0) {

-        port = DEFAULT_PORT;

-      }

-      this.port = port;

-      return this;

-    }

-

-    public String getHost() {

-      return host;

-    }

-

-    public Builder setHost(String host) {

-      if (host == null) {

-        host = DEFAULT_HOST;

-      }

-      this.host = host;

-      return this;

-    }

-

-    public HttpTransport getHttpTransport() {

-      return httpTransport;

-    }

-

     public Builder setHttpTransport(HttpTransport httpTransport) {

       this.httpTransport = httpTransport;

       return this;

     }

 

-    public Builder setTLSConf(TLSConfig tlsConfig) {

-      this.httpTransport = new TLSHttpsTransport(tlsConfig);

-      return this;

-    }

-

-    public Builder setTenantName(String tenantName) {

-      if (tenantName == null) {

-        tenantName = DEFAULT_HEADER_TENANT_NAME;

-      }

-      this.tenantName = tenantName;

+    public Builder setAddressManager(AddressManager addressManager) {

+      this.addressManager = addressManager;

       return this;

     }

 

     public ServiceCenterRawClient build() {

-      return new ServiceCenterRawClient(host, port, projectName, httpTransport, tenantName);

+      return new ServiceCenterRawClient(tenantName, httpTransport, addressManager);

     }

   }

 }

diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/Microservice.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/Microservice.java
index 54a183c..9d69bfd 100755
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/Microservice.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/Microservice.java
@@ -22,9 +22,6 @@
 import java.util.List;

 import java.util.Map;

 

-import com.fasterxml.jackson.annotation.JsonRootName;

-

-@JsonRootName("service")

 public class Microservice {

 

   private String serviceId;

diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/MicroserviceInstance.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/MicroserviceInstance.java
index 3fd4c29..f2f7ab0 100755
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/MicroserviceInstance.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/MicroserviceInstance.java
@@ -22,9 +22,6 @@
 import java.util.List;

 import java.util.Map;

 

-import com.fasterxml.jackson.annotation.JsonRootName;

-

-@JsonRootName("instance")

 public class MicroserviceInstance {

   // even disconnected from service center

   // instanceId will not be changed

diff --git a/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java
index d843638..f7a3f7b 100755
--- a/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java
+++ b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java
@@ -18,6 +18,7 @@
 package org.apache.servicecomb.service.center.client;

 

 import java.io.IOException;

+import java.util.Arrays;

 

 import org.apache.servicecomb.http.client.common.HttpResponse;

 import org.apache.servicecomb.http.client.common.HttpTransport;

@@ -43,11 +44,10 @@
 

     HttpTransport httpTransport = Mockito.mock(HttpTransport.class);

 

+    AddressManager addressManager = new AddressManager(PROJECT_NAME, Arrays.asList("http://127.0.0.1:30100"));

     ServiceCenterRawClient client = new ServiceCenterRawClient.Builder()

         .setHttpTransport(httpTransport)

-        .setHost(DEFAULT_HOST)

-        .setPort(DEFAULT_PORT)

-        .setProjectName(PROJECT_NAME)

+        .setAddressManager(addressManager)

         .setTenantName(TENANT_NAME)

         .build();

 

diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java
index 3cddf22..cbcb675 100644
--- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java
+++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java
@@ -18,6 +18,7 @@
 package org.apache.servicecomb.demo.multiServiceCenterClient;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -25,6 +26,8 @@
 import org.apache.servicecomb.demo.CategorizedTestCase;
 import org.apache.servicecomb.demo.TestMgr;
 import org.apache.servicecomb.foundation.common.event.SimpleEventBus;
+import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties;
+import org.apache.servicecomb.service.center.client.AddressManager;
 import org.apache.servicecomb.service.center.client.DiscoveryEvents.InstanceChangedEvent;
 import org.apache.servicecomb.service.center.client.RegistrationEvents;
 import org.apache.servicecomb.service.center.client.RegistrationEvents.HeartBeatEvent;
@@ -59,7 +62,10 @@
 
   @Override
   public void testRestTransport() throws Exception {
-    ServiceCenterClient serviceCenterClient = new ServiceCenterClient("127.0.0.1", 30100);
+    AddressManager addressManager = new AddressManager("default", Arrays.asList("http://127.0.0.1:30100"));
+    SSLProperties sslProperties = new SSLProperties();
+    sslProperties.setEnabled(false);
+    ServiceCenterClient serviceCenterClient = new ServiceCenterClient(addressManager, sslProperties, "default", null);
     EventBus eventBus = new SimpleEventBus();
     ServiceCenterRegistration serviceCenterRegistration = new ServiceCenterRegistration(serviceCenterClient, eventBus);
     Microservice microservice = new Microservice();
@@ -125,6 +131,9 @@
     discoveryCounter.await(30000, TimeUnit.MILLISECONDS);
     TestMgr.check(instances != null, true);
     TestMgr.check(instances.size(), 1);
+    discovery.stop();
+    serviceCenterRegistration.stop();
+    serviceCenterClient.deleteMicroserviceInstance(microservice.getServiceId(), microserviceInstance.getInstanceId());
   }
 
   @Subscribe