fix(nacos-client): fix merge conflict

This commit is contained in:
chuntaojun 2019-06-11 09:16:22 +08:00
commit dd9676c2e4
34 changed files with 1246 additions and 213 deletions

View File

@ -32,8 +32,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>7</source>
<target>7</target>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>

View File

@ -66,8 +66,7 @@ public class ServerHttpAgent implements HttpAgent {
public HttpResult httpGet(String path, List<String> headers, List<String> paramValues, String encoding,
long readTimeoutMs) throws IOException {
final long endTime = System.currentTimeMillis() + readTimeoutMs;
boolean isSSL = false;
final boolean isSSL = false;
String currentServerAddr = serverListMgr.getCurrentServerAddr();
int maxRetry = this.maxRetry;

View File

@ -535,8 +535,6 @@ public class ClientWorker {
}
}
// =================
public boolean isHealthServer() {
return isHealthServer;
}
@ -551,11 +549,11 @@ public class ClientWorker {
/**
* groupKey -> cacheData
*/
AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<Map<String, CacheData>>(
private final AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<Map<String, CacheData>>(
new HashMap<String, CacheData>());
HttpAgent agent;
ConfigFilterChainManager configFilterChainManager;
private final HttpAgent agent;
private final ConfigFilterChainManager configFilterChainManager;
private boolean isHealthServer = true;
private long timeout;
private double currentLongingTaskCount = 0;

View File

@ -45,6 +45,8 @@ import java.util.*;
*/
@SuppressWarnings("PMD.ServiceOrDaoClassShouldEndWithImplRule")
public class NacosNamingService implements NamingService {
private static final String DEFAULT_PORT = "8080";
/**
* Each Naming instance should have different namespace.
*/
@ -74,7 +76,6 @@ public class NacosNamingService implements NamingService {
}
public NacosNamingService(Properties properties) {
init(properties);
}
@ -148,7 +149,7 @@ public class NacosNamingService implements NamingService {
cacheDir = System.getProperty("user.home") + "/nacos/naming/" + namespace;
}
}
@Override
public void registerInstance(String serviceName, String ip, int port) throws NacosException {
registerInstance(serviceName, ip, port, Constants.DEFAULT_CLUSTER_NAME);

View File

@ -211,6 +211,6 @@ public class ConcurrentDiskUtil {
}
}
static final int RETRY_COUNT = 10;
static final int SLEEP_BASETIME = 10;
private static final int RETRY_COUNT = 10;
private static final int SLEEP_BASETIME = 10;
}

View File

@ -36,9 +36,9 @@ import static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;
*/
public class HostReactor {
public static final long DEFAULT_DELAY = 1000L;
private static final long DEFAULT_DELAY = 1000L;
public long updateHoldInterval = 5000L;
private static final long UPDATE_HOLD_INTERVAL = 5000L;
private final Map<String, ScheduledFuture<?>> futureMap = new HashMap<String, ScheduledFuture<?>>();
@ -234,11 +234,11 @@ public class HostReactor {
} else if (updatingMap.containsKey(serviceName)) {
if (updateHoldInterval > 0) {
if (UPDATE_HOLD_INTERVAL > 0) {
// hold a moment waiting for update finish
synchronized (serviceObj) {
try {
serviceObj.wait(updateHoldInterval);
serviceObj.wait(UPDATE_HOLD_INTERVAL);
} catch (InterruptedException e) {
NAMING_LOGGER.error("[getServiceInfo] serviceName:" + serviceName + ", clusters:" + clusters, e);
}

View File

@ -86,28 +86,22 @@ public class EnvUtil {
return selfLocationTag;
}
public static String listToString(List<String> list) {
if (list == null) {
private static String listToString(List<String> list) {
if (list == null || list.isEmpty()) {
return null;
}
StringBuilder result = new StringBuilder();
boolean first = true;
// 第一个前面不拼接","
for (String string : list) {
if (first) {
first = false;
} else {
result.append(",");
}
result.append(string);
result.append(",");
}
return result.toString();
return result.toString().substring(0, result.length() - 1);
}
private static String selfAmorayTag;
private static String selfVipserverTag;
private static String selfLocationTag;
public final static String AMORY_TAG = "Amory-Tag";
public final static String VIPSERVER_TAG = "Vipserver-Tag";
public final static String LOCATION_TAG = "Location-Tag";
private final static String AMORY_TAG = "Amory-Tag";
private final static String VIPSERVER_TAG = "Vipserver-Tag";
private final static String LOCATION_TAG = "Location-Tag";
}

View File

@ -38,7 +38,7 @@ public class StringUtils {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
if (!Character.isWhitespace(str.charAt(i))) {
return false;
}
}
@ -46,7 +46,6 @@ public class StringUtils {
}
public static boolean isNotBlank(String str) {
return !isBlank(str);
}

View File

@ -1,134 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>1.0.1</version>
</parent>
<artifactId>nacos-console</artifactId>
<!--<packaging>war</packaging>-->
<packaging>jar</packaging>
<name>nacos-console ${project.version}</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>7.0.59</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>nacos-naming</artifactId>
</dependency>
<!-- log -->
<!-- log4j通过slf4j来代理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<!-- apache commons logging通过slf4j来代理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
<!-- java.util.logging 通过slf4j来代理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</dependency>
<!-- log -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<finalName>nacos-server</finalName>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.1.RELEASE</version>
<configuration>
<mainClass>com.alibaba.nacos.Nacos</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>static/console-fe/.vscode/**</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>nacos-version.txt</include>
</includes>
</resource>
</resources>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-all</artifactId>
<version>1.0.1</version>
</parent>
<artifactId>nacos-console</artifactId>
<!--<packaging>war</packaging>-->
<packaging>jar</packaging>
<name>nacos-console ${project.version}</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>7.0.59</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>nacos-naming</artifactId>
</dependency>
<!-- log -->
<!-- log4j通过slf4j来代理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<!-- apache commons logging通过slf4j来代理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
<!-- java.util.logging 通过slf4j来代理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</dependency>
<!-- log -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<finalName>nacos-server</finalName>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.1.RELEASE</version>
<configuration>
<mainClass>com.alibaba.nacos.Nacos</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>static/console-fe/.vscode/**</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>nacos-version.txt</include>
</includes>
</resource>
</resources>
</build>
</project>

0
console/src/main/resources/nacos-version.txt Executable file → Normal file
View File

View File

@ -38,6 +38,9 @@ module.exports = {
components: resolve('src/components'),
},
},
node: {
fs: 'empty'
},
module: {
rules: [
{

View File

@ -75,6 +75,7 @@
"react-router-dom": "^4.3.1",
"react-router-redux": "^4.0.8",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0"
"redux-thunk": "^2.3.0",
"yamljs": "^0.3.0"
}
}

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1,491 @@
/*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { getParams } from '../../globalLib';
import { ConfigProvider, Dialog, Loading, Tab } from '@alifd/next';
import './index.scss';
const TabPane = Tab.Item;
/**
*
* Service Registration Sample Code Show Window
* @author yongchao9 #2019年05月18日 下午4:26:19
*
*/
@ConfigProvider.config
class ShowServiceCodeing extends React.Component {
static displayName = 'ShowServiceCodeing';
static propTypes = {
locale: PropTypes.object,
};
constructor(props) {
super(props);
this.state = {
dialogvisible: false,
loading: false,
};
this.defaultCode = '';
this.nodejsCode = 'TODO';
this.cppCode = 'TODO';
this.shellCode = 'TODO';
this.pythonCode = 'TODO';
this.record = {};
this.springCode = 'TODO';
this.sprigbootCode = 'TODO';
this.sprigcloudCode = 'TODO';
}
componentDidMount() {
}
openLoading() {
this.setState({
loading: true,
});
}
closeLoading() {
this.setState({
loading: false,
});
}
getData() {
const namespace = getParams('namespace'); // 获取ak,sk
const obj = {
group: this.record.group || '',
dataId: this.record.dataId || '',
namespace,
inEdas: window.globalConfig.isParentEdas(),
};
this.defaultCode = this.getJavaCode(obj);
this.createCodeMirror('text/x-java', this.defaultCode);
this.springCode = this.getSpringCode(obj);
this.sprigbootCode = this.getSpringBootCode(obj);
this.sprigcloudCode = this.getSpringCloudCode(obj);
this.nodejsCode = this.getNodejsCode(obj);
this.cppCode = this.getCppCode(obj);
this.shellCode = this.getShellCode(obj);
this.pythonCode = this.getPythonCode(obj);
this.forceUpdate();
}
getJavaCode(data) {
return `/* Refer to document: https://github.com/alibaba/nacos/blob/master/example/src/main/java/com/alibaba/nacos/example
* pom.xml
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>$\{latest.version}</version>
</dependency>
*/
package com.alibaba.nacos.example;
import java.util.Properties;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.Event;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
/**
* @author nkorange
*/
public class NamingExample {
public static void main(String[] args) throws NacosException {
Properties properties = new Properties();
properties.setProperty("serverAddr", System.getProperty("serverAddr"));
properties.setProperty("namespace", System.getProperty("namespace"));
NamingService naming = NamingFactory.createNamingService(properties);
naming.registerInstance("${this.record.name}", "11.11.11.11", 8888, "TEST1");
naming.registerInstance("${this.record.name}", "2.2.2.2", 9999, "DEFAULT");
System.out.println(naming.getAllInstances("${this.record.name}"));
naming.deregisterInstance("${this.record.name}", "2.2.2.2", 9999, "DEFAULT");
System.out.println(naming.getAllInstances("${this.record.name}"));
naming.subscribe("${this.record.name}", new EventListener() {
@Override
public void onEvent(Event event) {
System.out.println(((NamingEvent)event).getServiceName());
System.out.println(((NamingEvent)event).getInstances());
}
});
}
}`;
}
getSpringCode(data) {
return `/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-example/nacos-spring-discovery-example
* pom.xml
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-spring-context</artifactId>
<version>\${latest.version}</version>
</dependency>
*/
// Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-example/nacos-spring-discovery-example/src/main/java/com/alibaba/nacos/example/spring
package com.alibaba.nacos.example.spring;
import com.alibaba.nacos.api.annotation.NacosProperties;
import com.alibaba.nacos.spring.context.annotation.discovery.EnableNacosDiscovery;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableNacosDiscovery(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848"))
public class NacosConfiguration {
}
// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-example/nacos-spring-discovery-example/src/main/java/com/alibaba/nacos/example/spring/controller
package com.alibaba.nacos.example.spring.controller;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
@Controller
@RequestMapping("discovery")
public class DiscoveryController {
@NacosInjected
private NamingService namingService;
@RequestMapping(value = "/get", method = GET)
@ResponseBody
public List<Instance> get(@RequestParam String serviceName) throws NacosException {
return namingService.getAllInstances(serviceName);
}
}`;
}
getSpringBootCode(data) {
return `/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example
* pom.xml
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>\${latest.version}</version>
</dependency>
*/
/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example/src/main/resources
* application.properties
nacos.discovery.server-addr=127.0.0.1:8848
*/
// Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example/src/main/java/com/alibaba/nacos/example/spring/boot/controller
package com.alibaba.nacos.example.spring.boot.controller;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
@Controller
@RequestMapping("discovery")
public class DiscoveryController {
@NacosInjected
private NamingService namingService;
@RequestMapping(value = "/get", method = GET)
@ResponseBody
public List<Instance> get(@RequestParam String serviceName) throws NacosException {
return namingService.getAllInstances(serviceName);
}
}`;
}
getSpringCloudCode(data) {
return `/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/
* pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>\${latest.version}</version>
</dependency>
*/
// nacos-spring-cloud-provider-example
/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-provider-example/src/main/resources
* application.properties
server.port=18080
spring.application.name=${this.record.name}
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
*/
// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-provider-example/src/main/java/com/alibaba/nacos/example/spring/cloud
package com.alibaba.nacos.example.spring.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* @author xiaojing
*/
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderApplication.class, args);
}
@RestController
class EchoController {
@RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
public String echo(@PathVariable String string) {
return "Hello Nacos Discovery " + string;
}
}
}
// nacos-spring-cloud-consumer-example
/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-consumer-example/src/main/resources
* application.properties
spring.application.name=micro-service-oauth2
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
*/
// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-consumer-example/src/main/java/com/alibaba/nacos/example/spring/cloud
package com.alibaba.nacos.example.spring.cloud;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author xiaojing
*/
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApplication {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApplication.class, args);
}
@RestController
public class TestController {
private final RestTemplate restTemplate;
@Autowired
public TestController(RestTemplate restTemplate) {this.restTemplate = restTemplate;}
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
public String echo(@PathVariable String str) {
return restTemplate.getForObject("http://service-provider/echo/" + str, String.class);
}
}
}`;
}
getNodejsCode(data) {
return 'TODO';
}
getCppCode(data) {
return 'TODO';
}
getShellCode(data) {
return 'TODO';
}
getPythonCode(data) {
return 'TODO';
}
openDialog(record) {
this.setState({
dialogvisible: true,
});
this.record = record;
setTimeout(() => {
this.getData(); // 获取数据
});
}
closeDialog() {
this.setState({
dialogvisible: false,
});
}
createCodeMirror(mode, value) {
const commontarget = this.refs.codepreview;
if (commontarget) {
commontarget.innerHTML = '';
this.cm = window.CodeMirror(commontarget, {
value,
mode,
height: 400,
width: 500,
lineNumbers: true,
theme: 'xq-light',
lint: true,
tabMode: 'indent',
autoMatchParens: true,
textWrapping: true,
gutters: ['CodeMirror-lint-markers'],
extraKeys: {
F1(cm) {
cm.setOption('fullScreen', !cm.getOption('fullScreen'));
},
Esc(cm) {
if (cm.getOption('fullScreen')) cm.setOption('fullScreen', false);
},
},
});
// this.cm.setSize('300px',height:'222px');
this.cm.setSize('auto', '490px');
}
// this.cm.setSize(window.innerWidth*0.8-10,400);//设置宽高
}
changeTab(key, code) {
setTimeout(() => {
this[key] = true;
this.createCodeMirror('text/javascript', code);
});
}
render() {
const { locale = {} } = this.props;
const footer = <div />;
return (
<div>
<Dialog
title={locale.sampleCode}
style={{ width: '80%' }}
visible={this.state.dialogvisible}
footer={footer}
onClose={this.closeDialog.bind(this)}
>
<div style={{ height: 500 }}>
<Loading tip={locale.loading} style={{ width: '100%' }} visible={this.state.loading}>
<Tab shape={'text'} style={{ height: 40, paddingBottom: 10 }}>
<TabPane
title={'Java'}
key={0}
onClick={this.changeTab.bind(this, 'commoneditor1', this.defaultCode)}
/>
<TabPane
title={'Spring'}
key={1}
onClick={this.changeTab.bind(this, 'commoneditor1', this.springCode)}
/>
<TabPane
title={'Spring Boot'}
key={2}
onClick={this.changeTab.bind(this, 'commoneditor2', this.sprigbootCode)}
/>
<TabPane
title={'Spring Cloud'}
key={21}
onClick={this.changeTab.bind(this, 'commoneditor21', this.sprigcloudCode)}
/>
<TabPane
title={'Node.js'}
key={3}
onClick={this.changeTab.bind(this, 'commoneditor3', this.nodejsCode)}
/>
<TabPane
title={'C++'}
key={4}
onClick={this.changeTab.bind(this, 'commoneditor4', this.cppCode)}
/>
<TabPane
title={'Shell'}
key={5}
onClick={this.changeTab.bind(this, 'commoneditor5', this.shellCode)}
/>
<TabPane
title={'Python'}
key={6}
onClick={this.changeTab.bind(this, 'commoneditor6', this.pythonCode)}
/>
{}
</Tab>
<div ref={'codepreview'} />
</Loading>
</div>
</Dialog>
</div>
);
}
}
export default ShowServiceCodeing;

View File

@ -41,6 +41,7 @@ import ListeningToQuery from './pages/ConfigurationManagement/ListeningToQuery';
import ConfigurationManagement from './pages/ConfigurationManagement/ConfigurationManagement';
import ServiceList from './pages/ServiceManagement/ServiceList';
import ServiceDetail from './pages/ServiceManagement/ServiceDetail';
import ClusterNodeList from './pages/ClusterManagement/ClusterNodeList';
import reducers from './reducers';
import { changeLanguage } from './reducers/locale';
@ -81,6 +82,7 @@ const MENU = [
{ path: '/configurationManagement', component: ConfigurationManagement },
{ path: '/serviceManagement', component: ServiceList },
{ path: '/serviceDetail', component: ServiceDetail },
{ path: '/clusterManagement', component: ClusterNodeList },
];
@connect(

View File

@ -391,7 +391,7 @@ class MainLayout extends React.Component {
refreshNav() {
const { navList } = this.state;
const { location, history, functionMode } = this.props;
const [configUrl, serviceUrl] = ['/configurationManagement', '/serviceManagement'];
const [configUrl, serviceUrl, clusterUrl] = ['/configurationManagement', '/serviceManagement', '/clusterManagement'];
this.setState(
{
navList: navList.map(item => {
@ -407,6 +407,12 @@ class MainLayout extends React.Component {
) {
item.enable = true;
}
if (
item.serviceName === 'clusterManagementVirtual' &&
(functionMode === null || functionMode === 'cluster')
) {
item.enable = true;
}
return item;
}),
},
@ -418,6 +424,9 @@ class MainLayout extends React.Component {
if (functionMode === 'naming' && location.pathname === configUrl) {
history.push(serviceUrl);
}
if (functionMode === 'cluster' && location.pathname === clusterUrl) {
history.push(clusterUrl);
}
}
componentWillReceiveProps() {

View File

@ -46,6 +46,8 @@ const I18N_CONF = {
serviceManagement: 'Service List',
serviceDetail: 'Service Details',
namespace: 'Namespace',
clusterManagementVirtual: 'ClusterManagement',
clusterManagement: 'Cluster Node List',
},
NameSpace: {
namespace: 'Namespaces',
@ -84,11 +86,24 @@ const I18N_CONF = {
columnHealthyInstanceCount: 'Healthy Instance Count',
operation: 'Operation',
detail: 'Details',
sampleCode: 'Code Example',
deleteAction: 'Delete',
prompt: 'Confirm',
promptDelete: 'Do you want to delete the service?',
create: 'Create Service',
},
ClusterNodeList: {
clusterNodeList: 'Node List',
nodeIp: 'NodeIp',
nodeIpPlaceholder: 'Please enter node Ip',
query: 'Search',
pubNoData: 'No results found.',
nodeState: 'NodeState',
clusterTerm: 'ClusterTerm',
leaderDueMs: 'LeaderDue(ms)',
heartbeatDueMs: 'HeartbeatDue(ms)',
voteFor: 'VoteFor',
},
EditClusterDialog: {
updateCluster: 'Update Cluster',
checkType: 'Check Type',

View File

@ -46,6 +46,8 @@ const I18N_CONF = {
serviceManagement: '服务列表',
serviceDetail: '服务详情',
namespace: '命名空间',
clusterManagementVirtual: '集群管理',
clusterManagement: '节点列表',
},
NameSpace: {
namespace: '命名空间',
@ -84,11 +86,24 @@ const I18N_CONF = {
columnHealthyInstanceCount: '健康实例数',
operation: '操作',
detail: '详情',
sampleCode: '示例代码',
deleteAction: '删除',
prompt: '提示',
promptDelete: '确定要删除当前服务吗',
create: '创建服务',
},
ClusterNodeList: {
clusterNodeList: '节点列表',
nodeIp: '节点Ip',
nodeIpPlaceholder: '请输入节点Ip',
query: '查询',
pubNoData: '没有数据',
nodeState: '节点状态',
clusterTerm: '集群任期',
leaderDueMs: 'Leader止时(ms)',
heartbeatDueMs: '心跳止时(ms)',
voteFor: '投票对象',
},
EditClusterDialog: {
updateCluster: '更新集群',
checkType: '检查类型',

View File

@ -227,6 +227,37 @@ module.exports = {
useRouter: false,
id: 'namespace',
},
{
enable: false,
isExtend: true,
name: '集群管理',
title: '集群管理',
isVirtual: true,
projectName: 'nacos',
serviceName: 'clusterManagementVirtual',
link: 'clusterManagementVirtual',
hasFusion: true,
template: '',
registerName: 'com.alibaba.nacos.page.clusterManagementVirtual',
useRouter: false,
id: 'com.alibaba.nacos.page.clusterManagementVirtual',
children: [
{
isExtend: false,
name: '节点状态',
title: '节点状态',
isVirtual: false,
projectName: 'nacos',
serviceName: 'clusterManagement',
link: 'clusterManagement',
hasFusion: true,
template: '',
registerName: 'com.alibaba.nacos.page.clusterManagement',
useRouter: false,
id: 'clusterManagement',
},
],
},
],
defaultKey: 'configurationManagement',
projectName: 'nacos',

View File

@ -0,0 +1,204 @@
/*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import {
Button,
Field,
Form,
Grid,
Input,
Loading,
Pagination,
Table,
ConfigProvider,
} from '@alifd/next';
import { request } from '../../../globalLib';
import RegionGroup from '../../../components/RegionGroup';
import './ClusterNodeList.scss';
const FormItem = Form.Item;
const { Row, Col } = Grid;
const { Column } = Table;
@ConfigProvider.config
class ClusterNodeList extends React.Component {
static displayName = 'ClusterNodeList';
static propTypes = {
locale: PropTypes.object,
};
constructor(props) {
super(props);
this.state = {
loading: false,
total: 0,
pageSize: 10,
currentPage: 1,
keyword: '',
dataSource: [],
};
this.field = new Field(this);
}
openLoading() {
this.setState({ loading: true });
}
closeLoading() {
this.setState({ loading: false });
}
openEditServiceDialog() {
try {
this.editServiceDialog.current.getInstance().show(this.state.service);
} catch (error) {}
}
queryClusterStateList() {
const { currentPage, pageSize, keyword, withInstances = false } = this.state;
const parameter = [
`withInstances=${withInstances}`,
`pageNo=${currentPage}`,
`pageSize=${pageSize}`,
`keyword=${keyword}`,
];
request({
url: `v1/ns/operator/cluster/states?${parameter.join('&')}`,
beforeSend: () => this.openLoading(),
success: ({ count = 0, clusterStateList = [] } = {}) => {
this.setState({
dataSource: clusterStateList,
total: count,
});
},
error: () =>
this.setState({
dataSource: [],
total: 0,
currentPage: 0,
}),
complete: () => this.closeLoading(),
});
}
getQueryLater = () => {
setTimeout(() => this.queryClusterStateList());
};
setNowNameSpace = (nowNamespaceName, nowNamespaceId) =>
this.setState({
nowNamespaceName,
nowNamespaceId,
});
rowColor = row => ({ className: !row.voteFor ? '' : '' });
render() {
const { locale = {} } = this.props;
const {
pubNoData,
clusterNodeList,
nodeIp,
nodeIpPlaceholder,
query,
} = locale;
const { keyword, nowNamespaceName, nowNamespaceId } = this.state;
const { init, getValue } = this.field;
this.init = init;
this.getValue = getValue;
return (
<div className="main-container cluster-management">
<Loading
shape="flower"
style={{ position: 'relative', width: '100%' }}
visible={this.state.loading}
tip="Loading..."
color="#333"
>
<div style={{ marginTop: -15 }}>
<RegionGroup
setNowNameSpace={this.setNowNameSpace}
namespaceCallBack={this.getQueryLater}
/>
</div>
<h3 className="page-title">
<span className="title-item">{clusterNodeList}</span>
<span className="title-item">|</span>
<span className="title-item">{nowNamespaceName}</span>
<span className="title-item">{nowNamespaceId}</span>
</h3>
<Row className="demo-row" style={{ marginBottom: 10, padding: 0 }}>
<Col span="24">
<Form inline field={this.field}>
<FormItem label={nodeIp}>
<Input
placeholder={nodeIpPlaceholder}
style={{ width: 200 }}
value={keyword}
onChange={keyword => this.setState({ keyword })}
onPressEnter={() =>
this.setState({ currentPage: 1 }, () => this.queryClusterStateList())
}
/>
</FormItem>
<FormItem label="">
<Button
type="primary"
onClick={() => this.setState({ currentPage: 1 }, () => this.queryClusterStateList())}
style={{ marginRight: 10 }}
>
{query}
</Button>
</FormItem>
</Form>
</Col>
</Row>
<Row style={{ padding: 0 }}>
<Col span="24" style={{ padding: 0 }}>
<Table
dataSource={this.state.dataSource}
locale={{ empty: pubNoData }}
getRowProps={row => this.rowColor(row)}
>
<Column title={locale.nodeIp} dataIndex="nodeIp" />
<Column title={locale.nodeState} dataIndex="nodeState" />
<Column title={locale.clusterTerm} dataIndex="clusterTerm" />
<Column title={locale.leaderDueMs} dataIndex="leaderDueMs" />
<Column title={locale.heartbeatDueMs} dataIndex="heartbeatDueMs" />
</Table>
</Col>
</Row>
{this.state.total > this.state.pageSize && (
<div style={{ marginTop: 10, textAlign: 'right' }}>
<Pagination
current={this.state.currentPage}
total={this.state.total}
pageSize={this.state.pageSize}
onChange={currentPage =>
this.setState({ currentPage }, () => this.queryClusterStateList())
}
/>
</div>
)}
</Loading>
</div>
);
}
}
export default ClusterNodeList;

View File

@ -0,0 +1,29 @@
/*
* 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.
*/
.cluster-management {
.page-title {
height: 30px;
width: 100%;
line-height: 30px;
margin: 0 0 20px;
padding: 0 0 0 10px;
border-left: 3px solid #09c;
color: #ccc;
}
.title-item {
font-size: 14px;
color: #000;
margin-right: 8px;
}
}

View File

@ -0,0 +1,16 @@
/*
* 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.
*/
import ClusterNodeList from './ClusterNodeList';
export default ClusterNodeList;

View File

@ -29,6 +29,7 @@ import {
import { request } from '../../../globalLib';
import RegionGroup from '../../../components/RegionGroup';
import EditServiceDialog from '../ServiceDetail/EditServiceDialog';
import ShowServiceCodeing from 'components/ShowCodeing/ShowServiceCodeing';
import './ServiceList.scss';
@ -48,6 +49,7 @@ class ServiceList extends React.Component {
constructor(props) {
super(props);
this.editServiceDialog = React.createRef();
this.showcode = React.createRef();
this.state = {
loading: false,
total: 0,
@ -69,8 +71,10 @@ class ServiceList extends React.Component {
openEditServiceDialog() {
try {
this.editServiceDialog.current.getInstance().show(this.state.service);
} catch (error) {}
this.editServiceDialog.current.getInstance()
.show(this.state.service);
} catch (error) {
}
}
queryServiceList() {
@ -104,6 +108,21 @@ class ServiceList extends React.Component {
setTimeout(() => this.queryServiceList());
};
showcode = () => {
setTimeout(() => this.queryServiceList());
};
/**
*
* Added method to open sample code window
* @author yongchao9 #2019年05月18日 下午5:46:28
*
*/
showSampleCode(record) {
this.showcode.current.getInstance()
.openDialog(record);
}
deleteService(service) {
const { locale = {} } = this.props;
const { prompt, promptDelete } = locale;
@ -138,6 +157,7 @@ class ServiceList extends React.Component {
rowColor = row => ({ className: !row.healthyInstanceCount ? 'row-bg-red' : '' });
render() {
const { locale = {} } = this.props;
const {
@ -149,6 +169,7 @@ class ServiceList extends React.Component {
create,
operation,
detail,
sampleCode,
deleteAction,
} = locale;
const { keyword, nowNamespaceName, nowNamespaceId } = this.state;
@ -160,7 +181,10 @@ class ServiceList extends React.Component {
<div className="main-container service-management">
<Loading
shape="flower"
style={{ position: 'relative', width: '100%' }}
style={{
position: 'relative',
width: '100%',
}}
visible={this.state.loading}
tip="Loading..."
color="#333"
@ -177,7 +201,13 @@ class ServiceList extends React.Component {
<span className="title-item">{nowNamespaceName}</span>
<span className="title-item">{nowNamespaceId}</span>
</h3>
<Row className="demo-row" style={{ marginBottom: 10, padding: 0 }}>
<Row
className="demo-row"
style={{
marginBottom: 10,
padding: 0,
}}
>
<Col span="24">
<Form inline field={this.field}>
<FormItem label={serviceName}>
@ -227,24 +257,32 @@ class ServiceList extends React.Component {
title={operation}
align="center"
cell={(value, index, record) => (
// @author yongchao9 #2019年05月18日 下午5:46:28
/* Add a link to view "sample code"
replace the original button with a label,
which is consistent with the operation style in configuration management.
*/
<div>
<Button
type="normal"
<a
onClick={() =>
this.props.history.push(
`/serviceDetail?name=${record.name}&groupName=${record.groupName}`
)
}
`/serviceDetail?name=${record.name}&groupName=${record.groupName}`,
)}
style={{ marginRight: 5 }}
>
{detail}
</Button>
<Button
style={{ marginLeft: 12 }}
type="normal"
</a>
<span style={{ marginRight: 5 }}>|</span>
<a style={{ marginRight: 5 }} onClick={() => this.showSampleCode(record)}>
{sampleCode}
</a>
<span style={{ marginRight: 5 }}>|</span>
<a
onClick={() => this.deleteService(record)}
style={{ marginRight: 5 }}
>
{deleteAction}
</Button>
</a>
</div>
)}
/>
@ -252,7 +290,11 @@ class ServiceList extends React.Component {
</Col>
</Row>
{this.state.total > this.state.pageSize && (
<div style={{ marginTop: 10, textAlign: 'right' }}>
<div style={{
marginTop: 10,
textAlign: 'right',
}}
>
<Pagination
current={this.state.currentPage}
total={this.state.total}
@ -264,6 +306,7 @@ class ServiceList extends React.Component {
</div>
)}
</Loading>
<ShowServiceCodeing ref={this.showcode} />
<EditServiceDialog
ref={this.editServiceDialog}
openLoading={() => this.openLoading()}

View File

@ -1,3 +1,5 @@
import * as yamljs from 'yamljs';
export default {
/**
* 检测json是否合法
@ -35,15 +37,13 @@ export default {
/**
* 检测yaml是否合法
*/
// validateYaml(str) {
// try {
// console.log('yaml: ', yaml, yaml.safeLoadAll(str));
// return !!yaml.safeLoadAll(str);
// } catch (e) {
// console.log('e: ', e);
// return false;
// }
// },
validateYaml(str) {
try {
return yamljs.parse(str);
} catch (e) {
return false;
}
},
/**
* 检测属性是否正确
@ -66,6 +66,7 @@ export default {
'text/html': this.validateXml,
html: this.validateXml,
properties: this.validateProperties,
yaml: this.validateYaml,
};
if (!validateObj[type]) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -41,7 +41,7 @@ import static com.alibaba.nacos.core.utils.SystemUtils.*;
@Component("serverListManager")
public class ServerListManager {
public static final int STABLE_PERIOD = 60 * 1000;
private static final int STABLE_PERIOD = 60 * 1000;
@Autowired
private SwitchDomain switchDomain;

View File

@ -16,11 +16,14 @@
package com.alibaba.nacos.naming.controllers;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.naming.CommonParams;
import com.alibaba.nacos.api.naming.pojo.AbstractHealthChecker;
import com.alibaba.nacos.core.utils.WebUtils;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeerSet;
import com.alibaba.nacos.naming.core.Cluster;
import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager;
@ -28,6 +31,8 @@ import com.alibaba.nacos.naming.exception.NacosException;
import com.alibaba.nacos.naming.healthcheck.HealthCheckType;
import com.alibaba.nacos.naming.misc.Loggers;
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
import com.alibaba.nacos.naming.pojo.ClusterStateView;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
@ -37,6 +42,9 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author nkorange

View File

@ -235,10 +235,6 @@ public class InstanceController {
String clusterName = clientBeat.getCluster();
if (StringUtils.isBlank(clusterName)) {
clusterName = UtilsAndCommons.DEFAULT_CLUSTER_NAME;
}
if (Loggers.DEBUG_LOG.isDebugEnabled()) {
Loggers.DEBUG_LOG.debug("[CLIENT-BEAT] full arguments: beat: {}, serviceName: {}", clientBeat, serviceName);
}

View File

@ -24,6 +24,8 @@ import com.alibaba.nacos.core.utils.WebUtils;
import com.alibaba.nacos.naming.cluster.ServerListManager;
import com.alibaba.nacos.naming.cluster.ServerStatusManager;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftCore;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeerSet;
import com.alibaba.nacos.naming.core.DistroMapper;
import com.alibaba.nacos.naming.core.Service;
import com.alibaba.nacos.naming.core.ServiceManager;
@ -31,8 +33,10 @@ import com.alibaba.nacos.naming.misc.SwitchDomain;
import com.alibaba.nacos.naming.misc.SwitchEntry;
import com.alibaba.nacos.naming.misc.SwitchManager;
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
import com.alibaba.nacos.naming.pojo.ClusterStateView;
import com.alibaba.nacos.naming.push.PushService;
import com.alibaba.nacos.naming.web.NeedAuth;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
@ -42,6 +46,8 @@ import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
@ -77,6 +83,9 @@ public class OperatorController {
@Autowired
private RaftCore raftCore;
@Autowired
private RaftPeerSet raftPeerSet;
@RequestMapping("/push/state")
public JSONObject pushState(HttpServletRequest request) {
@ -215,4 +224,41 @@ public class OperatorController {
serverListManager.onReceiveServerStatus(serverStatus);
return "ok";
}
@RequestMapping(value = "/cluster/states", method = RequestMethod.GET)
public Object listStates(HttpServletRequest request) {
String namespaceId = WebUtils.optional(request, CommonParams.NAMESPACE_ID,
Constants.DEFAULT_NAMESPACE_ID);
JSONObject result = new JSONObject();
int page = Integer.parseInt(WebUtils.required(request, "pageNo"));
int pageSize = Integer.parseInt(WebUtils.required(request, "pageSize"));
String keyword = WebUtils.optional(request, "keyword", StringUtils.EMPTY);
String containedInstance = WebUtils.optional(request, "instance", StringUtils.EMPTY);
List<RaftPeer> raftPeerLists = new ArrayList<>();
int total = serviceManager.getPagedClusterState(namespaceId, page - 1, pageSize, keyword, containedInstance, raftPeerLists, raftPeerSet);
if (CollectionUtils.isEmpty(raftPeerLists)) {
result.put("clusterStateList", Collections.emptyList());
result.put("count", 0);
return result;
}
JSONArray clusterStateJsonArray = new JSONArray();
for(RaftPeer raftPeer: raftPeerLists) {
ClusterStateView clusterStateView = new ClusterStateView();
clusterStateView.setClusterTerm(raftPeer.term.intValue());
clusterStateView.setNodeIp(raftPeer.ip);
clusterStateView.setNodeState(raftPeer.state.name());
clusterStateView.setVoteFor(raftPeer.voteFor);
clusterStateView.setHeartbeatDueMs(raftPeer.heartbeatDueMs);
clusterStateView.setLeaderDueMs(raftPeer.leaderDueMs);
clusterStateJsonArray.add(clusterStateView);
}
result.put("clusterStateList", clusterStateJsonArray);
result.put("count", total);
return result;
}
}

View File

@ -27,6 +27,8 @@ import com.alibaba.nacos.naming.consistency.ConsistencyService;
import com.alibaba.nacos.naming.consistency.Datum;
import com.alibaba.nacos.naming.consistency.KeyBuilder;
import com.alibaba.nacos.naming.consistency.RecordListener;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeerSet;
import com.alibaba.nacos.naming.misc.*;
import com.alibaba.nacos.naming.push.PushService;
import org.apache.commons.lang3.ArrayUtils;
@ -227,6 +229,41 @@ public class ServiceManager implements RecordListener<Service> {
}
}
public int getPagedClusterState(String namespaceId, int startPage, int pageSize, String keyword, String containedInstance, List<RaftPeer> raftPeerList, RaftPeerSet raftPeerSet) {
List<RaftPeer> matchList = new ArrayList<>(raftPeerSet.allPeers());
List<RaftPeer> tempList = new ArrayList<>();
if(StringUtils.isNotBlank(keyword)) {
for(RaftPeer raftPeer: matchList) {
String ip = raftPeer.ip.split(":")[0];
if(keyword.equals(ip)) {
tempList.add(raftPeer);
}
}
matchList = tempList;
}
if (pageSize >= matchList.size()) {
raftPeerList.addAll(matchList);
return matchList.size();
}
for (int i = 0; i < matchList.size(); i++) {
if (i < startPage * pageSize) {
continue;
}
raftPeerList.add(matchList.get(i));
if (raftPeerList.size() >= pageSize) {
break;
}
}
return matchList.size();
}
public void updatedHealthStatus(String namespaceId, String serviceName, String serverIP) {
Message msg = synchronizer.get(serverIP, UtilsAndCommons.assembleFullServiceName(namespaceId, serviceName));
JSONObject serviceJson = JSON.parseObject(msg.getData());

View File

@ -18,6 +18,7 @@ package com.alibaba.nacos.naming.misc;
import com.alibaba.nacos.naming.boot.RunningConfig;
import com.ning.http.client.AsyncCompletionHandler;
import com.ning.http.client.Response;
import org.springframework.util.StringUtils;
import java.net.HttpURLConnection;
import java.util.HashMap;
@ -31,7 +32,7 @@ import java.util.Map;
public class ServerStatusSynchronizer implements Synchronizer {
@Override
public void send(final String serverIP, Message msg) {
if (serverIP == null) {
if (StringUtils.isEmpty(serverIP)) {
return;
}

View File

@ -0,0 +1,94 @@
/*
* 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.naming.pojo;
import com.alibaba.fastjson.JSON;
/**
* @author: universefeeler
* @Date: 2019/05/19 15:51
* @Description:
*/
public class ClusterStateView{
private String nodeIp;
private String nodeState;
private long clusterTerm;
private long leaderDueMs;
private String voteFor;
private long heartbeatDueMs;
public long getLeaderDueMs() {
return leaderDueMs;
}
public void setLeaderDueMs(long leaderDueMs) {
this.leaderDueMs = leaderDueMs;
}
public long getHeartbeatDueMs() {
return heartbeatDueMs;
}
public void setHeartbeatDueMs(long heartbeatDueMs) {
this.heartbeatDueMs = heartbeatDueMs;
}
public String getVoteFor() {
return voteFor;
}
public void setVoteFor(String voteFor) {
this.voteFor = voteFor;
}
public String getNodeIp() {
return nodeIp;
}
public void setNodeIp(String nodeIp) {
this.nodeIp = nodeIp;
}
public String getNodeState() {
return nodeState;
}
public void setNodeState(String nodeState) {
this.nodeState = nodeState;
}
public long getClusterTerm() {
return clusterTerm;
}
public void setClusterTerm(long clusterTerm) {
this.clusterTerm = clusterTerm;
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
}