From 190ac8d057ccffcafd1e4840b7aa482de77673b4 Mon Sep 17 00:00:00 2001 From: hxy1991 Date: Wed, 5 Dec 2018 20:33:50 +0800 Subject: [PATCH 1/4] Fixes #391 --- .../console/controller/HealthController.java | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 console/src/main/java/com/alibaba/nacos/console/controller/HealthController.java diff --git a/console/src/main/java/com/alibaba/nacos/console/controller/HealthController.java b/console/src/main/java/com/alibaba/nacos/console/controller/HealthController.java new file mode 100644 index 000000000..0e59b188d --- /dev/null +++ b/console/src/main/java/com/alibaba/nacos/console/controller/HealthController.java @@ -0,0 +1,108 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.nacos.console.controller; + +import com.alibaba.nacos.config.server.service.PersistService; +import com.alibaba.nacos.naming.web.ApiCommands; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author hxy1991 + */ +@RestController("consoleHealth") +@RequestMapping("/v1/console/health") +public class HealthController { + + private static final Logger logger = LoggerFactory.getLogger(HealthController.class); + + private final PersistService persistService; + private final ApiCommands apiCommands; + + @Autowired + public HealthController(PersistService persistService, ApiCommands apiCommands) { + this.persistService = persistService; + this.apiCommands = apiCommands; + } + + /** + * Whether the Nacos is in broken states or not, and cannot recover except by being restarted + * + * @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code equal to 500 indicates that + * Nacos is in broken states. + */ + @ResponseBody + @RequestMapping(value = "liveness", method = RequestMethod.GET) + public ResponseEntity liveness() { + return ResponseEntity.ok().body("OK"); + } + + /** + * Ready to receive the request or not + * + * @return HTTP code equal to 200 indicates that Nacos is ready. HTTP code equal to 500 indicates that Nacos is not + * ready. + */ + @ResponseBody + @RequestMapping(value = "readiness", method = RequestMethod.GET) + public ResponseEntity readiness(HttpServletRequest request) { + boolean isConfigReadiness = isConfigReadiness(); + boolean isNamingReadiness = isNamingReadiness(request); + + if (isConfigReadiness && isNamingReadiness) { + return ResponseEntity.ok().body("OK"); + } + + if (!isConfigReadiness && !isNamingReadiness) { + return ResponseEntity.status(500).body("Config and Naming are not in readiness"); + } + + if (!isConfigReadiness) { + return ResponseEntity.status(500).body("Config is not in readiness"); + } + + return ResponseEntity.status(500).body("Naming is not in readiness"); + } + + private boolean isConfigReadiness() { + // check db + try { + persistService.configInfoCount(""); + return true; + } catch (Exception e) { + logger.error("Config health check fail.", e); + } + return false; + } + + private boolean isNamingReadiness(HttpServletRequest request) { + try { + apiCommands.hello(request); + return true; + } catch (Exception e) { + logger.error("Naming health check fail.", e); + } + return false; + } +} From 6deb418c360c3286b08f5572f38749dfd4840ce1 Mon Sep 17 00:00:00 2001 From: hxy1991 Date: Wed, 5 Dec 2018 21:41:03 +0800 Subject: [PATCH 2/4] Fixes #391 --- console/pom.xml | 8 +- .../controller/HealthControllerTest.java | 91 +++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 console/src/test/java/com/alibaba/nacos/console/controller/HealthControllerTest.java diff --git a/console/pom.xml b/console/pom.xml index 56e333670..ee482ec26 100644 --- a/console/pom.xml +++ b/console/pom.xml @@ -59,8 +59,12 @@ org.slf4j jul-to-slf4j - - + + + org.mockito + mockito-core + test + nacos-server diff --git a/console/src/test/java/com/alibaba/nacos/console/controller/HealthControllerTest.java b/console/src/test/java/com/alibaba/nacos/console/controller/HealthControllerTest.java new file mode 100644 index 000000000..62bb784cd --- /dev/null +++ b/console/src/test/java/com/alibaba/nacos/console/controller/HealthControllerTest.java @@ -0,0 +1,91 @@ +package com.alibaba.nacos.console.controller; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.nacos.config.server.service.PersistService; +import com.alibaba.nacos.naming.web.ApiCommands; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import javax.servlet.http.HttpServletRequest; + +import static org.mockito.ArgumentMatchers.any; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = MockServletContext.class) +@WebAppConfiguration +public class HealthControllerTest { + + @InjectMocks + private HealthController healthController; + + @Mock + private PersistService persistService; + + @Mock + private ApiCommands apiCommands; + + private MockMvc mockmvc; + + @Before + public void setUp() { + mockmvc = MockMvcBuilders.standaloneSetup(healthController).build(); + } + + @Test + public void testLiveness() throws Exception { + String url = "/v1/console/health/liveness"; + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(url); + Assert.assertEquals(200, mockmvc.perform(builder).andReturn().getResponse().getStatus()); + } + + @Test + public void testReadiness() throws Exception { + String url = "/v1/console/health/readiness"; + + Mockito.when(persistService.configInfoCount(any(String.class))).thenReturn(0); + Mockito.when(apiCommands.hello(any(HttpServletRequest.class))).thenReturn(new JSONObject()); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(url); + Assert.assertEquals(200, mockmvc.perform(builder).andReturn().getResponse().getStatus()); + + // Config and Naming are not in readiness + Mockito.when(persistService.configInfoCount(any(String.class))).thenThrow( + new RuntimeException("HealthControllerTest.testReadiness")); + Mockito.when(apiCommands.hello(any(HttpServletRequest.class))).thenThrow( + new RuntimeException("HealthControllerTest.testReadiness")); + builder = MockMvcRequestBuilders.get(url); + MockHttpServletResponse response = mockmvc.perform(builder).andReturn().getResponse(); + Assert.assertEquals(500, response.getStatus()); + Assert.assertEquals("Config and Naming are not in readiness", response.getContentAsString()); + + // Config is not in readiness + Mockito.when(persistService.configInfoCount(any(String.class))).thenThrow( + new RuntimeException("HealthControllerTest.testReadiness")); + Mockito.when(apiCommands.hello(any(HttpServletRequest.class))).thenReturn(new JSONObject()); + response = mockmvc.perform(builder).andReturn().getResponse(); + Assert.assertEquals(500, response.getStatus()); + Assert.assertEquals("Config is not in readiness", response.getContentAsString()); + + // Naming is not in readiness + Mockito.when(persistService.configInfoCount(any(String.class))).thenReturn(0); + Mockito.when(apiCommands.hello(any(HttpServletRequest.class))).thenThrow( + new RuntimeException("HealthControllerTest.testReadiness")); + builder = MockMvcRequestBuilders.get(url); + response = mockmvc.perform(builder).andReturn().getResponse(); + Assert.assertEquals(500, response.getStatus()); + Assert.assertEquals("Naming is not in readiness", response.getContentAsString()); + } +} \ No newline at end of file From 25819dce2875844ef9d1d62ddba83cce7acda683 Mon Sep 17 00:00:00 2001 From: hxy1991 Date: Wed, 5 Dec 2018 22:36:33 +0800 Subject: [PATCH 3/4] Fixes #229 --- .../com/alibaba/nacos/client/logger/slf4j/Slf4jLogger.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/src/main/java/com/alibaba/nacos/client/logger/slf4j/Slf4jLogger.java b/client/src/main/java/com/alibaba/nacos/client/logger/slf4j/Slf4jLogger.java index ae8339c4c..e70453143 100644 --- a/client/src/main/java/com/alibaba/nacos/client/logger/slf4j/Slf4jLogger.java +++ b/client/src/main/java/com/alibaba/nacos/client/logger/slf4j/Slf4jLogger.java @@ -65,6 +65,10 @@ public class Slf4jLogger extends LoggerSupport implements Logger { activateOptionClass = "com.alibaba.nacos.client.logger.option.Slf4jLog4j2AdapterActivateOption"; } + if (activateOptionClass == null) { + throw new IllegalArgumentException("delegate must be logback impl or slf4j-log4j impl"); + } + try { Class clazz = (Class)Class.forName(activateOptionClass); Constructor c = clazz.getConstructor(Object.class); From 1ca774b42c3b607eddf87447cf434c880f49ed84 Mon Sep 17 00:00:00 2001 From: hxy1991 Date: Wed, 5 Dec 2018 22:50:52 +0800 Subject: [PATCH 4/4] Fixes #391 --- .../controller/HealthControllerTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/console/src/test/java/com/alibaba/nacos/console/controller/HealthControllerTest.java b/console/src/test/java/com/alibaba/nacos/console/controller/HealthControllerTest.java index 62bb784cd..63582743a 100644 --- a/console/src/test/java/com/alibaba/nacos/console/controller/HealthControllerTest.java +++ b/console/src/test/java/com/alibaba/nacos/console/controller/HealthControllerTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.alibaba.nacos.console.controller; import com.alibaba.fastjson.JSONObject; @@ -24,6 +39,9 @@ import javax.servlet.http.HttpServletRequest; import static org.mockito.ArgumentMatchers.any; +/** + * @author hxy1991 + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MockServletContext.class) @WebAppConfiguration