From da01862664fbce5605f55840affa0621871057b9 Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Tue, 8 May 2018 18:37:38 +0800 Subject: [PATCH 01/13] SCB-548 support gracefully shutdown Signed-off-by: zhengyangyong --- .../core/CseApplicationListener.java | 21 +++++++++++++++++-- .../tracing/SpringCloudZuulTracingTest.java | 1 - 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java index 4952f35f3f2..060309ea33f 100644 --- a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java +++ b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java @@ -33,6 +33,7 @@ import org.apache.servicecomb.foundation.common.event.EventManager; import org.apache.servicecomb.foundation.common.utils.BeanUtils; import org.apache.servicecomb.foundation.common.utils.FortifyUtils; +import org.apache.servicecomb.foundation.vertx.VertxUtils; import org.apache.servicecomb.serviceregistry.RegistryUtils; import org.apache.servicecomb.serviceregistry.task.MicroserviceInstanceRegisterTask; import org.slf4j.Logger; @@ -50,6 +51,8 @@ import com.google.common.eventbus.Subscribe; +import io.vertx.core.Vertx; + public class CseApplicationListener implements ApplicationListener, Ordered, ApplicationContextAware { private static final Logger LOGGER = LoggerFactory.getLogger(CseApplicationListener.class); @@ -135,8 +138,6 @@ public void onApplicationEvent(ApplicationEvent event) { RegistryUtils.run(); // 当程序退出时,进行相关清理,注意:kill -9 {pid}下无效 - // 1. 去注册实例信息 - // TODO 服务优雅退出 if (applicationContext instanceof AbstractApplicationContext) { ((AbstractApplicationContext) applicationContext).registerShutdownHook(); } @@ -148,12 +149,28 @@ public void onApplicationEvent(ApplicationEvent event) { } else if (event instanceof ContextClosedEvent) { LOGGER.warn("cse is closing now..."); triggerEvent(EventType.BEFORE_CLOSE); + + //Unregister microservice instance from Service Center RegistryUtils.destroy(); + + //Stop vertx threads to prevent blocking exit + closeVertx("registry"); + closeVertx("config-center"); + closeVertx("transport"); + triggerEvent(EventType.AFTER_CLOSE); isInit = false; } } + private void closeVertx(String name) { + Vertx vertx = VertxUtils.getVertxByName(name); + if (vertx != null) { + vertx.close(); + VertxUtils.getVertxMap().remove(name); + } + } + /** *

As the process of instance registry is asynchronous, the {@code AFTER_REGISTRY} * event should not be sent immediately after {@link RegistryUtils#run()} is invoked. diff --git a/integration-tests/spring-zuul-tracing-tests/src/test/java/org/apache/servicecomb/spring/cloud/zuul/tracing/SpringCloudZuulTracingTest.java b/integration-tests/spring-zuul-tracing-tests/src/test/java/org/apache/servicecomb/spring/cloud/zuul/tracing/SpringCloudZuulTracingTest.java index 35a82b1de0d..1402cc2372e 100644 --- a/integration-tests/spring-zuul-tracing-tests/src/test/java/org/apache/servicecomb/spring/cloud/zuul/tracing/SpringCloudZuulTracingTest.java +++ b/integration-tests/spring-zuul-tracing-tests/src/test/java/org/apache/servicecomb/spring/cloud/zuul/tracing/SpringCloudZuulTracingTest.java @@ -17,7 +17,6 @@ package org.apache.servicecomb.spring.cloud.zuul.tracing; -import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; From e3e04a582bd4443238e7eb03465d253068d6dbcf Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Wed, 9 May 2018 15:59:08 +0800 Subject: [PATCH 02/13] SCB-548 improvement and fix it failed Signed-off-by: zhengyangyong --- .../core/CseApplicationListener.java | 18 +++--------------- .../core/handler/ShutdownHookHandler.java | 8 ++++++++ .../foundation/vertx/VertxUtils.java | 7 +++++++ .../tests/RawSpringMvcIntegrationTest.java | 2 +- ...lifiedMappingAnnotationIntegrationTest.java | 2 +- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java index 060309ea33f..0cd57f64ff4 100644 --- a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java +++ b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java @@ -51,8 +51,6 @@ import com.google.common.eventbus.Subscribe; -import io.vertx.core.Vertx; - public class CseApplicationListener implements ApplicationListener, Ordered, ApplicationContextAware { private static final Logger LOGGER = LoggerFactory.getLogger(CseApplicationListener.class); @@ -150,26 +148,16 @@ public void onApplicationEvent(ApplicationEvent event) { LOGGER.warn("cse is closing now..."); triggerEvent(EventType.BEFORE_CLOSE); - //Unregister microservice instance from Service Center + //Unregister microservice instance from Service Center and close vertx + //We need unregister from service center immediately RegistryUtils.destroy(); - - //Stop vertx threads to prevent blocking exit - closeVertx("registry"); - closeVertx("config-center"); - closeVertx("transport"); + VertxUtils.closeVertxByName("registry"); triggerEvent(EventType.AFTER_CLOSE); isInit = false; } } - private void closeVertx(String name) { - Vertx vertx = VertxUtils.getVertxByName(name); - if (vertx != null) { - vertx.close(); - VertxUtils.getVertxMap().remove(name); - } - } /** *

As the process of instance registry is asynchronous, the {@code AFTER_REGISTRY} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java b/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java index 8d1318aa3e7..c4d9a3aa12a 100644 --- a/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java +++ b/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java @@ -22,6 +22,7 @@ import org.apache.servicecomb.core.Handler; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.foundation.vertx.VertxUtils; import org.apache.servicecomb.swagger.invocation.AsyncResponse; import org.apache.servicecomb.swagger.invocation.Response; import org.slf4j.Logger; @@ -56,6 +57,8 @@ public long getActiveCount() { @Override public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { if (shuttingDown) { + System.out.println("shutting down in progress"); + asyncResp.handle(Response.createFail(invocation.getInvocationType(), "shutting down in progress")); return; @@ -92,6 +95,11 @@ public void run() { time = time + period; LOG.warn("waiting invocation to finish in seconds " + time); } + + //Stop vertx to prevent blocking exit, this work need do after invocation waiting timeout + VertxUtils.closeVertxByName("config-center"); + VertxUtils.closeVertxByName("transport"); + LOG.warn("handler chain is shut down"); } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java index 4aba612f2b6..d5e55f463d4 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java @@ -157,6 +157,13 @@ public static Vertx getVertxByName(String name) { return vertxMap.get(name); } + public static void closeVertxByName(String name) { + Vertx vertx = vertxMap.remove(name); + if (vertx != null) { + vertx.close(); + } + } + public static void runInContext(Context context, AsyncResultCallback callback, T result, Throwable e) { if (context == Vertx.currentContext()) { complete(callback, result, e); diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java b/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java index dd11460e413..714975512ea 100644 --- a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java +++ b/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java @@ -33,7 +33,7 @@ public static void init() throws Exception { } @AfterClass - public static void shutdown() throws Exception { + public static void shutdown() { CseApplicationListener cal = BeanUtils.getBean("org.apache.servicecomb.core.CseApplicationListener"); ContextClosedEvent event = new ContextClosedEvent(BeanUtils.getContext()); cal.onApplicationEvent(event); diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java b/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java index a4cd050383a..f25f0801991 100644 --- a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java +++ b/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java @@ -34,7 +34,7 @@ public static void init() throws Exception { } @AfterClass - public static void shutdown() throws Exception { + public static void shutdown() { CseApplicationListener cal = BeanUtils.getBean("org.apache.servicecomb.core.CseApplicationListener"); ContextClosedEvent event = new ContextClosedEvent(BeanUtils.getContext()); cal.onApplicationEvent(event); From 3f1ccf8b1a64e4b801407a5715647bee24b2dbd8 Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Thu, 10 May 2018 09:58:48 +0800 Subject: [PATCH 03/13] SCB-548 fix pr comment Signed-off-by: zhengyangyong --- .../apache/servicecomb/core/handler/ShutdownHookHandler.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java b/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java index c4d9a3aa12a..019aab266cd 100644 --- a/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java +++ b/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java @@ -57,8 +57,6 @@ public long getActiveCount() { @Override public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { if (shuttingDown) { - System.out.println("shutting down in progress"); - asyncResp.handle(Response.createFail(invocation.getInvocationType(), "shutting down in progress")); return; From 6eb811f4b051de3096b09e2857d03981fd3bfd2c Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Fri, 11 May 2018 14:37:27 +0800 Subject: [PATCH 04/13] SCB-548 improve gracefully shutdown Signed-off-by: zhengyangyong --- .../core/CseApplicationListener.java | 35 ++++++++++---- .../core/handler/ShutdownHookHandler.java | 46 +++++++++---------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java index 0cd57f64ff4..24da8c2cc18 100644 --- a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java +++ b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java @@ -26,6 +26,7 @@ import org.apache.servicecomb.core.definition.loader.SchemaListenerManager; import org.apache.servicecomb.core.endpoint.AbstractEndpointsCache; import org.apache.servicecomb.core.handler.HandlerConfigUtils; +import org.apache.servicecomb.core.handler.ShutdownHookHandler; import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager; import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils; import org.apache.servicecomb.core.provider.producer.ProducerProviderManager; @@ -146,18 +147,36 @@ public void onApplicationEvent(ApplicationEvent event) { } } else if (event instanceof ContextClosedEvent) { LOGGER.warn("cse is closing now..."); - triggerEvent(EventType.BEFORE_CLOSE); - - //Unregister microservice instance from Service Center and close vertx - //We need unregister from service center immediately - RegistryUtils.destroy(); - VertxUtils.closeVertxByName("registry"); - - triggerEvent(EventType.AFTER_CLOSE); + gracefullyShutdown(); isInit = false; } } + private void gracefullyShutdown() { + //Step 1: Unregister microservice instance from Service Center and close vertx + // We need unregister from service center immediately + RegistryUtils.destroy(); + VertxUtils.closeVertxByName("registry"); + + //Step 2: wait all invocation finished + try { + ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.acquire(); + LOGGER.warn("all invocation finished"); + } catch (InterruptedException e) { + LOGGER.error("invocation finished semaphore interrupted", e); + } + + //Step 3: notify all component do clean works via Event + triggerEvent(EventType.BEFORE_CLOSE); + + //Step 4: Stop vertx to prevent blocking exit + VertxUtils.closeVertxByName("config-center"); + VertxUtils.closeVertxByName("transport"); + + triggerEvent(EventType.AFTER_CLOSE); + ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); + } + /** *

As the process of instance registry is asynchronous, the {@code AFTER_REGISTRY} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java b/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java index 019aab266cd..4b284a4cb08 100644 --- a/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java +++ b/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java @@ -17,19 +17,19 @@ package org.apache.servicecomb.core.handler; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicLong; import org.apache.servicecomb.core.Handler; import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.vertx.VertxUtils; +import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; import org.apache.servicecomb.swagger.invocation.AsyncResponse; import org.apache.servicecomb.swagger.invocation.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * 实现调用链的优雅停止: 当调用链没有返回的时候,等待返回或者超时 + * 实现调用链的优雅停止: 当调用链没有返回的时候,等待返回(由于Consumer存在超时,所以必定能够返回) */ public final class ShutdownHookHandler implements Handler, Runnable { private static final Logger LOG = LoggerFactory.getLogger(ShutdownHookHandler.class); @@ -40,13 +40,16 @@ public final class ShutdownHookHandler implements Handler, Runnable { private final AtomicLong responseCounter = new AtomicLong(0); - private final int timeout = 600; - - private final int period = 10; - private volatile boolean shuttingDown = false; + public final Semaphore ALL_INVOCATION_FINISHED = new Semaphore(1); + private ShutdownHookHandler() { + try { + ALL_INVOCATION_FINISHED.acquire(); + } catch (InterruptedException e) { + throw new ServiceCombException("init invocation finished semaphore failed", e); + } Runtime.getRuntime().addShutdownHook(new Thread(this)); } @@ -63,7 +66,7 @@ public void handle(Invocation invocation, AsyncResponse asyncResp) throws Except } // TODO:统计功能应该独立出来,在链中统计,会有各种bug - // 下面的两次catch,可能会导致一次请求,对应2次应答 + // 下面的两次catch,可能会导致一次请求,对应2次应答 requestCounter.incrementAndGet(); try { invocation.next(resp -> { @@ -71,33 +74,26 @@ public void handle(Invocation invocation, AsyncResponse asyncResp) throws Except asyncResp.handle(resp); } finally { responseCounter.incrementAndGet(); + validAllInvocationFinished(); } }); } catch (Throwable e) { responseCounter.incrementAndGet(); + validAllInvocationFinished(); throw e; } } + private synchronized void validAllInvocationFinished() { + if (shuttingDown && getActiveCount() <= 0) { + ALL_INVOCATION_FINISHED.release(); + } + } + @Override public void run() { shuttingDown = true; - LOG.warn("handler chain is shutting down"); - int time = 0; - while (getActiveCount() != 0 && time <= timeout) { - try { - TimeUnit.SECONDS.sleep(period); - } catch (InterruptedException e) { - LOG.warn(e.getMessage()); - } - time = time + period; - LOG.warn("waiting invocation to finish in seconds " + time); - } - - //Stop vertx to prevent blocking exit, this work need do after invocation waiting timeout - VertxUtils.closeVertxByName("config-center"); - VertxUtils.closeVertxByName("transport"); - - LOG.warn("handler chain is shut down"); + LOG.warn("handler chain is shutting down..."); + validAllInvocationFinished(); } } From d66eb287ee4a5126e2455855e00792d4a75fe01d Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Fri, 11 May 2018 14:47:03 +0800 Subject: [PATCH 05/13] SCB-548 reorganization springmvc it (spring-springmvc-tests and springmvc-tests) make four independent module in order to eliminate disturbance(from gracefully shutdown) Signed-off-by: zhengyangyong --- .../core/TestCseApplicationListener.java | 3 + integration-tests/pom.xml | 1 - integration-tests/springmvc-tests/pom.xml | 12 +++- .../springmvc-tests-common/pom.xml | 32 +++++++++++ .../tests/SpringMvcIntegrationTestBase.java | 2 +- .../tests/endpoints/CodeFirstSpringmvc.java | 0 .../endpoints/CodeFirstSpringmvcBase.java | 0 ...tSpringmvcSimplifiedMappingAnnotation.java | 0 .../tests/endpoints/ControllerBase.java | 0 .../tests/endpoints/ControllerImpl.java | 0 ...rollerSimplifiedMappingAnnotationImpl.java | 0 .../EnglishGreetingRestEndpoint.java | 0 .../EnglishGreetingRestEndpointBase.java | 0 ...mplifiedMappingAnnotationRestEndpoint.java | 0 .../endpoints/FrenchGreetingRestEndpoint.java | 0 .../FrenchGreetingRestEndpointBase.java | 0 ...mplifiedMappingAnnotationRestEndpoint.java | 0 .../pom.xml | 29 ++-------- .../tests/SpringMvcSpringIntegrationTest.java | 7 ++- .../springmvc/tests/SpringMvcSpringMain.java | 0 .../src/test/resources/log4j.properties | 0 .../src/test/resources/microservice.yaml | 0 .../src/test/resources/registry.yaml | 0 .../springmvc-tests-general/pom.xml | 41 +++++++++++++ .../tests/RawSpringMvcIntegrationTest.java | 3 + .../springmvc/tests/SpringMvcTestMain.java | 0 .../src/test/resources/microservice.yaml | 31 ++++++++++ .../src/test/resources/registry.yaml | 24 ++++++++ .../pom.xml | 57 +++++++++++++++++++ .../springmvc/tests/SpringMvcSpringMain.java | 26 +++++++++ ...ifiedMappingAnnotationIntegrationTest.java | 7 ++- .../src/test/resources/log4j.properties | 20 +++++++ .../src/test/resources/microservice.yaml | 31 ++++++++++ .../src/test/resources/registry.yaml | 24 ++++++++ .../pom.xml | 41 +++++++++++++ ...ifiedMappingAnnotationIntegrationTest.java | 3 + .../springmvc/tests/SpringMvcTestMain.java | 29 ++++++++++ .../src/test/resources/microservice.yaml | 31 ++++++++++ .../src/test/resources/registry.yaml | 24 ++++++++ 39 files changed, 448 insertions(+), 30 deletions(-) create mode 100644 integration-tests/springmvc-tests/springmvc-tests-common/pom.xml rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java (99%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvc.java (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcSimplifiedMappingAnnotation.java (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerBase.java (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerImpl.java (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerSimplifiedMappingAnnotationImpl.java (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpoint.java (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpointBase.java (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingSimplifiedMappingAnnotationRestEndpoint.java (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpoint.java (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpointBase.java (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-common}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingSimplifiedMappingAnnotationRestEndpoint.java (100%) rename integration-tests/{spring-springmvc-tests => springmvc-tests/springmvc-tests-general-with-springboot}/pom.xml (74%) rename integration-tests/{spring-springmvc-tests => springmvc-tests/springmvc-tests-general-with-springboot}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java (87%) rename integration-tests/{spring-springmvc-tests => springmvc-tests/springmvc-tests-general-with-springboot}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java (100%) rename integration-tests/{spring-springmvc-tests => springmvc-tests/springmvc-tests-general-with-springboot}/src/test/resources/log4j.properties (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-general-with-springboot}/src/test/resources/microservice.yaml (100%) rename integration-tests/springmvc-tests/{ => springmvc-tests-general-with-springboot}/src/test/resources/registry.yaml (100%) create mode 100644 integration-tests/springmvc-tests/springmvc-tests-general/pom.xml rename integration-tests/springmvc-tests/{ => springmvc-tests-general}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java (91%) rename integration-tests/springmvc-tests/{ => springmvc-tests-general}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java (100%) create mode 100644 integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/microservice.yaml create mode 100644 integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/registry.yaml create mode 100644 integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/pom.xml create mode 100644 integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java rename integration-tests/{spring-springmvc-tests => springmvc-tests/springmvc-tests-simplified-mapping-with-springboot}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java (87%) create mode 100644 integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/log4j.properties create mode 100644 integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/microservice.yaml create mode 100644 integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/registry.yaml create mode 100644 integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/pom.xml rename integration-tests/springmvc-tests/{ => springmvc-tests-simplified-mapping}/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java (91%) create mode 100644 integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java create mode 100644 integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/microservice.yaml create mode 100644 integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/registry.yaml diff --git a/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java b/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java index e5eaec84a34..43fd873f319 100644 --- a/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java +++ b/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java @@ -35,6 +35,7 @@ import org.apache.servicecomb.core.BootListener.EventType; import org.apache.servicecomb.core.definition.loader.SchemaListenerManager; import org.apache.servicecomb.core.endpoint.AbstractEndpointsCache; +import org.apache.servicecomb.core.handler.ShutdownHookHandler; import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager; import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils; import org.apache.servicecomb.core.provider.producer.ProducerProviderManager; @@ -167,6 +168,8 @@ void destroy() { CseApplicationListener cal = new CseApplicationListener(); ContextClosedEvent event = new ContextClosedEvent(context); + ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); + List eventTypes = new ArrayList<>(); BootListener bootListener = e -> { eventTypes.add(e.getEventType()); diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 52c37a26709..62152e492ff 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -37,7 +37,6 @@ test-common spring-jaxrs-tests pojo-test - spring-springmvc-tests spring-zuul-tracing-tests spring-pojo-tests dynamic-config-tests diff --git a/integration-tests/springmvc-tests/pom.xml b/integration-tests/springmvc-tests/pom.xml index ba4f674e3a9..8b907a256d4 100644 --- a/integration-tests/springmvc-tests/pom.xml +++ b/integration-tests/springmvc-tests/pom.xml @@ -27,7 +27,17 @@ 4.0.0 springmvc-tests - Java Chassis::Integration Tests::Raw Spring MVC + pom + Java Chassis::Integration Tests::Spring MVC + + + springmvc-tests-common + springmvc-tests-general + springmvc-tests-simplified-mapping + springmvc-tests-general-with-springboot + springmvc-tests-simplified-mapping-with-springboot + + org.apache.servicecomb.demo diff --git a/integration-tests/springmvc-tests/springmvc-tests-common/pom.xml b/integration-tests/springmvc-tests/springmvc-tests-common/pom.xml new file mode 100644 index 00000000000..885d5126e25 --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-common/pom.xml @@ -0,0 +1,32 @@ + + + + + + springmvc-tests + org.apache.servicecomb.tests + 1.0.0-m2-SNAPSHOT + + 4.0.0 + + Java Chassis::Integration Tests::Spring MVC Common + springmvc-tests-common + + \ No newline at end of file diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java similarity index 99% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java index 611916c9a5d..6d3fdf9d1d4 100644 --- a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java +++ b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java @@ -84,7 +84,7 @@ public class SpringMvcIntegrationTestBase { private final String controllerUrl = baseUrl + "springmvc/controller/"; - static void setUpLocalRegistry() { + public static void setUpLocalRegistry() { ClassLoader loader = Thread.currentThread().getContextClassLoader(); URL resource = loader.getResource("registry.yaml"); assert resource != null; diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvc.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvc.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvc.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvc.java diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcSimplifiedMappingAnnotation.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcSimplifiedMappingAnnotation.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcSimplifiedMappingAnnotation.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcSimplifiedMappingAnnotation.java diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerBase.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerBase.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerBase.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerBase.java diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerImpl.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerImpl.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerImpl.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerImpl.java diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerSimplifiedMappingAnnotationImpl.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerSimplifiedMappingAnnotationImpl.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerSimplifiedMappingAnnotationImpl.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/ControllerSimplifiedMappingAnnotationImpl.java diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpoint.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpoint.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpoint.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpoint.java diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpointBase.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpointBase.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpointBase.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingRestEndpointBase.java diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingSimplifiedMappingAnnotationRestEndpoint.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingSimplifiedMappingAnnotationRestEndpoint.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingSimplifiedMappingAnnotationRestEndpoint.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/EnglishGreetingSimplifiedMappingAnnotationRestEndpoint.java diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpoint.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpoint.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpoint.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpoint.java diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpointBase.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpointBase.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpointBase.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingRestEndpointBase.java diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingSimplifiedMappingAnnotationRestEndpoint.java b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingSimplifiedMappingAnnotationRestEndpoint.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingSimplifiedMappingAnnotationRestEndpoint.java rename to integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/FrenchGreetingSimplifiedMappingAnnotationRestEndpoint.java diff --git a/integration-tests/spring-springmvc-tests/pom.xml b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/pom.xml similarity index 74% rename from integration-tests/spring-springmvc-tests/pom.xml rename to integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/pom.xml index 2840574d5df..6832ba80768 100644 --- a/integration-tests/spring-springmvc-tests/pom.xml +++ b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/pom.xml @@ -20,26 +20,21 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - integration-tests + springmvc-tests org.apache.servicecomb.tests 1.0.0-m2-SNAPSHOT 4.0.0 - spring-springmvc-tests - Java Chassis::Integration Tests::Spring MVC + Java Chassis::Integration Tests::Spring MVC General With Spring Boot + springmvc-tests-general-with-springboot + org.apache.servicecomb.tests - springmvc-tests + springmvc-tests-common 1.0.0-m2-SNAPSHOT test-jar - - - org.apache.servicecomb.demo - demo-signature - - org.apache.servicecomb @@ -59,16 +54,4 @@ - - - - org.apache.maven.plugins - maven-surefire-plugin - - 1 - - - - - - + \ No newline at end of file diff --git a/integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java similarity index 87% rename from integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java rename to integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java index 75d6693f375..c0caef64c15 100644 --- a/integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java +++ b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java @@ -17,6 +17,7 @@ package org.apache.servicecomb.demo.springmvc.tests; +import org.apache.servicecomb.core.handler.ShutdownHookHandler; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.runner.RunWith; @@ -29,14 +30,16 @@ public class SpringMvcSpringIntegrationTest extends SpringMvcIntegrationTestBase private static ConfigurableApplicationContext context; @BeforeClass - public static void init() throws Exception { + public static void init() { System.setProperty("cse.uploads.directory", "/tmp"); setUpLocalRegistry(); context = SpringApplication.run(SpringMvcSpringMain.class); } @AfterClass - public static void shutdown() throws Exception { + public static void shutdown() { + //sim system.exit(0) + ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); context.close(); } } diff --git a/integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java similarity index 100% rename from integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java rename to integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java diff --git a/integration-tests/spring-springmvc-tests/src/test/resources/log4j.properties b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/log4j.properties similarity index 100% rename from integration-tests/spring-springmvc-tests/src/test/resources/log4j.properties rename to integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/log4j.properties diff --git a/integration-tests/springmvc-tests/src/test/resources/microservice.yaml b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/microservice.yaml similarity index 100% rename from integration-tests/springmvc-tests/src/test/resources/microservice.yaml rename to integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/microservice.yaml diff --git a/integration-tests/springmvc-tests/src/test/resources/registry.yaml b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/registry.yaml similarity index 100% rename from integration-tests/springmvc-tests/src/test/resources/registry.yaml rename to integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/resources/registry.yaml diff --git a/integration-tests/springmvc-tests/springmvc-tests-general/pom.xml b/integration-tests/springmvc-tests/springmvc-tests-general/pom.xml new file mode 100644 index 00000000000..6b07517e877 --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-general/pom.xml @@ -0,0 +1,41 @@ + + + + + + springmvc-tests + org.apache.servicecomb.tests + 1.0.0-m2-SNAPSHOT + + 4.0.0 + + Java Chassis::Integration Tests::Spring MVC General + springmvc-tests-general + + + + org.apache.servicecomb.tests + springmvc-tests-common + 1.0.0-m2-SNAPSHOT + test-jar + + + + \ No newline at end of file diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java similarity index 91% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java rename to integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java index 714975512ea..c0fc7e3a74e 100644 --- a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java +++ b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java @@ -18,6 +18,7 @@ package org.apache.servicecomb.demo.springmvc.tests; import org.apache.servicecomb.core.CseApplicationListener; +import org.apache.servicecomb.core.handler.ShutdownHookHandler; import org.apache.servicecomb.foundation.common.utils.BeanUtils; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -34,6 +35,8 @@ public static void init() throws Exception { @AfterClass public static void shutdown() { + //sim system.exit(0) + ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); CseApplicationListener cal = BeanUtils.getBean("org.apache.servicecomb.core.CseApplicationListener"); ContextClosedEvent event = new ContextClosedEvent(BeanUtils.getContext()); cal.onApplicationEvent(event); diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java similarity index 100% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java rename to integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java diff --git a/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/microservice.yaml b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/microservice.yaml new file mode 100644 index 00000000000..a5d81f8712e --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/microservice.yaml @@ -0,0 +1,31 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +APPLICATION_ID: springmvctest-it +service_description: + name: springmvc-tests + version: 0.0.2 +servicecomb: + service: + registry: + address: http://127.0.0.1:30100 + rest: + address: 0.0.0.0:8080 + handler: + chain: + Provider: + default: bizkeeper-provider diff --git a/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/registry.yaml b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/registry.yaml new file mode 100644 index 00000000000..c1ca1e9b312 --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/resources/registry.yaml @@ -0,0 +1,24 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +springmvc-tests: + - id: "001" + version: "0.0.2" + appid: springmvctest-it + instances: + - endpoints: + - rest://127.0.0.1:8080 diff --git a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/pom.xml b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/pom.xml new file mode 100644 index 00000000000..a98aea37d3a --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/pom.xml @@ -0,0 +1,57 @@ + + + + + + springmvc-tests + org.apache.servicecomb.tests + 1.0.0-m2-SNAPSHOT + + 4.0.0 + + Java Chassis::Integration Tests::Spring MVC Simplified Mapping With Spring Boot + springmvc-tests-simplified-mapping-with-springboot + + + + org.apache.servicecomb.tests + springmvc-tests-common + 1.0.0-m2-SNAPSHOT + test-jar + + + org.apache.servicecomb + spring-boot-starter-provider + + + org.springframework.boot + spring-boot-test + + + org.springframework + spring-test + + + org.hibernate + hibernate-validator + + + + \ No newline at end of file diff --git a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java new file mode 100644 index 00000000000..e149464af89 --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringMain.java @@ -0,0 +1,26 @@ +/* + * 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.demo.springmvc.tests; + +import org.apache.servicecomb.springboot.starter.provider.EnableServiceComb; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@EnableServiceComb +class SpringMvcSpringMain { +} diff --git a/integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java similarity index 87% rename from integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java rename to integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java index 089d3d02175..dfc0ca8b746 100644 --- a/integration-tests/spring-springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java @@ -17,6 +17,7 @@ package org.apache.servicecomb.demo.springmvc.tests; +import org.apache.servicecomb.core.handler.ShutdownHookHandler; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.runner.RunWith; @@ -29,7 +30,7 @@ public class SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest extends S private static ConfigurableApplicationContext context; @BeforeClass - public static void init() throws Exception { + public static void init() { System.setProperty("spring.profiles.active", "SimplifiedMapping"); System.setProperty("cse.uploads.directory", "/tmp"); setUpLocalRegistry(); @@ -37,7 +38,9 @@ public static void init() throws Exception { } @AfterClass - public static void shutdown() throws Exception { + public static void shutdown() { + //sim system.exit(0) + ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); context.close(); } } diff --git a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/log4j.properties b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/log4j.properties new file mode 100644 index 00000000000..bc03e25ceb6 --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/log4j.properties @@ -0,0 +1,20 @@ +# +# 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. +# +log4j.rootLogger=INFO, stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n diff --git a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/microservice.yaml b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/microservice.yaml new file mode 100644 index 00000000000..a5d81f8712e --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/microservice.yaml @@ -0,0 +1,31 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +APPLICATION_ID: springmvctest-it +service_description: + name: springmvc-tests + version: 0.0.2 +servicecomb: + service: + registry: + address: http://127.0.0.1:30100 + rest: + address: 0.0.0.0:8080 + handler: + chain: + Provider: + default: bizkeeper-provider diff --git a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/registry.yaml b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/registry.yaml new file mode 100644 index 00000000000..c1ca1e9b312 --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/resources/registry.yaml @@ -0,0 +1,24 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +springmvc-tests: + - id: "001" + version: "0.0.2" + appid: springmvctest-it + instances: + - endpoints: + - rest://127.0.0.1:8080 diff --git a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/pom.xml b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/pom.xml new file mode 100644 index 00000000000..1940d98139b --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/pom.xml @@ -0,0 +1,41 @@ + + + + + + springmvc-tests + org.apache.servicecomb.tests + 1.0.0-m2-SNAPSHOT + + 4.0.0 + + Java Chassis::Integration Tests::Spring MVC Simplified Mapping + springmvc-tests-simplified-mapping + + + + org.apache.servicecomb.tests + springmvc-tests-common + 1.0.0-m2-SNAPSHOT + test-jar + + + + \ No newline at end of file diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java similarity index 91% rename from integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java rename to integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java index f25f0801991..d6d2cfc9404 100644 --- a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java @@ -18,6 +18,7 @@ package org.apache.servicecomb.demo.springmvc.tests; import org.apache.servicecomb.core.CseApplicationListener; +import org.apache.servicecomb.core.handler.ShutdownHookHandler; import org.apache.servicecomb.foundation.common.utils.BeanUtils; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -35,6 +36,8 @@ public static void init() throws Exception { @AfterClass public static void shutdown() { + //sim system.exit(0) + ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); CseApplicationListener cal = BeanUtils.getBean("org.apache.servicecomb.core.CseApplicationListener"); ContextClosedEvent event = new ContextClosedEvent(BeanUtils.getContext()); cal.onApplicationEvent(event); diff --git a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java new file mode 100644 index 00000000000..99d937049f5 --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcTestMain.java @@ -0,0 +1,29 @@ +/* + * 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.demo.springmvc.tests; + +import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.apache.servicecomb.foundation.common.utils.Log4jUtils; + +public class SpringMvcTestMain { + + public static void main(String[] args) throws Exception { + Log4jUtils.init(); + BeanUtils.init(); + } +} diff --git a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/microservice.yaml b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/microservice.yaml new file mode 100644 index 00000000000..a5d81f8712e --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/microservice.yaml @@ -0,0 +1,31 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +APPLICATION_ID: springmvctest-it +service_description: + name: springmvc-tests + version: 0.0.2 +servicecomb: + service: + registry: + address: http://127.0.0.1:30100 + rest: + address: 0.0.0.0:8080 + handler: + chain: + Provider: + default: bizkeeper-provider diff --git a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/registry.yaml b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/registry.yaml new file mode 100644 index 00000000000..c1ca1e9b312 --- /dev/null +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/resources/registry.yaml @@ -0,0 +1,24 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +springmvc-tests: + - id: "001" + version: "0.0.2" + appid: springmvctest-it + instances: + - endpoints: + - rest://127.0.0.1:8080 From 9eb2fdeae148ef4397db1bcec4e590abcb4109c7 Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Fri, 11 May 2018 16:43:15 +0800 Subject: [PATCH 06/13] SCB-548 improve gracefully shutdown process order Signed-off-by: zhengyangyong --- .../servicecomb/core/CseApplicationListener.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java index 24da8c2cc18..5d40780cd57 100644 --- a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java +++ b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java @@ -153,12 +153,14 @@ public void onApplicationEvent(ApplicationEvent event) { } private void gracefullyShutdown() { - //Step 1: Unregister microservice instance from Service Center and close vertx - // We need unregister from service center immediately + //Step 1: notify all component stop invoke via BEFORE_CLOSE Event + triggerEvent(EventType.BEFORE_CLOSE); + + //Step 2: Unregister microservice instance from Service Center and close vertx RegistryUtils.destroy(); VertxUtils.closeVertxByName("registry"); - //Step 2: wait all invocation finished + //Step 3: wait all invocation finished try { ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.acquire(); LOGGER.warn("all invocation finished"); @@ -166,15 +168,12 @@ private void gracefullyShutdown() { LOGGER.error("invocation finished semaphore interrupted", e); } - //Step 3: notify all component do clean works via Event - triggerEvent(EventType.BEFORE_CLOSE); - //Step 4: Stop vertx to prevent blocking exit VertxUtils.closeVertxByName("config-center"); VertxUtils.closeVertxByName("transport"); + //Step 5: notify all component do clean works via AFTER_CLOSE Event triggerEvent(EventType.AFTER_CLOSE); - ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); } From b7b60b9a8d6f77301c6b11c0d9f86cdef46b5c57 Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Sun, 13 May 2018 15:46:56 +0800 Subject: [PATCH 07/13] SCB-548 fix fork issue for ci Signed-off-by: zhengyangyong --- integration-tests/spring-zuul-tracing-tests/pom.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/integration-tests/spring-zuul-tracing-tests/pom.xml b/integration-tests/spring-zuul-tracing-tests/pom.xml index 27b27aac33b..f414368e4b7 100644 --- a/integration-tests/spring-zuul-tracing-tests/pom.xml +++ b/integration-tests/spring-zuul-tracing-tests/pom.xml @@ -93,4 +93,17 @@ test + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 1 + false + + + + From ff7b87e502beed374a0fb7246c79850b40c6dbda Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Tue, 15 May 2018 19:45:26 +0800 Subject: [PATCH 08/13] SCB-548 refactor for delete ShutdownHandler Signed-off-by: zhengyangyong --- .../core/CseApplicationListener.java | 149 +-------- .../apache/servicecomb/core/SCBEngine.java | 305 ++++++++++++++++++ .../apache/servicecomb/core/SCBStatus.java | 32 ++ .../core/handler/AbstractHandlerManager.java | 2 - .../core/handler/ShutdownHookHandler.java | 99 ------ .../consumer/ReferenceConfigUtils.java | 30 +- .../core/TestCseApplicationListener.java | 248 -------------- .../core/handler/TestShutdownHookHandler.java | 141 -------- .../provider/consumer/TestInvokerUtils.java | 22 +- .../consumer/TestReferenceConfigUtils.java | 9 +- .../perf/src/main/resources/microservice.yaml | 4 +- .../foundation/vertx/VertxUtils.java | 39 ++- .../tests/SpringMvcSpringIntegrationTest.java | 11 +- .../tests/RawSpringMvcIntegrationTest.java | 11 +- ...ifiedMappingAnnotationIntegrationTest.java | 11 +- ...ifiedMappingAnnotationIntegrationTest.java | 11 +- .../servicecomb/provider/pojo/Invoker.java | 5 +- .../provider/pojo/TestInvoker.java | 10 +- .../reference/CseClientHttpRequest.java | 4 + .../reference/TestCseClientHttpRequest.java | 14 +- .../async/CseAsyncClientHttpRequestTest.java | 21 +- .../client/http/WebsocketUtils.java | 5 - 22 files changed, 451 insertions(+), 732 deletions(-) create mode 100644 core/src/main/java/org/apache/servicecomb/core/SCBEngine.java create mode 100644 core/src/main/java/org/apache/servicecomb/core/SCBStatus.java delete mode 100644 core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java delete mode 100644 core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java delete mode 100644 core/src/test/java/org/apache/servicecomb/core/handler/TestShutdownHookHandler.java diff --git a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java index 5d40780cd57..36586874650 100644 --- a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java +++ b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java @@ -17,61 +17,23 @@ package org.apache.servicecomb.core; -import java.util.Collection; - -import javax.inject.Inject; - -import org.apache.servicecomb.core.BootListener.BootEvent; -import org.apache.servicecomb.core.BootListener.EventType; import org.apache.servicecomb.core.definition.loader.SchemaListenerManager; -import org.apache.servicecomb.core.endpoint.AbstractEndpointsCache; -import org.apache.servicecomb.core.handler.HandlerConfigUtils; -import org.apache.servicecomb.core.handler.ShutdownHookHandler; import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager; -import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils; import org.apache.servicecomb.core.provider.producer.ProducerProviderManager; import org.apache.servicecomb.core.transport.TransportManager; -import org.apache.servicecomb.foundation.common.event.EventManager; import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.FortifyUtils; -import org.apache.servicecomb.foundation.vertx.VertxUtils; import org.apache.servicecomb.serviceregistry.RegistryUtils; -import org.apache.servicecomb.serviceregistry.task.MicroserviceInstanceRegisterTask; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; -import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.core.Ordered; -import org.springframework.util.StringUtils; - -import com.google.common.eventbus.Subscribe; public class CseApplicationListener implements ApplicationListener, Ordered, ApplicationContextAware { - private static final Logger LOGGER = LoggerFactory.getLogger(CseApplicationListener.class); - - private static boolean isInit = false; - - @Inject - private ProducerProviderManager producerProviderManager; - - @Inject - private ConsumerProviderManager consumerProviderManager; - - @Inject - private TransportManager transportManager; - - @Inject - private SchemaListenerManager schemaListenerManager; - - private Collection bootListenerList; - private Class initEventClass = ContextRefreshedEvent.class; private ApplicationContext applicationContext; @@ -93,113 +55,22 @@ public int getOrder() { return -1000; } - protected void triggerEvent(EventType eventType) { - BootEvent event = new BootEvent(); - event.setEventType(eventType); - - for (BootListener listener : bootListenerList) { - listener.onBootEvent(event); - } - } - @Override public void onApplicationEvent(ApplicationEvent event) { if (initEventClass.isInstance(event)) { - //TODO to load when webapplication context is used for discovery client, need to check if can use the order and undo this change with proper fix. - if (!isInit) { - try { - bootListenerList = applicationContext.getBeansOfType(BootListener.class).values(); - - AbstractEndpointsCache.init(RegistryUtils.getInstanceCacheManager(), transportManager); - - triggerEvent(EventType.BEFORE_HANDLER); - HandlerConfigUtils.init(); - triggerEvent(EventType.AFTER_HANDLER); - - triggerEvent(EventType.BEFORE_PRODUCER_PROVIDER); - producerProviderManager.init(); - triggerEvent(EventType.AFTER_PRODUCER_PROVIDER); - - triggerEvent(EventType.BEFORE_CONSUMER_PROVIDER); - consumerProviderManager.init(); - triggerEvent(EventType.AFTER_CONSUMER_PROVIDER); - - triggerEvent(EventType.BEFORE_TRANSPORT); - transportManager.init(); - triggerEvent(EventType.AFTER_TRANSPORT); - - schemaListenerManager.notifySchemaListener(); - - triggerEvent(EventType.BEFORE_REGISTRY); - - triggerAfterRegistryEvent(); - - RegistryUtils.run(); - - // 当程序退出时,进行相关清理,注意:kill -9 {pid}下无效 - if (applicationContext instanceof AbstractApplicationContext) { - ((AbstractApplicationContext) applicationContext).registerShutdownHook(); - } - isInit = true; - } catch (Exception e) { - LOGGER.error("cse init failed, {}", FortifyUtils.getErrorInfo(e)); - } + if (applicationContext instanceof AbstractApplicationContext) { + ((AbstractApplicationContext) applicationContext).registerShutdownHook(); } - } else if (event instanceof ContextClosedEvent) { - LOGGER.warn("cse is closing now..."); - gracefullyShutdown(); - isInit = false; - } - } - private void gracefullyShutdown() { - //Step 1: notify all component stop invoke via BEFORE_CLOSE Event - triggerEvent(EventType.BEFORE_CLOSE); - - //Step 2: Unregister microservice instance from Service Center and close vertx - RegistryUtils.destroy(); - VertxUtils.closeVertxByName("registry"); + if (SCBEngine.getInstance().getBootListenerList() == null) { + SCBEngine.getInstance().setProducerProviderManager(applicationContext.getBean(ProducerProviderManager.class)); + SCBEngine.getInstance().setConsumerProviderManager(applicationContext.getBean(ConsumerProviderManager.class)); + SCBEngine.getInstance().setTransportManager(applicationContext.getBean(TransportManager.class)); + SCBEngine.getInstance().setSchemaListenerManager(applicationContext.getBean(SchemaListenerManager.class)); + SCBEngine.getInstance().setBootListenerList(applicationContext.getBeansOfType(BootListener.class).values()); + } - //Step 3: wait all invocation finished - try { - ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.acquire(); - LOGGER.warn("all invocation finished"); - } catch (InterruptedException e) { - LOGGER.error("invocation finished semaphore interrupted", e); + SCBEngine.getInstance().init(); } - - //Step 4: Stop vertx to prevent blocking exit - VertxUtils.closeVertxByName("config-center"); - VertxUtils.closeVertxByName("transport"); - - //Step 5: notify all component do clean works via AFTER_CLOSE Event - triggerEvent(EventType.AFTER_CLOSE); - } - - - /** - *

As the process of instance registry is asynchronous, the {@code AFTER_REGISTRY} - * event should not be sent immediately after {@link RegistryUtils#run()} is invoked. - * When the instance registry succeeds, {@link MicroserviceInstanceRegisterTask} will be posted in {@link EventManager}, - * register a subscriber to watch this event and send {@code AFTER_REGISTRY}.

- * - *

This method should be called before {@link RegistryUtils#run()} to avoid that the registry process is too quick - * that the event is not watched by this subscriber.

- * - *

Check if {@code InstanceId} is null to judge whether the instance registry has succeeded.

- */ - private void triggerAfterRegistryEvent() { - EventManager.register(new Object() { - @Subscribe - public void afterRegistryInstance(MicroserviceInstanceRegisterTask microserviceInstanceRegisterTask) { - LOGGER.info("receive MicroserviceInstanceRegisterTask event, check instance Id..."); - if (!StringUtils.isEmpty(RegistryUtils.getMicroserviceInstance().getInstanceId())) { - LOGGER.info("instance registry succeeds for the first time, will send AFTER_REGISTRY event."); - ReferenceConfigUtils.setReady(true); - triggerEvent(EventType.AFTER_REGISTRY); - EventManager.unregister(this); - } - } - }); } } diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java new file mode 100644 index 00000000000..f1411e1ab8d --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java @@ -0,0 +1,305 @@ +/* + * 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.core; + +import java.util.Collection; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicLong; + +import org.apache.servicecomb.core.BootListener.BootEvent; +import org.apache.servicecomb.core.BootListener.EventType; +import org.apache.servicecomb.core.definition.loader.SchemaListenerManager; +import org.apache.servicecomb.core.endpoint.AbstractEndpointsCache; +import org.apache.servicecomb.core.event.InvocationFinishEvent; +import org.apache.servicecomb.core.event.InvocationStartEvent; +import org.apache.servicecomb.core.handler.HandlerConfigUtils; +import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager; +import org.apache.servicecomb.core.provider.producer.ProducerProviderManager; +import org.apache.servicecomb.core.transport.TransportManager; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.foundation.vertx.VertxUtils; +import org.apache.servicecomb.serviceregistry.RegistryUtils; +import org.apache.servicecomb.serviceregistry.task.MicroserviceInstanceRegisterTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import com.google.common.eventbus.AllowConcurrentEvents; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; + +// TODO: should not depend on spring, that will make integration more flexible +public class SCBEngine { + private static final Logger LOGGER = LoggerFactory.getLogger(SCBEngine.class); + + private ProducerProviderManager producerProviderManager; + + private ConsumerProviderManager consumerProviderManager; + + private TransportManager transportManager; + + private SchemaListenerManager schemaListenerManager; + + private Collection bootListenerList; + + private final AtomicLong invocationStartedCounter = new AtomicLong(); + + private final AtomicLong invocationFinishedCounter = new AtomicLong(); + + private final Semaphore allInvocationFinished = new Semaphore(1); + + private volatile SCBStatus status = SCBStatus.DOWN; + + public void setStatus(SCBStatus status) { + this.status = status; + } + + private EventBus eventBus = EventManager.getEventBus(); + + private static final SCBEngine INSTANCE = new SCBEngine(); + + public static SCBEngine getInstance() { + return INSTANCE; + } + + public void setProducerProviderManager( + ProducerProviderManager producerProviderManager) { + this.producerProviderManager = producerProviderManager; + } + + public void setConsumerProviderManager( + ConsumerProviderManager consumerProviderManager) { + this.consumerProviderManager = consumerProviderManager; + } + + public TransportManager getTransportManager() { + return transportManager; + } + + public void setTransportManager(TransportManager transportManager) { + this.transportManager = transportManager; + } + + public void setSchemaListenerManager( + SchemaListenerManager schemaListenerManager) { + this.schemaListenerManager = schemaListenerManager; + } + + public Collection getBootListenerList() { + return bootListenerList; + } + + public void setBootListenerList(Collection bootListenerList) { + this.bootListenerList = bootListenerList; + } + + protected void triggerEvent(EventType eventType) { + BootEvent event = new BootEvent(); + event.setEventType(eventType); + + for (BootListener listener : bootListenerList) { + listener.onBootEvent(event); + } + } + + protected void safeTriggerEvent(EventType eventType) { + BootEvent event = new BootEvent(); + event.setEventType(eventType); + + for (BootListener listener : bootListenerList) { + try { + listener.onBootEvent(event); + LOGGER.error("BootListener {} succeed to process {}.", listener.getClass().getName(), eventType); + } catch (Throwable e) { + LOGGER.error("BootListener {} failed to process {}.", listener.getClass().getName(), eventType, e); + } + } + } + + /** + *

As the process of instance registry is asynchronous, the {@code AFTER_REGISTRY} + * event should not be sent immediately after {@link RegistryUtils#run()} is invoked. + * When the instance registry succeeds, {@link MicroserviceInstanceRegisterTask} will be posted in {@link EventManager}, + * register a subscriber to watch this event and send {@code AFTER_REGISTRY}.

+ * + *

This method should be called before {@link RegistryUtils#run()} to avoid that the registry process is too quick + * that the event is not watched by this subscriber.

+ * + *

Check if {@code InstanceId} is null to judge whether the instance registry has succeeded.

+ */ + private void triggerAfterRegistryEvent() { + EventManager.register(new Object() { + @Subscribe + public void afterRegistryInstance(MicroserviceInstanceRegisterTask microserviceInstanceRegisterTask) { + LOGGER.info("receive MicroserviceInstanceRegisterTask event, check instance Id..."); + if (!StringUtils.isEmpty(RegistryUtils.getMicroserviceInstance().getInstanceId())) { + LOGGER.info("instance registry succeeds for the first time, will send AFTER_REGISTRY event."); + status = SCBStatus.UP; + triggerEvent(EventType.AFTER_REGISTRY); + EventManager.unregister(this); + } + } + }); + } + + @AllowConcurrentEvents + @Subscribe + public void onInvocationStart(InvocationStartEvent event) { + invocationStartedCounter.incrementAndGet(); + } + + @AllowConcurrentEvents + @Subscribe + public void onInvocationFinish(InvocationFinishEvent event) { + invocationFinishedCounter.incrementAndGet(); + if (validIsStopping()) { + validAllInvocationFinished(); + } + } + + public synchronized void init() { + if (validIsDown()) { + try { + doInit(); + status = SCBStatus.UP; + } catch (Exception e) { + uninit(); + status = SCBStatus.FAILED; + throw new IllegalStateException("ServiceComb init failed.", e); + } + } + } + + + private void doInit() throws Exception { + status = SCBStatus.STARTING; + + eventBus.register(this); + + allInvocationFinished.acquire(); + + AbstractEndpointsCache.init(RegistryUtils.getInstanceCacheManager(), transportManager); + + triggerEvent(EventType.BEFORE_HANDLER); + HandlerConfigUtils.init(); + triggerEvent(EventType.AFTER_HANDLER); + + triggerEvent(EventType.BEFORE_PRODUCER_PROVIDER); + producerProviderManager.init(); + triggerEvent(EventType.AFTER_PRODUCER_PROVIDER); + + triggerEvent(EventType.BEFORE_CONSUMER_PROVIDER); + consumerProviderManager.init(); + triggerEvent(EventType.AFTER_CONSUMER_PROVIDER); + + triggerEvent(EventType.BEFORE_TRANSPORT); + transportManager.init(); + triggerEvent(EventType.AFTER_TRANSPORT); + + schemaListenerManager.notifySchemaListener(); + + triggerEvent(EventType.BEFORE_REGISTRY); + + triggerAfterRegistryEvent(); + + RegistryUtils.run(); + + Runtime.getRuntime().addShutdownHook(new Thread(this::uninit)); + } + + /** + * not allow throw any exception + * even some step throw exception, must catch it and go on, otherwise shutdown process will be broken. + */ + public synchronized void uninit() { + if (validIsUp()) { + LOGGER.info("ServiceComb is closing now..."); + try { + doUninit(); + status = SCBStatus.DOWN; + } catch (Exception e) { + status = SCBStatus.FAILED; + LOGGER.info("ServiceComb failed shutdown", e); + } + } + } + + private void doUninit() throws Exception { + //Step 1: notify all component stop invoke via BEFORE_CLOSE Event + safeTriggerEvent(EventType.BEFORE_CLOSE); + + status = SCBStatus.STOPPING; + + //Step 2: Unregister microservice instance from Service Center and close vertx + // Forbidden other consumers find me + RegistryUtils.destroy(); + VertxUtils.blockCloseVertxByName("registry"); + + //Step 3: wait all invocation finished + // forbit create new consumer invocation + validAllInvocationFinished(); + allInvocationFinished.acquire(); + + //Step 4: Stop vertx to prevent blocking exit + VertxUtils.blockCloseVertxByName("config-center"); + VertxUtils.blockCloseVertxByName("transport"); + + //Step 5: notify all component do clean works via AFTER_CLOSE Event + safeTriggerEvent(EventType.AFTER_CLOSE); + + //Step 6: Clean flags for re-init + eventBus.unregister(this); + allInvocationFinished.release(); + } + + private void validAllInvocationFinished() { + LOGGER.info("valid for all invocation finished, request count: {}, response count: {}.", + invocationStartedCounter.get(), + invocationFinishedCounter.get()); + if (invocationFinishedCounter.get() == invocationStartedCounter.get()) { + allInvocationFinished.release(); + } + } + + public void assertIsStopping() { + if (validIsStopping()) { + throw new IllegalStateException( + "shutting down in progress, it's better to implement " + BootListener.class.getName() + + " and stop ... in EventType.BEFORE_CLOSE."); + } + } + + private boolean validIsStopping() { + return SCBStatus.STOPPING.equals(status); + } + + public void assertIsUp() { + if (!SCBStatus.UP.equals(status)) { + throw new IllegalStateException("System is not ready for remote calls. " + + "When beans are making remote calls in initialization, it's better to " + + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."); + } + } + + private boolean validIsUp() { + return SCBStatus.UP.equals(status); + } + + private boolean validIsDown() { + return SCBStatus.DOWN.equals(status); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBStatus.java b/core/src/main/java/org/apache/servicecomb/core/SCBStatus.java new file mode 100644 index 00000000000..62551eb1108 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/SCBStatus.java @@ -0,0 +1,32 @@ +/* + * 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.core; + +//DOWN -> STARTING -> UP -> STOPPING -> DOWN +public enum SCBStatus { + //Chassis is Down + DOWN, + //Chassis is Starting (progressing) + STARTING, + //Chassis is Running + UP, + //Chassis is Stopping (progressing) + STOPPING, + //Chassis Init Failed + FAILED +} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/AbstractHandlerManager.java b/core/src/main/java/org/apache/servicecomb/core/handler/AbstractHandlerManager.java index 3b49bc19d11..20c72b48977 100644 --- a/core/src/main/java/org/apache/servicecomb/core/handler/AbstractHandlerManager.java +++ b/core/src/main/java/org/apache/servicecomb/core/handler/AbstractHandlerManager.java @@ -86,8 +86,6 @@ private List createHandlerChain(String chainDef) { List> chainClasses = convertToChainClass(chainDef); List handlerList = new ArrayList<>(); - handlerList.add(ShutdownHookHandler.INSTANCE); - for (Class cls : chainClasses) { try { handlerList.add(cls.newInstance()); diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java b/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java deleted file mode 100644 index 4b284a4cb08..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/handler/ShutdownHookHandler.java +++ /dev/null @@ -1,99 +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.core.handler; - -import java.util.concurrent.Semaphore; -import java.util.concurrent.atomic.AtomicLong; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 实现调用链的优雅停止: 当调用链没有返回的时候,等待返回(由于Consumer存在超时,所以必定能够返回) - */ -public final class ShutdownHookHandler implements Handler, Runnable { - private static final Logger LOG = LoggerFactory.getLogger(ShutdownHookHandler.class); - - public static final ShutdownHookHandler INSTANCE = new ShutdownHookHandler(); - - private final AtomicLong requestCounter = new AtomicLong(0); - - private final AtomicLong responseCounter = new AtomicLong(0); - - private volatile boolean shuttingDown = false; - - public final Semaphore ALL_INVOCATION_FINISHED = new Semaphore(1); - - private ShutdownHookHandler() { - try { - ALL_INVOCATION_FINISHED.acquire(); - } catch (InterruptedException e) { - throw new ServiceCombException("init invocation finished semaphore failed", e); - } - Runtime.getRuntime().addShutdownHook(new Thread(this)); - } - - public long getActiveCount() { - return requestCounter.get() - responseCounter.get(); - } - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - if (shuttingDown) { - asyncResp.handle(Response.createFail(invocation.getInvocationType(), - "shutting down in progress")); - return; - } - - // TODO:统计功能应该独立出来,在链中统计,会有各种bug - // 下面的两次catch,可能会导致一次请求,对应2次应答 - requestCounter.incrementAndGet(); - try { - invocation.next(resp -> { - try { - asyncResp.handle(resp); - } finally { - responseCounter.incrementAndGet(); - validAllInvocationFinished(); - } - }); - } catch (Throwable e) { - responseCounter.incrementAndGet(); - validAllInvocationFinished(); - throw e; - } - } - - private synchronized void validAllInvocationFinished() { - if (shuttingDown && getActiveCount() <= 0) { - ALL_INVOCATION_FINISHED.release(); - } - } - - @Override - public void run() { - shuttingDown = true; - LOG.warn("handler chain is shutting down..."); - validAllInvocationFinished(); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigUtils.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigUtils.java index fe8d254b4f0..b0bf2d299e4 100644 --- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigUtils.java +++ b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigUtils.java @@ -17,38 +17,18 @@ package org.apache.servicecomb.core.provider.consumer; -import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.CseContext; -import org.springframework.stereotype.Component; +import org.apache.servicecomb.core.SCBEngine; -@Component public class ReferenceConfigUtils { - private static boolean ready; - - public static void setReady(boolean ready) { - ReferenceConfigUtils.ready = ready; - } - - private static void assertIsReady() { - if (!ready) { - throw new IllegalStateException("System is not ready for remote calls. " - + "When beans are making remote calls in initialization, it's better to " - + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."); - } - } - public static ReferenceConfig getForInvoke(String microserviceName) { - assertIsReady(); - + SCBEngine.getInstance().assertIsUp(); return CseContext.getInstance().getConsumerProviderManager().getReferenceConfig(microserviceName); } - public static ReferenceConfig getForInvoke(String microserviceName, String microserviceVersion, - String transport) { - assertIsReady(); - + public static ReferenceConfig getForInvoke(String microserviceName, String microserviceVersion, String transport) { + SCBEngine.getInstance().assertIsUp(); return CseContext.getInstance().getConsumerProviderManager().createReferenceConfig(microserviceName, - microserviceVersion, - transport); + microserviceVersion, transport); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java b/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java deleted file mode 100644 index 43fd873f319..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java +++ /dev/null @@ -1,248 +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.core; - -import static org.junit.Assert.fail; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.ws.Holder; - -import org.apache.commons.lang3.reflect.FieldUtils; -import org.apache.servicecomb.core.BootListener.BootEvent; -import org.apache.servicecomb.core.BootListener.EventType; -import org.apache.servicecomb.core.definition.loader.SchemaListenerManager; -import org.apache.servicecomb.core.endpoint.AbstractEndpointsCache; -import org.apache.servicecomb.core.handler.ShutdownHookHandler; -import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager; -import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils; -import org.apache.servicecomb.core.provider.producer.ProducerProviderManager; -import org.apache.servicecomb.core.transport.TransportManager; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.ReflectUtils; -import org.apache.servicecomb.serviceregistry.RegistryUtils; -import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.serviceregistry.task.MicroserviceInstanceRegisterTask; -import org.hamcrest.Matchers; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.mockito.Mockito; -import org.springframework.context.ApplicationContext; -import org.springframework.context.event.ContextClosedEvent; -import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.context.support.AbstractApplicationContext; - -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Injectable; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestCseApplicationListener { - static ApplicationContext orgContext; - - @BeforeClass - public static void classSetup() { - orgContext = BeanUtils.getContext(); - } - - @AfterClass - public static void teardown() { - AbstractEndpointsCache.init(null, null); - BeanUtils.setContext(orgContext); - } - - @After - public void cleanup() { - Deencapsulation.setField(ReferenceConfigUtils.class, "ready", false); - } - - @Test - public void testCseApplicationListenerNormal(@Injectable ContextRefreshedEvent event, - @Injectable AbstractApplicationContext context, - @Injectable ProducerProviderManager producerProviderManager, - @Injectable ConsumerProviderManager consumerProviderManager, - @Injectable TransportManager transportManager, - @Mocked RegistryUtils ru) { - Map listeners = new HashMap<>(); - BootListener listener = Mockito.mock(BootListener.class); - listeners.put("test", listener); - - SchemaListenerManager schemaListenerManager = Mockito.mock(SchemaListenerManager.class); - MicroserviceInstance microserviceInstance = Mockito.mock(MicroserviceInstance.class); - - new Expectations() { - { - context.getBeansOfType(BootListener.class); - result = listeners; - } - }; - new Expectations(RegistryUtils.class) { - { - RegistryUtils.init(); - RegistryUtils.getInstanceCacheManager(); - RegistryUtils.run(); - RegistryUtils.getMicroserviceInstance(); - result = microserviceInstance; - } - }; - Mockito.when(microserviceInstance.getInstanceId()).thenReturn("testInstanceId"); - - CseApplicationListener cal = new CseApplicationListener(); - Deencapsulation.setField(cal, "schemaListenerManager", schemaListenerManager); - cal.setInitEventClass(ContextRefreshedEvent.class); - cal.setApplicationContext(context); - ReflectUtils.setField(cal, "producerProviderManager", producerProviderManager); - ReflectUtils.setField(cal, "consumerProviderManager", consumerProviderManager); - ReflectUtils.setField(cal, "transportManager", transportManager); - - cal.onApplicationEvent(event); - - EventManager.post(Mockito.mock(MicroserviceInstanceRegisterTask.class)); - verify(schemaListenerManager).notifySchemaListener(); - verify(listener, times(10)).onBootEvent(Mockito.any(BootEvent.class)); - } - - @Test - public void testCseApplicationListenerThrowException(@Injectable ContextRefreshedEvent event, - @Injectable AbstractApplicationContext context, - @Injectable BootListener listener, - @Injectable ProducerProviderManager producerProviderManager, - @Mocked RegistryUtils ru) { - Map listeners = new HashMap<>(); - listeners.put("test", listener); - - CseApplicationListener cal = new CseApplicationListener(); - cal.setApplicationContext(context); - ReflectUtils.setField(cal, "producerProviderManager", producerProviderManager); - cal.onApplicationEvent(event); - } - - @Test - public void testCseApplicationListenerParentNotnull(@Injectable ContextRefreshedEvent event, - @Injectable AbstractApplicationContext context, - @Injectable AbstractApplicationContext pContext, - @Mocked RegistryUtils ru) { - - CseApplicationListener cal = new CseApplicationListener(); - cal.setApplicationContext(context); - cal.onApplicationEvent(event); - } - - @Test - public void testCseApplicationListenerShutdown(@Mocked ApplicationContext context) throws IllegalAccessException { - Holder destroyHolder = new Holder<>(); - new MockUp() { - @Mock - void destroy() { - destroyHolder.value = true; - } - }; - CseApplicationListener cal = new CseApplicationListener(); - ContextClosedEvent event = new ContextClosedEvent(context); - - ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); - - List eventTypes = new ArrayList<>(); - BootListener bootListener = e -> { - eventTypes.add(e.getEventType()); - }; - FieldUtils.writeField(cal, "bootListenerList", Arrays.asList(bootListener), true); - cal.onApplicationEvent(event); - - Assert.assertTrue(destroyHolder.value); - Assert.assertThat(eventTypes, Matchers.contains(EventType.BEFORE_CLOSE, EventType.AFTER_CLOSE)); - } - - @Test - public void testTriggerAfterRegistryEvent() { - CseApplicationListener cal = new CseApplicationListener(); - - Collection listeners = new ArrayList<>(1); - BootListener listener = Mockito.mock(BootListener.class); - listeners.add(listener); - Deencapsulation.setField(cal, "bootListenerList", listeners); - - MicroserviceInstance microserviceInstance = Mockito.mock(MicroserviceInstance.class); - new Expectations(RegistryUtils.class) { - { - RegistryUtils.getMicroserviceInstance(); - result = microserviceInstance; - } - }; - Mockito.when(microserviceInstance.getInstanceId()).thenReturn("testInstanceId"); - - Deencapsulation.invoke(cal, "triggerAfterRegistryEvent"); - - EventManager.post(Mockito.mock(MicroserviceInstanceRegisterTask.class)); - - Deencapsulation.invoke(ReferenceConfigUtils.class, "assertIsReady"); - - // AFTER_REGISTRY event should only be sent at the first time of registry success. - EventManager.post(Mockito.mock(MicroserviceInstanceRegisterTask.class)); - verify(listener, times(1)).onBootEvent(Mockito.any(BootEvent.class)); - } - - @Test - public void testTriggerAfterRegistryEventOnInstanceIdIsNull() { - CseApplicationListener cal = new CseApplicationListener(); - - Collection listeners = new ArrayList<>(1); - BootListener listener = Mockito.mock(BootListener.class); - listeners.add(listener); - Deencapsulation.setField(cal, "bootListenerList", listeners); - - MicroserviceInstance microserviceInstance = Mockito.mock(MicroserviceInstance.class); - new Expectations(RegistryUtils.class) { - { - RegistryUtils.getMicroserviceInstance(); - result = microserviceInstance; - } - }; - Mockito.when(microserviceInstance.getInstanceId()).thenReturn(null).thenReturn("testInstanceId"); - - Deencapsulation.invoke(cal, "triggerAfterRegistryEvent"); - - EventManager.post(Mockito.mock(MicroserviceInstanceRegisterTask.class)); - - try { - Deencapsulation.invoke(ReferenceConfigUtils.class, "assertIsReady"); - fail("an exception is expected."); - } catch (Exception e) { - Assert.assertEquals(IllegalStateException.class, e.getClass()); - } - verify(listener, times(0)).onBootEvent(Mockito.any(BootEvent.class)); - - // AFTER_REGISTRY event should only be sent at the first time of registry success. - EventManager.post(Mockito.mock(MicroserviceInstanceRegisterTask.class)); - Deencapsulation.invoke(ReferenceConfigUtils.class, "assertIsReady"); - verify(listener, times(1)).onBootEvent(Mockito.any(BootEvent.class)); - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/handler/TestShutdownHookHandler.java b/core/src/test/java/org/apache/servicecomb/core/handler/TestShutdownHookHandler.java deleted file mode 100644 index 00b767a8d6c..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/handler/TestShutdownHookHandler.java +++ /dev/null @@ -1,141 +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.core.handler; - -import java.lang.reflect.Field; -import java.util.concurrent.atomic.AtomicLong; - -import javax.xml.ws.Holder; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.InvocationType; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.Assert; -import org.junit.Test; -import org.springframework.util.ReflectionUtils; - -import mockit.Deencapsulation; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestShutdownHookHandler { - static Field requestCountField = ReflectionUtils.findField(ShutdownHookHandler.class, "requestCounter"); - - static { - requestCountField.setAccessible(true); - } - - static AtomicLong requestCounter = - (AtomicLong) ReflectionUtils.getField(requestCountField, ShutdownHookHandler.INSTANCE); - - @Test - public void testShutdownHookHandlerCount(@Mocked Response response) throws Exception { - Deencapsulation.setField(ShutdownHookHandler.INSTANCE, "shuttingDown", false); - - ShutdownHookHandler handler = ShutdownHookHandler.INSTANCE; - Assert.assertEquals(0, handler.getActiveCount()); - - // no reply - Invocation invocation = new MockUp() { - @Mock - public void next(AsyncResponse asyncResp) throws Exception { - } - }.getMockInstance(); - handler.handle(invocation, asyncResp -> { - }); - Assert.assertEquals(1, requestCounter.get()); - Assert.assertEquals(1, handler.getActiveCount()); - - // normal - invocation = new MockUp() { - @Mock - public void next(AsyncResponse asyncResp) throws Exception { - asyncResp.handle(response); - } - }.getMockInstance(); - handler.handle(invocation, asyncResp -> { - }); - Assert.assertEquals(2, requestCounter.get()); - Assert.assertEquals(1, handler.getActiveCount()); - - // next exception - invocation = new MockUp() { - @Mock - public void next(AsyncResponse asyncResp) throws Exception { - throw new Error(); - } - }.getMockInstance(); - try { - handler.handle(invocation, asyncResp -> { - }); - Assert.assertFalse(true); - } catch (Throwable e) { - Assert.assertEquals(3, requestCounter.get()); - Assert.assertEquals(1, handler.getActiveCount()); - } - - AtomicLong responseCounter = Deencapsulation.getField(ShutdownHookHandler.INSTANCE, "responseCounter"); - responseCounter.incrementAndGet(); - Assert.assertEquals(0, handler.getActiveCount()); - - // reply exception - // TODO: should be fixed - // try { - // handler.handle(invocation, asyncResp -> { - // throw new Error(); - // }); - // - // Assert.assertFalse(true); - // } catch (Throwable e) { - // Assert.assertEquals(3, requestCounter.get()); - // Assert.assertEquals(1, handler.getActiveCount()); - // } - } - - @Test - public void testShutdownHookHandlerReject() throws Exception { - Deencapsulation.setField(ShutdownHookHandler.INSTANCE, "shuttingDown", true); - Holder typeHolder = new Holder<>(InvocationType.PRODUCER); - Invocation invocation = new MockUp() { - @Mock - public InvocationType getInvocationType() { - return typeHolder.value; - } - }.getMockInstance(); - - ShutdownHookHandler handler = ShutdownHookHandler.INSTANCE; - handler.handle(invocation, asyncResp -> { - InvocationException e = asyncResp.getResult(); - Assert.assertEquals(((CommonExceptionData) e.getErrorData()).getMessage(), - "shutting down in progress"); - Assert.assertEquals(e.getStatusCode(), 590); - }); - - typeHolder.value = InvocationType.CONSUMER; - handler.handle(invocation, asyncResp -> { - InvocationException e = asyncResp.getResult(); - Assert.assertEquals(((CommonExceptionData) e.getErrorData()).getMessage(), - "shutting down in progress"); - Assert.assertEquals(e.getStatusCode(), 490); - }); - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java index d975e65e981..16adde75002 100644 --- a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java +++ b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java @@ -22,6 +22,8 @@ import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.SCBStatus; import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.core.invocation.InvocationFactory; @@ -43,13 +45,13 @@ public class TestInvokerUtils { @Test - public void testSyncInvokeInvocationWithException() throws InterruptedException { + public void testSyncInvokeInvocationWithException() { Invocation invocation = Mockito.mock(Invocation.class); Response response = Mockito.mock(Response.class); new MockUp() { @Mock - public Response waitResponse() throws InterruptedException { + public Response waitResponse() { return Mockito.mock(Response.class); } }; @@ -80,7 +82,6 @@ void next(AsyncResponse asyncResp) { } }; - Holder holder = new Holder<>(); InvokerUtils.reactiveInvoke(invocation, ar -> { holder.value = ContextUtils.getInvocationContext(); @@ -105,15 +106,16 @@ Object syncInvoke(Invocation invocation) { @Test public void tetSyncInvokeNotReady() { - ReferenceConfigUtils.setReady(false); + + SCBEngine.getInstance().setStatus(SCBStatus.DOWN); try { InvokerUtils.syncInvoke("ms", "schemaId", "opName", null); Assert.fail("must throw exception"); } catch (IllegalStateException e) { Assert.assertEquals("System is not ready for remote calls. " - + "When beans are making remote calls in initialization, it's better to " - + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY.", + + "When beans are making remote calls in initialization, it's better to " + + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY.", e.getMessage()); } @@ -122,8 +124,8 @@ public void tetSyncInvokeNotReady() { Assert.fail("must throw exception"); } catch (IllegalStateException e) { Assert.assertEquals("System is not ready for remote calls. " - + "When beans are making remote calls in initialization, it's better to " - + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY.", + + "When beans are making remote calls in initialization, it's better to " + + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY.", e.getMessage()); } } @@ -131,7 +133,9 @@ public void tetSyncInvokeNotReady() { @Test public void tetSyncInvokeReady(@Injectable ConsumerProviderManager consumerProviderManager, @Injectable Invocation invocation) { - ReferenceConfigUtils.setReady(true); + + SCBEngine.getInstance().setStatus(SCBStatus.UP); + CseContext.getInstance().setConsumerProviderManager(consumerProviderManager); new Expectations(InvocationFactory.class) { diff --git a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfigUtils.java b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfigUtils.java index fbe664c43fd..b31ee58cbea 100644 --- a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfigUtils.java +++ b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfigUtils.java @@ -18,6 +18,8 @@ import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.CseContext; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.SCBStatus; import org.junit.Assert; import org.junit.Test; @@ -30,7 +32,8 @@ public void testNotReady() { + "When beans are making remote calls in initialization, it's better to " + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."; - ReferenceConfigUtils.setReady(false); + SCBEngine.getInstance().setStatus(SCBStatus.DOWN); + try { ReferenceConfigUtils.getForInvoke("abc"); Assert.fail("must throw exception"); @@ -48,7 +51,9 @@ public void testNotReady() { @Test public void testReady(@Injectable ConsumerProviderManager consumerProviderManager) { - ReferenceConfigUtils.setReady(true); + + SCBEngine.getInstance().setStatus(SCBStatus.UP); + CseContext.getInstance().setConsumerProviderManager(consumerProviderManager); Assert.assertNotNull(ReferenceConfigUtils.getForInvoke("abc")); diff --git a/demo/perf/src/main/resources/microservice.yaml b/demo/perf/src/main/resources/microservice.yaml index e597667c132..254a85be9e0 100644 --- a/demo/perf/src/main/resources/microservice.yaml +++ b/demo/perf/src/main/resources/microservice.yaml @@ -39,10 +39,10 @@ servicecomb: thread-count: 8 references: transport: rest -servicecomb: metrics: window_time: 1000 - +servicecomb.metrics.publisher.defaultLog.enabled: true + sync-count: 10 async-count: 20 sync: false diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java index d5e55f463d4..5d4709fe2a1 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java @@ -21,6 +21,7 @@ import java.io.InputStream; import java.lang.management.ManagementFactory; import java.util.Map; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import javax.xml.ws.Holder; @@ -157,13 +158,6 @@ public static Vertx getVertxByName(String name) { return vertxMap.get(name); } - public static void closeVertxByName(String name) { - Vertx vertx = vertxMap.remove(name); - if (vertx != null) { - vertx.close(); - } - } - public static void runInContext(Context context, AsyncResultCallback callback, T result, Throwable e) { if (context == Vertx.currentContext()) { complete(callback, result, e); @@ -205,4 +199,35 @@ public static byte[] getBytesFast(ByteBuf byteBuf) { byteBuf.getBytes(0, arr); return arr; } + + public static CompletableFuture closeVertxByName(String name) { + LOGGER.info("Closing vertx {}.", name); + CompletableFuture future = new CompletableFuture<>(); + Vertx vertx = vertxMap.remove(name); + if (vertx == null) { + LOGGER.info("Vertx {} not exist.", name); + future.complete(null); + return future; + } + + vertx.close(ar -> { + if (ar.succeeded()) { + LOGGER.info("Success to close vertx {}.", name); + future.complete(null); + return; + } + + future.completeExceptionally(ar.cause()); + }); + return future; + } + + public static void blockCloseVertxByName(String name) { + CompletableFuture future = closeVertxByName(name); + try { + future.get(); + } catch (Throwable e) { + LOGGER.error("Failed to close vertx {}.", name, e); + } + } } diff --git a/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java index c0caef64c15..fbbf181375d 100644 --- a/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java +++ b/integration-tests/springmvc-tests/springmvc-tests-general-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringIntegrationTest.java @@ -17,29 +17,24 @@ package org.apache.servicecomb.demo.springmvc.tests; -import org.apache.servicecomb.core.handler.ShutdownHookHandler; +import org.apache.servicecomb.core.SCBEngine; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.runner.RunWith; import org.springframework.boot.SpringApplication; -import org.springframework.context.ConfigurableApplicationContext; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) public class SpringMvcSpringIntegrationTest extends SpringMvcIntegrationTestBase { - private static ConfigurableApplicationContext context; - @BeforeClass public static void init() { System.setProperty("cse.uploads.directory", "/tmp"); setUpLocalRegistry(); - context = SpringApplication.run(SpringMvcSpringMain.class); + SpringApplication.run(SpringMvcSpringMain.class); } @AfterClass public static void shutdown() { - //sim system.exit(0) - ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); - context.close(); + SCBEngine.getInstance().uninit(); } } diff --git a/integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java index c0fc7e3a74e..7a49b20b610 100644 --- a/integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java +++ b/integration-tests/springmvc-tests/springmvc-tests-general/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcIntegrationTest.java @@ -17,12 +17,9 @@ package org.apache.servicecomb.demo.springmvc.tests; -import org.apache.servicecomb.core.CseApplicationListener; -import org.apache.servicecomb.core.handler.ShutdownHookHandler; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.apache.servicecomb.core.SCBEngine; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.springframework.context.event.ContextClosedEvent; public class RawSpringMvcIntegrationTest extends SpringMvcIntegrationTestBase { @@ -35,10 +32,6 @@ public static void init() throws Exception { @AfterClass public static void shutdown() { - //sim system.exit(0) - ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); - CseApplicationListener cal = BeanUtils.getBean("org.apache.servicecomb.core.CseApplicationListener"); - ContextClosedEvent event = new ContextClosedEvent(BeanUtils.getContext()); - cal.onApplicationEvent(event); + SCBEngine.getInstance().uninit(); } } diff --git a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java index dfc0ca8b746..292f9264d01 100644 --- a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping-with-springboot/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest.java @@ -17,30 +17,25 @@ package org.apache.servicecomb.demo.springmvc.tests; -import org.apache.servicecomb.core.handler.ShutdownHookHandler; +import org.apache.servicecomb.core.SCBEngine; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.runner.RunWith; import org.springframework.boot.SpringApplication; -import org.springframework.context.ConfigurableApplicationContext; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) public class SpringMvcSpringSimplifiedMappingAnnotationIntegrationTest extends SpringMvcIntegrationTestBase { - private static ConfigurableApplicationContext context; - @BeforeClass public static void init() { System.setProperty("spring.profiles.active", "SimplifiedMapping"); System.setProperty("cse.uploads.directory", "/tmp"); setUpLocalRegistry(); - context = SpringApplication.run(SpringMvcSpringMain.class); + SpringApplication.run(SpringMvcSpringMain.class); } @AfterClass public static void shutdown() { - //sim system.exit(0) - ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); - context.close(); + SCBEngine.getInstance().uninit(); } } diff --git a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java index d6d2cfc9404..35cdbd8c218 100644 --- a/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java +++ b/integration-tests/springmvc-tests/springmvc-tests-simplified-mapping/src/test/java/org/apache/servicecomb/demo/springmvc/tests/RawSpringMvcSimplifiedMappingAnnotationIntegrationTest.java @@ -17,12 +17,9 @@ package org.apache.servicecomb.demo.springmvc.tests; -import org.apache.servicecomb.core.CseApplicationListener; -import org.apache.servicecomb.core.handler.ShutdownHookHandler; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.apache.servicecomb.core.SCBEngine; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.springframework.context.event.ContextClosedEvent; public class RawSpringMvcSimplifiedMappingAnnotationIntegrationTest extends SpringMvcIntegrationTestBase { @@ -36,10 +33,6 @@ public static void init() throws Exception { @AfterClass public static void shutdown() { - //sim system.exit(0) - ShutdownHookHandler.INSTANCE.ALL_INVOCATION_FINISHED.release(); - CseApplicationListener cal = BeanUtils.getBean("org.apache.servicecomb.core.CseApplicationListener"); - ContextClosedEvent event = new ContextClosedEvent(BeanUtils.getContext()); - cal.onApplicationEvent(event); + SCBEngine.getInstance().uninit(); } } diff --git a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java index 905d938512f..1dd25e2d9de 100644 --- a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java +++ b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java @@ -24,6 +24,7 @@ import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.core.invocation.InvocationFactory; @@ -84,7 +85,7 @@ protected void prepare() { } @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + public Object invoke(Object proxy, Method method, Object[] args) { if (swaggerConsumer == null) { synchronized (this) { if (swaggerConsumer == null) { @@ -93,6 +94,8 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl } } + SCBEngine.getInstance().assertIsStopping(); + SwaggerConsumerOperation consumerOperation = swaggerConsumer.findOperation(method.getName()); Invocation invocation = InvocationFactory diff --git a/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java b/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java index 3264e665557..715edccc440 100644 --- a/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java +++ b/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java @@ -22,12 +22,13 @@ import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.SCBStatus; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.definition.schema.ConsumerSchemaFactory; import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager; import org.apache.servicecomb.core.provider.consumer.InvokerUtils; import org.apache.servicecomb.core.provider.consumer.ReferenceConfig; -import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils; import org.apache.servicecomb.swagger.engine.SwaggerConsumer; import org.apache.servicecomb.swagger.engine.SwaggerConsumerOperation; import org.apache.servicecomb.swagger.engine.bootstrap.BootstrapNormal; @@ -56,12 +57,12 @@ public class TestInvoker { @Before public void setup() { - ReferenceConfigUtils.setReady(true); + SCBEngine.getInstance().setStatus(SCBStatus.UP); } @After public void teardown() { - ReferenceConfigUtils.setReady(false); + SCBEngine.getInstance().setStatus(SCBStatus.DOWN); } @Test @@ -70,7 +71,8 @@ public void testNotReady() throws Throwable { + "When beans are making remote calls in initialization, it's better to " + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."; - ReferenceConfigUtils.setReady(false); + SCBEngine.getInstance().setStatus(SCBStatus.DOWN); + Invoker invoker = new Invoker("test", "schemaId", IPerson.class); try { diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java index 947469d3ddb..a64d794705a 100644 --- a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java @@ -30,6 +30,7 @@ import org.apache.servicecomb.common.rest.locator.OperationLocator; import org.apache.servicecomb.common.rest.locator.ServicePathManager; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.invocation.InvocationFactory; import org.apache.servicecomb.core.provider.consumer.InvokerUtils; @@ -148,6 +149,9 @@ public ClientHttpResponse execute() { protected RequestMeta createRequestMeta(String httpMetod, URI uri) { String microserviceName = uri.getAuthority(); + + SCBEngine.getInstance().assertIsStopping(); + ReferenceConfig referenceConfig = ReferenceConfigUtils.getForInvoke(microserviceName); MicroserviceMeta microserviceMeta = referenceConfig.getMicroserviceMeta(); diff --git a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java index a1d7271eedb..fe32d992bc8 100644 --- a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java +++ b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java @@ -26,8 +26,9 @@ import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.SCBStatus; import org.apache.servicecomb.core.definition.SchemaMeta; -import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils; import org.apache.servicecomb.core.unittest.UnitTestMeta; import org.apache.servicecomb.serviceregistry.RegistryUtils; import org.apache.servicecomb.serviceregistry.ServiceRegistry; @@ -45,12 +46,12 @@ public class TestCseClientHttpRequest { @Before public void setup() { - ReferenceConfigUtils.setReady(true); + SCBEngine.getInstance().setStatus(SCBStatus.UP); } @After public void teardown() { - ReferenceConfigUtils.setReady(false); + SCBEngine.getInstance().setStatus(SCBStatus.DOWN); } @RequestMapping(path = "SpringmvcImpl") @@ -63,12 +64,13 @@ public byte[] bytes(@RequestBody byte[] input) { } @Test - public void testNotReady() throws IOException { + public void testNotReady() { String exceptionMessage = "System is not ready for remote calls. " + "When beans are making remote calls in initialization, it's better to " + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."; - ReferenceConfigUtils.setReady(false); + SCBEngine.getInstance().setStatus(SCBStatus.DOWN); + CseClientHttpRequest client = new CseClientHttpRequest(URI.create("cse://app:test/"), HttpMethod.POST); @@ -81,7 +83,7 @@ public void testNotReady() throws IOException { } @Test - public void testNormal() throws IOException { + public void testNormal() { ServiceRegistry serviceRegistry = ServiceRegistryFactory.createLocal(); serviceRegistry.init(); RegistryUtils.setServiceRegistry(serviceRegistry); diff --git a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java index 35388cc7a85..d24a5eadfd6 100644 --- a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java +++ b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java @@ -27,8 +27,9 @@ import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.SCBStatus; import org.apache.servicecomb.core.definition.SchemaMeta; -import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils; import org.apache.servicecomb.core.unittest.UnitTestMeta; import org.apache.servicecomb.provider.springmvc.reference.CseClientHttpResponse; import org.apache.servicecomb.serviceregistry.RegistryUtils; @@ -51,12 +52,12 @@ public class CseAsyncClientHttpRequestTest { @Before public void setup() { - ReferenceConfigUtils.setReady(true); + SCBEngine.getInstance().setStatus(SCBStatus.UP); } @After public void teardown() { - ReferenceConfigUtils.setReady(false); + SCBEngine.getInstance().setStatus(SCBStatus.DOWN); } @RequestMapping(path = "CseAsyncClientHttpRequestTestSchema") @@ -73,7 +74,7 @@ public void testNotReady() { String exceptionMessage = "System is not ready for remote calls. " + "When beans are making remote calls in initialization, it's better to " + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."; - ReferenceConfigUtils.setReady(false); + SCBEngine.getInstance().setStatus(SCBStatus.DOWN); CseAsyncClientHttpRequest clientHttpRequest = new CseAsyncClientHttpRequest(URI.create("cse://app:test/"), HttpMethod.POST); try { @@ -94,13 +95,15 @@ public void testNormal() { .getSchemaListenerManager() .setSchemaListenerList(Arrays.asList(new RestEngineSchemaListener())); - SchemaMeta schemaMeta = meta.getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class); + SchemaMeta schemaMeta = meta + .getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class); CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(schemaMeta); Holder holder = new Holder<>(); CseAsyncClientHttpRequest client = new CseAsyncClientHttpRequest(URI.create( - "cse://app:test/" + CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class.getSimpleName() + "/testbytes"), + "cse://app:test/" + CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class.getSimpleName() + + "/testbytes"), HttpMethod.POST) { @Override protected CompletableFuture doAsyncInvoke(Invocation invocation) { @@ -125,7 +128,8 @@ public void testFail() { CseContext.getInstance() .getSchemaListenerManager() .setSchemaListenerList(Arrays.asList(new RestEngineSchemaListener())); - SchemaMeta schemaMeta = meta.getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class); + SchemaMeta schemaMeta = meta + .getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class); CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(schemaMeta); Throwable error = new Error("failed"); @@ -133,7 +137,8 @@ public void testFail() { CseAsyncClientHttpRequest client = new CseAsyncClientHttpRequest(URI.create( - "cse://app:test/" + CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class.getSimpleName() + "/testbytes"), + "cse://app:test/" + CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class.getSimpleName() + + "/testbytes"), HttpMethod.POST) { @Override protected CompletableFuture doAsyncInvoke(Invocation invocation) { diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/WebsocketUtils.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/WebsocketUtils.java index e262d8cc457..70625dad263 100644 --- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/WebsocketUtils.java +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/client/http/WebsocketUtils.java @@ -59,11 +59,6 @@ public static void open(IpPort ipPort, String url, Handler onOpen, Handler }); ws.closeHandler(v -> { onClose.handle(v); - try { - ws.close(); - } catch (Exception err) { - LOGGER.error("ws close error.", err); - } }); ws.handler(onMessage); }, From 7c464f4b859cdf9a39954cb6356ff1c93823df53 Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Wed, 16 May 2018 17:17:32 +0800 Subject: [PATCH 09/13] SCB-548 refactor and fix pr comment Signed-off-by: zhengyangyong --- .../apache/servicecomb/core/SCBEngine.java | 61 ++++------------- .../core/provider/consumer/InvokerUtils.java | 39 ++++++++--- .../consumer/ReferenceConfigUtils.java | 34 ---------- .../provider/consumer/TestInvokerUtils.java | 66 +++++++++++++++---- .../consumer/TestReferenceConfigUtils.java | 62 ----------------- .../servicecomb/provider/pojo/Invoker.java | 11 +--- .../provider/pojo/TestInvoker.java | 19 ------ .../reference/CseClientHttpRequest.java | 12 ++-- .../reference/TestCseClientHttpRequest.java | 25 +------ .../async/CseAsyncClientHttpRequestTest.java | 22 +------ 10 files changed, 108 insertions(+), 243 deletions(-) delete mode 100644 core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigUtils.java delete mode 100644 core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfigUtils.java diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java index f1411e1ab8d..772070c888b 100644 --- a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java +++ b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.core; import java.util.Collection; -import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import org.apache.servicecomb.core.BootListener.BootEvent; @@ -60,14 +60,16 @@ public class SCBEngine { private final AtomicLong invocationFinishedCounter = new AtomicLong(); - private final Semaphore allInvocationFinished = new Semaphore(1); - private volatile SCBStatus status = SCBStatus.DOWN; public void setStatus(SCBStatus status) { this.status = status; } + public SCBStatus getStatus() { + return status; + } + private EventBus eventBus = EventManager.getEventBus(); private static final SCBEngine INSTANCE = new SCBEngine(); @@ -123,7 +125,7 @@ protected void safeTriggerEvent(EventType eventType) { for (BootListener listener : bootListenerList) { try { listener.onBootEvent(event); - LOGGER.error("BootListener {} succeed to process {}.", listener.getClass().getName(), eventType); + LOGGER.info("BootListener {} succeed to process {}.", listener.getClass().getName(), eventType); } catch (Throwable e) { LOGGER.error("BootListener {} failed to process {}.", listener.getClass().getName(), eventType, e); } @@ -166,13 +168,10 @@ public void onInvocationStart(InvocationStartEvent event) { @Subscribe public void onInvocationFinish(InvocationFinishEvent event) { invocationFinishedCounter.incrementAndGet(); - if (validIsStopping()) { - validAllInvocationFinished(); - } } public synchronized void init() { - if (validIsDown()) { + if (SCBStatus.DOWN.equals(status)) { try { doInit(); status = SCBStatus.UP; @@ -190,8 +189,6 @@ private void doInit() throws Exception { eventBus.register(this); - allInvocationFinished.acquire(); - AbstractEndpointsCache.init(RegistryUtils.getInstanceCacheManager(), transportManager); triggerEvent(EventType.BEFORE_HANDLER); @@ -226,7 +223,7 @@ private void doInit() throws Exception { * even some step throw exception, must catch it and go on, otherwise shutdown process will be broken. */ public synchronized void uninit() { - if (validIsUp()) { + if (SCBStatus.UP.equals(status)) { LOGGER.info("ServiceComb is closing now..."); try { doUninit(); @@ -252,7 +249,6 @@ private void doUninit() throws Exception { //Step 3: wait all invocation finished // forbit create new consumer invocation validAllInvocationFinished(); - allInvocationFinished.acquire(); //Step 4: Stop vertx to prevent blocking exit VertxUtils.blockCloseVertxByName("config-center"); @@ -263,43 +259,14 @@ private void doUninit() throws Exception { //Step 6: Clean flags for re-init eventBus.unregister(this); - allInvocationFinished.release(); - } - - private void validAllInvocationFinished() { - LOGGER.info("valid for all invocation finished, request count: {}, response count: {}.", - invocationStartedCounter.get(), - invocationFinishedCounter.get()); - if (invocationFinishedCounter.get() == invocationStartedCounter.get()) { - allInvocationFinished.release(); - } - } - - public void assertIsStopping() { - if (validIsStopping()) { - throw new IllegalStateException( - "shutting down in progress, it's better to implement " + BootListener.class.getName() - + " and stop ... in EventType.BEFORE_CLOSE."); - } } - private boolean validIsStopping() { - return SCBStatus.STOPPING.equals(status); - } - - public void assertIsUp() { - if (!SCBStatus.UP.equals(status)) { - throw new IllegalStateException("System is not ready for remote calls. " - + "When beans are making remote calls in initialization, it's better to " - + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."); + private void validAllInvocationFinished() throws InterruptedException { + while (true) { + if (invocationFinishedCounter.get() == invocationStartedCounter.get()) { + return; + } + TimeUnit.SECONDS.sleep(1); } } - - private boolean validIsUp() { - return SCBStatus.UP.equals(status); - } - - private boolean validIsDown() { - return SCBStatus.DOWN.equals(status); - } } diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java index 7dc01f3a128..78a44309bd0 100644 --- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java +++ b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java @@ -17,7 +17,10 @@ package org.apache.servicecomb.core.provider.consumer; +import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.SCBStatus; import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.core.invocation.InvocationFactory; import org.apache.servicecomb.swagger.invocation.AsyncResponse; @@ -32,31 +35,31 @@ public final class InvokerUtils { private static final Logger LOGGER = LoggerFactory.getLogger(InvokerUtils.class); public static Object syncInvoke(String microserviceName, String schemaId, String operationName, Object[] args) { - ReferenceConfig referenceConfig = ReferenceConfigUtils.getForInvoke(microserviceName); - SchemaMeta schemaMeta = referenceConfig.getMicroserviceMeta().ensureFindSchemaMeta(schemaId); - Invocation invocation = InvocationFactory.forConsumer(referenceConfig, schemaMeta, operationName, args); - return syncInvoke(invocation); + validCanInvoke(); + ReferenceConfig referenceConfig = CseContext.getInstance().getConsumerProviderManager() + .getReferenceConfig(microserviceName); + return syncInvoke(generateInvocation(schemaId, operationName, args, referenceConfig)); } public static Object syncInvoke(String microserviceName, String microserviceVersion, String transport, String schemaId, String operationName, Object[] args) { - ReferenceConfig referenceConfig = - ReferenceConfigUtils.getForInvoke(microserviceName, microserviceVersion, transport); - SchemaMeta schemaMeta = referenceConfig.getMicroserviceMeta().ensureFindSchemaMeta(schemaId); - Invocation invocation = InvocationFactory.forConsumer(referenceConfig, schemaMeta, operationName, args); - return syncInvoke(invocation); + validCanInvoke(); + ReferenceConfig referenceConfig = CseContext.getInstance().getConsumerProviderManager() + .createReferenceConfig(microserviceName, microserviceVersion, transport); + return syncInvoke(generateInvocation(schemaId, operationName, args, referenceConfig)); } public static Object syncInvoke(Invocation invocation) throws InvocationException { + validCanInvoke(); Response response = innerSyncInvoke(invocation); if (response.isSuccessed()) { return response.getResult(); } - throw ExceptionFactory.convertConsumerException(response.getResult()); } public static Response innerSyncInvoke(Invocation invocation) { + validCanInvoke(); try { invocation.onStart(); SyncResponseExecutor respExecutor = new SyncResponseExecutor(); @@ -79,6 +82,7 @@ public static Response innerSyncInvoke(Invocation invocation) { } public static void reactiveInvoke(Invocation invocation, AsyncResponse asyncResp) { + validCanInvoke(); try { invocation.onStart(); invocation.setSync(false); @@ -104,8 +108,23 @@ public static void reactiveInvoke(Invocation invocation, AsyncResponse asyncResp } } + private static Invocation generateInvocation(String schemaId, String operationName, Object[] args, + ReferenceConfig referenceConfig) { + SchemaMeta schemaMeta = referenceConfig.getMicroserviceMeta().ensureFindSchemaMeta(schemaId); + return InvocationFactory.forConsumer(referenceConfig, schemaMeta, operationName, args); + } + + private static void validCanInvoke() { + if (!SCBStatus.UP.equals(SCBEngine.getInstance().getStatus())) { + throw new IllegalStateException( + "System is starting and not ready for remote calls or shutting down in progress, STATUS = " + String + .valueOf(SCBEngine.getInstance().getStatus())); + } + } + @Deprecated public static Object invoke(Invocation invocation) { + validCanInvoke(); return syncInvoke(invocation); } } diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigUtils.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigUtils.java deleted file mode 100644 index b0bf2d299e4..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigUtils.java +++ /dev/null @@ -1,34 +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.core.provider.consumer; - -import org.apache.servicecomb.core.CseContext; -import org.apache.servicecomb.core.SCBEngine; - -public class ReferenceConfigUtils { - public static ReferenceConfig getForInvoke(String microserviceName) { - SCBEngine.getInstance().assertIsUp(); - return CseContext.getInstance().getConsumerProviderManager().getReferenceConfig(microserviceName); - } - - public static ReferenceConfig getForInvoke(String microserviceName, String microserviceVersion, String transport) { - SCBEngine.getInstance().assertIsUp(); - return CseContext.getInstance().getConsumerProviderManager().createReferenceConfig(microserviceName, - microserviceVersion, transport); - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java index 16adde75002..8bf6cae778a 100644 --- a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java +++ b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java @@ -19,7 +19,6 @@ import javax.xml.ws.Holder; -import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; @@ -70,6 +69,9 @@ public Response waitResponse() { @Test public void testReactiveInvoke(@Mocked Invocation invocation, @Mocked InvocationContext parentContext, @Mocked Response response) { + + SCBEngine.getInstance().setStatus(SCBStatus.UP); + new MockUp(invocation) { @Mock InvocationContext getParentContext() { @@ -83,9 +85,7 @@ void next(AsyncResponse asyncResp) { }; Holder holder = new Holder<>(); - InvokerUtils.reactiveInvoke(invocation, ar -> { - holder.value = ContextUtils.getInvocationContext(); - }); + InvokerUtils.reactiveInvoke(invocation, ar -> holder.value = ContextUtils.getInvocationContext()); Assert.assertNull(ContextUtils.getInvocationContext()); Assert.assertSame(parentContext, holder.value); @@ -94,6 +94,9 @@ void next(AsyncResponse asyncResp) { @SuppressWarnings("deprecation") @Test public void invoke() { + + SCBEngine.getInstance().setStatus(SCBStatus.UP); + new MockUp() { @Mock Object syncInvoke(Invocation invocation) { @@ -105,33 +108,68 @@ Object syncInvoke(Invocation invocation) { } @Test - public void tetSyncInvokeNotReady() { + public void testSyncInvokeNotReady(@Mocked Invocation invocation) { SCBEngine.getInstance().setStatus(SCBStatus.DOWN); + try { + InvokerUtils.syncInvoke(invocation); + Assert.fail("must throw exception"); + } catch (IllegalStateException e) { + Assert + .assertEquals("System is starting and not ready for remote calls or shutting down in progress, STATUS = DOWN", + e.getMessage()); + } + try { InvokerUtils.syncInvoke("ms", "schemaId", "opName", null); Assert.fail("must throw exception"); } catch (IllegalStateException e) { - Assert.assertEquals("System is not ready for remote calls. " - + "When beans are making remote calls in initialization, it's better to " - + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY.", - e.getMessage()); + Assert + .assertEquals("System is starting and not ready for remote calls or shutting down in progress, STATUS = DOWN", + e.getMessage()); } try { InvokerUtils.syncInvoke("ms", "latest", "rest", "schemaId", "opName", null); Assert.fail("must throw exception"); } catch (IllegalStateException e) { - Assert.assertEquals("System is not ready for remote calls. " - + "When beans are making remote calls in initialization, it's better to " - + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY.", - e.getMessage()); + Assert + .assertEquals("System is starting and not ready for remote calls or shutting down in progress, STATUS = DOWN", + e.getMessage()); + } + } + + @Test + public void testReactiveInvokeNotReady(@Mocked Invocation invocation, @Mocked InvocationContext parentContext, + @Mocked Response response) { + + SCBEngine.getInstance().setStatus(SCBStatus.DOWN); + + new MockUp(invocation) { + @Mock + InvocationContext getParentContext() { + return parentContext; + } + + @Mock + void next(AsyncResponse asyncResp) { + asyncResp.handle(response); + } + }; + + Holder holder = new Holder<>(); + try { + InvokerUtils.reactiveInvoke(invocation, ar -> holder.value = ContextUtils.getInvocationContext()); + } catch (IllegalStateException e) { + Assert + .assertEquals("System is starting and not ready for remote calls or shutting down in progress, STATUS = DOWN", + e.getMessage()); } } @Test - public void tetSyncInvokeReady(@Injectable ConsumerProviderManager consumerProviderManager, + public void testSyncInvokeReady(@Injectable ConsumerProviderManager consumerProviderManager, @Injectable Invocation invocation) { SCBEngine.getInstance().setStatus(SCBStatus.UP); diff --git a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfigUtils.java b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfigUtils.java deleted file mode 100644 index b31ee58cbea..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfigUtils.java +++ /dev/null @@ -1,62 +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.core.provider.consumer; - -import org.apache.servicecomb.core.BootListener; -import org.apache.servicecomb.core.CseContext; -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.SCBStatus; -import org.junit.Assert; -import org.junit.Test; - -import mockit.Injectable; - -public class TestReferenceConfigUtils { - @Test - public void testNotReady() { - String exceptionMessage = "System is not ready for remote calls. " - + "When beans are making remote calls in initialization, it's better to " - + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."; - - SCBEngine.getInstance().setStatus(SCBStatus.DOWN); - - try { - ReferenceConfigUtils.getForInvoke("abc"); - Assert.fail("must throw exception"); - } catch (IllegalStateException e) { - Assert.assertEquals(exceptionMessage, e.getMessage()); - } - - try { - ReferenceConfigUtils.getForInvoke("abc", "v1", ""); - Assert.fail("must throw exception"); - } catch (IllegalStateException e) { - Assert.assertEquals(exceptionMessage, e.getMessage()); - } - } - - @Test - public void testReady(@Injectable ConsumerProviderManager consumerProviderManager) { - - SCBEngine.getInstance().setStatus(SCBStatus.UP); - - CseContext.getInstance().setConsumerProviderManager(consumerProviderManager); - - Assert.assertNotNull(ReferenceConfigUtils.getForInvoke("abc")); - Assert.assertNotNull(ReferenceConfigUtils.getForInvoke("abc", "v1", "")); - } -} diff --git a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java index 1dd25e2d9de..18fd64aec02 100644 --- a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java +++ b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java @@ -24,13 +24,11 @@ import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.core.invocation.InvocationFactory; import org.apache.servicecomb.core.provider.consumer.InvokerUtils; import org.apache.servicecomb.core.provider.consumer.ReferenceConfig; -import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils; import org.apache.servicecomb.swagger.engine.SwaggerConsumer; import org.apache.servicecomb.swagger.engine.SwaggerConsumerOperation; import org.apache.servicecomb.swagger.invocation.Response; @@ -65,7 +63,7 @@ public Invoker(String microserviceName, String schemaId, Class consumerIntf) } protected void prepare() { - referenceConfig = ReferenceConfigUtils.getForInvoke(microserviceName); + referenceConfig = CseContext.getInstance().getConsumerProviderManager().getReferenceConfig(microserviceName); MicroserviceMeta microserviceMeta = referenceConfig.getMicroserviceMeta(); if (StringUtils.isEmpty(schemaId)) { @@ -94,12 +92,9 @@ public Object invoke(Object proxy, Method method, Object[] args) { } } - SCBEngine.getInstance().assertIsStopping(); - SwaggerConsumerOperation consumerOperation = swaggerConsumer.findOperation(method.getName()); - Invocation invocation = - InvocationFactory - .forConsumer(referenceConfig, schemaMeta, consumerOperation.getSwaggerMethod().getName(), null); + Invocation invocation = InvocationFactory + .forConsumer(referenceConfig, schemaMeta, consumerOperation.getSwaggerMethod().getName(), null); consumerOperation.getArgumentsMapper().toInvocation(args, invocation); diff --git a/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java b/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java index 715edccc440..c0682f9b676 100644 --- a/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java +++ b/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java @@ -19,7 +19,6 @@ import java.util.concurrent.CompletableFuture; -import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; @@ -65,24 +64,6 @@ public void teardown() { SCBEngine.getInstance().setStatus(SCBStatus.DOWN); } - @Test - public void testNotReady() throws Throwable { - String exceptionMessage = "System is not ready for remote calls. " - + "When beans are making remote calls in initialization, it's better to " - + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."; - - SCBEngine.getInstance().setStatus(SCBStatus.DOWN); - - Invoker invoker = new Invoker("test", "schemaId", IPerson.class); - - try { - invoker.invoke(null, null, null); - Assert.fail("must throw exception"); - } catch (IllegalStateException e) { - Assert.assertEquals(exceptionMessage, e.getMessage()); - } - } - @Test public void testNormalSchemaId(@Injectable ConsumerProviderManager manager, @Injectable ReferenceConfig config, diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java index a64d794705a..1e85f5a391e 100644 --- a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java @@ -29,13 +29,12 @@ import org.apache.servicecomb.common.rest.definition.RestOperationMeta; import org.apache.servicecomb.common.rest.locator.OperationLocator; import org.apache.servicecomb.common.rest.locator.ServicePathManager; +import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.invocation.InvocationFactory; import org.apache.servicecomb.core.provider.consumer.InvokerUtils; import org.apache.servicecomb.core.provider.consumer.ReferenceConfig; -import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.context.InvocationContext; import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; @@ -147,12 +146,11 @@ public ClientHttpResponse execute() { return this.invoke(args); } - protected RequestMeta createRequestMeta(String httpMetod, URI uri) { + protected RequestMeta createRequestMeta(String httpMethod, URI uri) { String microserviceName = uri.getAuthority(); - SCBEngine.getInstance().assertIsStopping(); - - ReferenceConfig referenceConfig = ReferenceConfigUtils.getForInvoke(microserviceName); + ReferenceConfig referenceConfig = CseContext.getInstance().getConsumerProviderManager() + .getReferenceConfig(microserviceName); MicroserviceMeta microserviceMeta = referenceConfig.getMicroserviceMeta(); ServicePathManager servicePathManager = ServicePathManager.getServicePathManager(microserviceMeta); @@ -162,7 +160,7 @@ protected RequestMeta createRequestMeta(String httpMetod, URI uri) { microserviceMeta.getName())); } - OperationLocator locator = servicePathManager.consumerLocateOperation(path, httpMetod); + OperationLocator locator = servicePathManager.consumerLocateOperation(path, httpMethod); RestOperationMeta swaggerRestOperation = locator.getOperation(); Map pathParams = locator.getPathVarMap(); diff --git a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java index fe32d992bc8..7de386016c7 100644 --- a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java +++ b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCseClientHttpRequest.java @@ -16,14 +16,12 @@ */ package org.apache.servicecomb.provider.springmvc.reference; -import java.io.IOException; import java.net.URI; -import java.util.Arrays; +import java.util.Collections; import javax.xml.ws.Holder; import org.apache.servicecomb.common.rest.RestEngineSchemaListener; -import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; @@ -63,25 +61,6 @@ public byte[] bytes(@RequestBody byte[] input) { } } - @Test - public void testNotReady() { - String exceptionMessage = "System is not ready for remote calls. " - + "When beans are making remote calls in initialization, it's better to " - + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."; - - SCBEngine.getInstance().setStatus(SCBStatus.DOWN); - - CseClientHttpRequest client = - new CseClientHttpRequest(URI.create("cse://app:test/"), HttpMethod.POST); - - try { - client.execute(); - Assert.fail("must throw exception"); - } catch (IllegalStateException e) { - Assert.assertEquals(exceptionMessage, e.getMessage()); - } - } - @Test public void testNormal() { ServiceRegistry serviceRegistry = ServiceRegistryFactory.createLocal(); @@ -92,7 +71,7 @@ public void testNormal() { CseContext.getInstance() .getSchemaListenerManager() - .setSchemaListenerList(Arrays.asList(new RestEngineSchemaListener())); + .setSchemaListenerList(Collections.singletonList(new RestEngineSchemaListener())); SchemaMeta schemaMeta = meta.getOrCreateSchemaMeta(SpringmvcImpl.class); CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(schemaMeta); diff --git a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java index d24a5eadfd6..fcab92086b8 100644 --- a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java +++ b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java @@ -18,13 +18,12 @@ package org.apache.servicecomb.provider.springmvc.reference.async; import java.net.URI; -import java.util.Arrays; +import java.util.Collections; import java.util.concurrent.CompletableFuture; import javax.xml.ws.Holder; import org.apache.servicecomb.common.rest.RestEngineSchemaListener; -import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; @@ -69,21 +68,6 @@ public byte[] testbytes(@RequestBody byte[] input) { } } - @Test - public void testNotReady() { - String exceptionMessage = "System is not ready for remote calls. " - + "When beans are making remote calls in initialization, it's better to " - + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."; - SCBEngine.getInstance().setStatus(SCBStatus.DOWN); - CseAsyncClientHttpRequest clientHttpRequest = new CseAsyncClientHttpRequest(URI.create("cse://app:test/"), - HttpMethod.POST); - try { - clientHttpRequest.executeAsync(); - } catch (IllegalStateException e) { - Assert.assertEquals(exceptionMessage, e.getMessage()); - } - } - @Test public void testNormal() { ServiceRegistry serviceRegistry = ServiceRegistryFactory.createLocal(); @@ -93,7 +77,7 @@ public void testNormal() { CseContext.getInstance() .getSchemaListenerManager() - .setSchemaListenerList(Arrays.asList(new RestEngineSchemaListener())); + .setSchemaListenerList(Collections.singletonList(new RestEngineSchemaListener())); SchemaMeta schemaMeta = meta .getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class); @@ -127,7 +111,7 @@ public void testFail() { UnitTestMeta meta = new UnitTestMeta(); CseContext.getInstance() .getSchemaListenerManager() - .setSchemaListenerList(Arrays.asList(new RestEngineSchemaListener())); + .setSchemaListenerList(Collections.singletonList(new RestEngineSchemaListener())); SchemaMeta schemaMeta = meta .getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.CseAsyncClientHttpRequestTestSchema.class); CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(schemaMeta); From 7e2cbd6a0f10d921f509f994e75f637285ee6f79 Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Thu, 17 May 2018 10:10:48 +0800 Subject: [PATCH 10/13] SCB-548 add SCBEngine UT Signed-off-by: zhengyangyong --- .../servicecomb/core/TestSCBEngine.java | 68 +++++++++++++++++++ .../foundation/vertx/VertxUtils.java | 37 +--------- 2 files changed, 70 insertions(+), 35 deletions(-) create mode 100644 core/src/test/java/org/apache/servicecomb/core/TestSCBEngine.java diff --git a/core/src/test/java/org/apache/servicecomb/core/TestSCBEngine.java b/core/src/test/java/org/apache/servicecomb/core/TestSCBEngine.java new file mode 100644 index 00000000000..da0a9dbf446 --- /dev/null +++ b/core/src/test/java/org/apache/servicecomb/core/TestSCBEngine.java @@ -0,0 +1,68 @@ +/* + * 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.core; + +import java.util.ArrayList; + +import org.apache.servicecomb.core.definition.loader.SchemaListenerManager; +import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager; +import org.apache.servicecomb.core.provider.producer.ProducerProviderManager; +import org.apache.servicecomb.core.transport.TransportManager; +import org.apache.servicecomb.foundation.vertx.VertxUtils; +import org.apache.servicecomb.serviceregistry.RegistryUtils; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import mockit.Expectations; +import mockit.Injectable; + +public class TestSCBEngine { + @Test + public void test(@Injectable ProducerProviderManager producerProviderManager, + @Injectable ConsumerProviderManager consumerProviderManager, + @Injectable TransportManager transportManager) { + + new Expectations(RegistryUtils.class) { + { + RegistryUtils.getInstanceCacheManager(); + RegistryUtils.run(); + RegistryUtils.destroy(); + } + }; + + SchemaListenerManager schemaListenerManager = Mockito.mock(SchemaListenerManager.class); + + VertxUtils.getOrCreateVertxByName("transport", null); + + SCBEngine engine = new SCBEngine(); + engine.setBootListenerList(new ArrayList<>()); + engine.setConsumerProviderManager(consumerProviderManager); + engine.setProducerProviderManager(producerProviderManager); + engine.setTransportManager(transportManager); + engine.setSchemaListenerManager(schemaListenerManager); + + engine.init(); + + Assert.assertEquals(SCBStatus.UP, engine.getStatus()); + + engine.uninit(); + + Assert.assertEquals(SCBStatus.DOWN, engine.getStatus()); + } +} diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java index 5d4709fe2a1..a3aabd69452 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java @@ -36,7 +36,6 @@ import io.netty.buffer.ByteBuf; import io.vertx.core.AbstractVerticle; -import io.vertx.core.Context; import io.vertx.core.DeploymentOptions; import io.vertx.core.Verticle; import io.vertx.core.Vertx; @@ -112,9 +111,7 @@ public static boolean blockDeploy(Vertx vertx, } public static Vertx getOrCreateVertxByName(String name, VertxOptions vertxOptions) { - return vertxMap.computeIfAbsent(name, vertxName -> { - return (VertxImplEx) init(vertxName, vertxOptions); - }); + return vertxMap.computeIfAbsent(name, vertxName -> (VertxImplEx) init(vertxName, vertxOptions)); } public static Vertx init(VertxOptions vertxOptions) { @@ -126,7 +123,7 @@ public static Vertx init(String name, VertxOptions vertxOptions) { vertxOptions = new VertxOptions(); } - boolean isDebug = ManagementFactory.getRuntimeMXBean().getInputArguments().toString().indexOf("jdwp") >= 0; + boolean isDebug = ManagementFactory.getRuntimeMXBean().getInputArguments().toString().contains("jdwp"); if (isDebug) { vertxOptions.setBlockedThreadCheckInterval(BLOCKED_THREAD_CHECK_INTERVAL); LOGGER.info("in debug mode, disable blocked thread check."); @@ -145,36 +142,6 @@ protected static void configureVertxFileCaching() { } } - public static Vertx currentVertx() { - Context context = Vertx.currentContext(); - if (context == null) { - throw new RuntimeException("get currentVertx error, currentContext is null."); - } - - return context.owner(); - } - - public static Vertx getVertxByName(String name) { - return vertxMap.get(name); - } - - public static void runInContext(Context context, AsyncResultCallback callback, T result, Throwable e) { - if (context == Vertx.currentContext()) { - complete(callback, result, e); - } else { - context.runOnContext(v -> complete(callback, result, e)); - } - } - - private static void complete(AsyncResultCallback callback, T result, Throwable e) { - if (e != null) { - callback.fail(e.getCause()); - return; - } - - callback.success(result); - } - // try to reference byte[] // otherwise copy byte[] public static byte[] getBytesFast(InputStream inputStream) throws IOException { From 344fe80816e68dc0ff643e5f994afc313556957e Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Thu, 17 May 2018 14:21:21 +0800 Subject: [PATCH 11/13] SCB-548 fix pr comment and update coverage pom Signed-off-by: zhengyangyong --- .../apache/servicecomb/core/SCBEngine.java | 21 ++++++------ coverage-reports/pom.xml | 32 +++++++++++++++++++ 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java index 772070c888b..17a4fceeb8f 100644 --- a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java +++ b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java @@ -225,17 +225,13 @@ private void doInit() throws Exception { public synchronized void uninit() { if (SCBStatus.UP.equals(status)) { LOGGER.info("ServiceComb is closing now..."); - try { - doUninit(); - status = SCBStatus.DOWN; - } catch (Exception e) { - status = SCBStatus.FAILED; - LOGGER.info("ServiceComb failed shutdown", e); - } + doUninit(); + status = SCBStatus.DOWN; + LOGGER.info("ServiceComb had closed"); } } - private void doUninit() throws Exception { + private void doUninit() { //Step 1: notify all component stop invoke via BEFORE_CLOSE Event safeTriggerEvent(EventType.BEFORE_CLOSE); @@ -248,7 +244,11 @@ private void doUninit() throws Exception { //Step 3: wait all invocation finished // forbit create new consumer invocation - validAllInvocationFinished(); + try { + validAllInvocationFinished(); + } catch (InterruptedException e) { + LOGGER.error("wait all invocation finished interrupted", e); + } //Step 4: Stop vertx to prevent blocking exit VertxUtils.blockCloseVertxByName("config-center"); @@ -256,9 +256,6 @@ private void doUninit() throws Exception { //Step 5: notify all component do clean works via AFTER_CLOSE Event safeTriggerEvent(EventType.AFTER_CLOSE); - - //Step 6: Clean flags for re-init - eventBus.unregister(this); } private void validAllInvocationFinished() throws InterruptedException { diff --git a/coverage-reports/pom.xml b/coverage-reports/pom.xml index 337ae2699bb..fcdb3e0ac97 100644 --- a/coverage-reports/pom.xml +++ b/coverage-reports/pom.xml @@ -50,6 +50,10 @@ org.apache.servicecomb foundation-metrics + + org.apache.servicecomb + metrics-core + org.apache.servicecomb java-chassis-core @@ -174,6 +178,14 @@ org.apache.servicecomb config-apollo + + org.apache.servicecomb + config-cc + + + org.apache.servicecomb + edge-core + org.apache.servicecomb.demo pojo-client @@ -259,6 +271,26 @@ springmvc-tests 1.0.0-m2-SNAPSHOT + + org.apache.servicecomb.tests + springmvc-tests-general + 1.0.0-m2-SNAPSHOT + + + org.apache.servicecomb.tests + springmvc-tests-general-with-springboot + 1.0.0-m2-SNAPSHOT + + + org.apache.servicecomb.tests + springmvc-tests-simplified-mapping + 1.0.0-m2-SNAPSHOT + + + org.apache.servicecomb.tests + springmvc-tests-simplified-mapping-with-springboot + 1.0.0-m2-SNAPSHOT + org.apache.servicecomb.tests tracing-tests From 8f1bc8ffc574f947c5e26ad639466f7fa60bbcb5 Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Fri, 18 May 2018 09:25:38 +0800 Subject: [PATCH 12/13] SCB-548 fix pr comment Signed-off-by: zhengyangyong --- .../java/org/apache/servicecomb/core/SCBEngine.java | 10 +++++----- integration-tests/spring-zuul-tracing-tests/pom.xml | 13 ------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java index 17a4fceeb8f..e0a17b8b8c3 100644 --- a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java +++ b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java @@ -235,26 +235,26 @@ private void doUninit() { //Step 1: notify all component stop invoke via BEFORE_CLOSE Event safeTriggerEvent(EventType.BEFORE_CLOSE); + //Step 2: forbid create new consumer invocation status = SCBStatus.STOPPING; - //Step 2: Unregister microservice instance from Service Center and close vertx + //Step 3: Unregister microservice instance from Service Center and close vertx // Forbidden other consumers find me RegistryUtils.destroy(); VertxUtils.blockCloseVertxByName("registry"); - //Step 3: wait all invocation finished - // forbit create new consumer invocation + //Step 4: wait all invocation finished try { validAllInvocationFinished(); } catch (InterruptedException e) { LOGGER.error("wait all invocation finished interrupted", e); } - //Step 4: Stop vertx to prevent blocking exit + //Step 5: Stop vertx to prevent blocking exit VertxUtils.blockCloseVertxByName("config-center"); VertxUtils.blockCloseVertxByName("transport"); - //Step 5: notify all component do clean works via AFTER_CLOSE Event + //Step 6: notify all component do clean works via AFTER_CLOSE Event safeTriggerEvent(EventType.AFTER_CLOSE); } diff --git a/integration-tests/spring-zuul-tracing-tests/pom.xml b/integration-tests/spring-zuul-tracing-tests/pom.xml index f414368e4b7..27b27aac33b 100644 --- a/integration-tests/spring-zuul-tracing-tests/pom.xml +++ b/integration-tests/spring-zuul-tracing-tests/pom.xml @@ -93,17 +93,4 @@ test - - - - - org.apache.maven.plugins - maven-surefire-plugin - - 1 - false - - - - From 4b5722cfafb0acf0de7863c1d8ab5d58a289ded3 Mon Sep 17 00:00:00 2001 From: zhengyangyong Date: Fri, 18 May 2018 12:51:23 +0800 Subject: [PATCH 13/13] SCB-548 fix pr comment Signed-off-by: zhengyangyong --- .../core/provider/consumer/InvokerUtils.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java index 78a44309bd0..d617bd8c0bf 100644 --- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java +++ b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java @@ -35,7 +35,7 @@ public final class InvokerUtils { private static final Logger LOGGER = LoggerFactory.getLogger(InvokerUtils.class); public static Object syncInvoke(String microserviceName, String schemaId, String operationName, Object[] args) { - validCanInvoke(); + checkEngineStatus(); ReferenceConfig referenceConfig = CseContext.getInstance().getConsumerProviderManager() .getReferenceConfig(microserviceName); return syncInvoke(generateInvocation(schemaId, operationName, args, referenceConfig)); @@ -43,14 +43,14 @@ public static Object syncInvoke(String microserviceName, String schemaId, String public static Object syncInvoke(String microserviceName, String microserviceVersion, String transport, String schemaId, String operationName, Object[] args) { - validCanInvoke(); + checkEngineStatus(); ReferenceConfig referenceConfig = CseContext.getInstance().getConsumerProviderManager() .createReferenceConfig(microserviceName, microserviceVersion, transport); return syncInvoke(generateInvocation(schemaId, operationName, args, referenceConfig)); } public static Object syncInvoke(Invocation invocation) throws InvocationException { - validCanInvoke(); + checkEngineStatus(); Response response = innerSyncInvoke(invocation); if (response.isSuccessed()) { return response.getResult(); @@ -59,7 +59,7 @@ public static Object syncInvoke(Invocation invocation) throws InvocationExceptio } public static Response innerSyncInvoke(Invocation invocation) { - validCanInvoke(); + checkEngineStatus(); try { invocation.onStart(); SyncResponseExecutor respExecutor = new SyncResponseExecutor(); @@ -82,7 +82,7 @@ public static Response innerSyncInvoke(Invocation invocation) { } public static void reactiveInvoke(Invocation invocation, AsyncResponse asyncResp) { - validCanInvoke(); + checkEngineStatus(); try { invocation.onStart(); invocation.setSync(false); @@ -114,7 +114,7 @@ private static Invocation generateInvocation(String schemaId, String operationNa return InvocationFactory.forConsumer(referenceConfig, schemaMeta, operationName, args); } - private static void validCanInvoke() { + private static void checkEngineStatus() { if (!SCBStatus.UP.equals(SCBEngine.getInstance().getStatus())) { throw new IllegalStateException( "System is starting and not ready for remote calls or shutting down in progress, STATUS = " + String @@ -124,7 +124,7 @@ private static void validCanInvoke() { @Deprecated public static Object invoke(Invocation invocation) { - validCanInvoke(); + checkEngineStatus(); return syncInvoke(invocation); } }