You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/12/04 10:46:07 UTC
[servicecomb-java-chassis] 01/03: [SCB-1063]Improve the time cost
when first time loading schema
This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
commit b60605b7118c0271a3041650761138e0b02e43ca
Author: liubao <ba...@huawei.com>
AuthorDate: Tue Dec 4 10:51:23 2018 +0800
[SCB-1063]Improve the time cost when first time loading schema
---
.../definition/schema/ConsumerSchemaFactory.java | 8 +++-
.../client/http/ServiceRegistryClientImpl.java | 46 ++++++++++++++++++++--
.../client/http/TestServiceRegistryClientImpl.java | 20 ++++++++++
3 files changed, 69 insertions(+), 5 deletions(-)
diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/schema/ConsumerSchemaFactory.java b/core/src/main/java/org/apache/servicecomb/core/definition/schema/ConsumerSchemaFactory.java
index c9b8ed2..36148ab 100644
--- a/core/src/main/java/org/apache/servicecomb/core/definition/schema/ConsumerSchemaFactory.java
+++ b/core/src/main/java/org/apache/servicecomb/core/definition/schema/ConsumerSchemaFactory.java
@@ -37,7 +37,9 @@ public class ConsumerSchemaFactory extends AbstractSchemaFactory<ConsumerSchemaC
// 允许consumerIntf与schemaId对应的interface原型不同,用于支持context类型的参数
// consumerIntf为null,表示原型与契约相同
public void createConsumerSchema(MicroserviceMeta microserviceMeta, Microservice microservice) {
- for (String schemaId : microservice.getSchemas()) {
+ // concurrently compile will improve performance, so we force using parallel stream
+ long start = System.currentTimeMillis();
+ microservice.getSchemas().parallelStream().forEach(schemaId -> {
ConsumerSchemaContext context = new ConsumerSchemaContext();
context.setMicroserviceMeta(microserviceMeta);
context.setMicroservice(microservice);
@@ -45,7 +47,9 @@ public class ConsumerSchemaFactory extends AbstractSchemaFactory<ConsumerSchemaC
context.setProviderClass(null);
getOrCreateSchema(context);
- }
+ });
+ LOGGER.info("Loading schema for service {} token {}", microservice.getServiceId(),
+ (System.currentTimeMillis() - start));
}
@Override
diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
index c27ba96..3ee0fe8 100644
--- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
+++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
@@ -21,10 +21,13 @@ import static java.util.Collections.emptyList;
import java.nio.charset.Charset;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
import javax.ws.rs.core.Response.Status;
@@ -60,6 +63,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
import io.netty.handler.codec.http.HttpStatusClass;
import io.vertx.core.Handler;
@@ -79,6 +85,18 @@ public final class ServiceRegistryClientImpl implements ServiceRegistryClient {
this.ipPortManager = ipPortManager;
}
+ private LoadingCache<String, Map<String, String>> schemaCache = CacheBuilder.newBuilder()
+ .expireAfterAccess(60, TimeUnit.SECONDS).build(new CacheLoader<String, Map<String, String>>() {
+ public Map<String, String> load(String key) {
+ Holder<List<GetSchemaResponse>> result = getSchemas(key, true, true);
+ Map<String, String> schemas = new HashMap<>();
+ if (result.getStatusCode() == Status.OK.getStatusCode() ) {
+ result.value.stream().forEach(r -> schemas.put(r.getSchemaId(), r.getSchema()));
+ }
+ return schemas;
+ }
+ });
+
@Override
public void init() {
}
@@ -350,6 +368,16 @@ public final class ServiceRegistryClientImpl implements ServiceRegistryClient {
}
private String doGetSchema(String microserviceId, String schemaId, boolean global) {
+ try {
+ // avoid query too many times of schema when first time loading
+ String cachedSchema = schemaCache.get(microserviceId).get(schemaId);
+ if (cachedSchema != null) {
+ return cachedSchema;
+ }
+ } catch (ExecutionException e) {
+ // ignore this error.
+ }
+
Holder<GetSchemaResponse> holder = new Holder<>();
IpPort ipPort = ipPortManager.getAvailableAddress();
@@ -383,15 +411,27 @@ public final class ServiceRegistryClientImpl implements ServiceRegistryClient {
@Override
public Holder<List<GetSchemaResponse>> getSchemas(String microserviceId) {
+ return getSchemas(microserviceId, false, false);
+ }
+
+ private Holder<List<GetSchemaResponse>> getSchemas(String microserviceId, boolean withSchema, boolean global) {
Holder<GetSchemasResponse> holder = new Holder<>();
IpPort ipPort = ipPortManager.getAvailableAddress();
Holder<List<GetSchemaResponse>> resultHolder = new Holder<>();
CountDownLatch countDownLatch = new CountDownLatch(1);
- // default not return schema content, just return summary!
+ String url = Const.REGISTRY_API.MICROSERVICE_ALL_SCHEMAs;
+ RequestParam requestParam = new RequestParam();
+ if (withSchema) {
+ url = Const.REGISTRY_API.MICROSERVICE_ALL_SCHEMAs + "?withSchema=1";
+ }
+ if (global) {
+ requestParam.addQueryParam("global", "true");
+ }
+
RestUtils.get(ipPort,
- String.format(Const.REGISTRY_API.MICROSERVICE_ALL_SCHEMAs, microserviceId),
- new RequestParam(),
+ String.format(url, microserviceId),
+ requestParam,
syncHandler(countDownLatch, GetSchemasResponse.class, holder));
try {
countDownLatch.await();
diff --git a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/client/http/TestServiceRegistryClientImpl.java b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/client/http/TestServiceRegistryClientImpl.java
index cba18e2..900f534 100644
--- a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/client/http/TestServiceRegistryClientImpl.java
+++ b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/client/http/TestServiceRegistryClientImpl.java
@@ -20,8 +20,11 @@ package org.apache.servicecomb.serviceregistry.client.http;
import static org.hamcrest.core.Is.is;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import javax.ws.rs.core.Response.Status;
@@ -47,6 +50,10 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClientOptions;
@@ -343,8 +350,21 @@ public class TestServiceRegistryClientImpl {
Assert.assertEquals("global=true", requestParam.getQueryParams());
}
};
+
+ LoadingCache<String, Map<String, String>> oldCache = Deencapsulation.getField(oClient, "schemaCache");
+ LoadingCache<String, Map<String, String>> newCache = CacheBuilder.newBuilder()
+ .expireAfterAccess(60, TimeUnit.SECONDS).build(new CacheLoader<String, Map<String, String>>() {
+ public Map<String, String> load(String key) {
+ Map<String, String> schemas = new HashMap<>();
+ return schemas;
+ }
+ });
+ Deencapsulation.setField(oClient, "schemaCache", newCache);
+
String str = oClient.getAggregatedSchema(microserviceId, schemaId);
Assert.assertEquals("schema", str);
+
+ Deencapsulation.setField(oClient, "schemaCache", oldCache);
}
@Test