负载均衡bugfix;监听并发问题bugfix;direct memory泄漏bugfix (#4365)
* memory gc optimize ; string pool bugfix * grpc executor * grpc executor * 负载均衡bugfix;监听并发问题bugfix;direct memory泄漏bugfix * check style fix
This commit is contained in:
parent
c1e4068dfe
commit
ad98020770
@ -81,8 +81,10 @@ public class DefaultRequestFuture implements RequestFuture {
|
|||||||
this.requestCallBack = requestCallBack;
|
this.requestCallBack = requestCallBack;
|
||||||
this.requestId = requestId;
|
this.requestId = requestId;
|
||||||
this.connectionId = connectionId;
|
this.connectionId = connectionId;
|
||||||
this.timeoutFuture = RpcScheduledExecutor.TIMEOUT_SHEDULER
|
if (requestCallBack != null) {
|
||||||
.schedule(new TimeoutHandler(), requestCallBack.getTimeout(), TimeUnit.MILLISECONDS);
|
this.timeoutFuture = RpcScheduledExecutor.TIMEOUT_SHEDULER
|
||||||
|
.schedule(new TimeoutHandler(), requestCallBack.getTimeout(), TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
this.timeoutInnerTrigger = timeoutInnerTrigger;
|
this.timeoutInnerTrigger = timeoutInnerTrigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,4 +83,11 @@ public interface Requester {
|
|||||||
* close connection.
|
* close connection.
|
||||||
*/
|
*/
|
||||||
public void close();
|
public void close();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check this requester is busy.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isBusy();
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,11 @@ public abstract class Connection implements Requester {
|
|||||||
this.serverInfo = serverInfo;
|
this.serverInfo = serverInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBusy() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter method for property <tt>abandon</tt>.
|
* Getter method for property <tt>abandon</tt>.
|
||||||
*
|
*
|
||||||
|
@ -78,8 +78,7 @@ public class GrpcConnection extends Connection {
|
|||||||
try {
|
try {
|
||||||
grpcResponse = requestFuture.get(timeouts, TimeUnit.MILLISECONDS);
|
grpcResponse = requestFuture.get(timeouts, TimeUnit.MILLISECONDS);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
throw new NacosException(NacosException.SERVER_ERROR, e);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Response response = (Response) GrpcUtils.parse(grpcResponse).getBody();
|
Response response = (Response) GrpcUtils.parse(grpcResponse).getBody();
|
||||||
@ -101,13 +100,7 @@ public class GrpcConnection extends Connection {
|
|||||||
@Override
|
@Override
|
||||||
public Response get() throws InterruptedException, ExecutionException {
|
public Response get() throws InterruptedException, ExecutionException {
|
||||||
Payload grpcResponse = null;
|
Payload grpcResponse = null;
|
||||||
try {
|
grpcResponse = requestFuture.get();
|
||||||
grpcResponse = requestFuture.get();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Response response = (Response) GrpcUtils.parse(grpcResponse).getBody();
|
Response response = (Response) GrpcUtils.parse(grpcResponse).getBody();
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@ -177,6 +170,10 @@ public class GrpcConnection extends Connection {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
if (this.payloadStreamObserver != null) {
|
||||||
|
payloadStreamObserver.onCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.channel != null && !channel.isShutdown()) {
|
if (this.channel != null && !channel.isShutdown()) {
|
||||||
this.channel.shutdownNow();
|
this.channel.shutdownNow();
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,10 @@ public class ConnectionAlreadyClosedException extends RemoteException {
|
|||||||
|
|
||||||
private static final int CONNECTION_ALREADY_CLOSED = 600;
|
private static final int CONNECTION_ALREADY_CLOSED = 600;
|
||||||
|
|
||||||
|
public ConnectionAlreadyClosedException(String msg) {
|
||||||
|
super(CONNECTION_ALREADY_CLOSED);
|
||||||
|
}
|
||||||
|
|
||||||
public ConnectionAlreadyClosedException() {
|
public ConnectionAlreadyClosedException() {
|
||||||
super(CONNECTION_ALREADY_CLOSED);
|
super(CONNECTION_ALREADY_CLOSED);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2020 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.common.remote.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* connection is busy exception.
|
||||||
|
*
|
||||||
|
* @author liuzunfei
|
||||||
|
* @version $Id: ConnectionBusyException.java, v 0.1 2020年11月30日 7:28 PM liuzunfei Exp $
|
||||||
|
*/
|
||||||
|
public class ConnectionBusyException extends RemoteException {
|
||||||
|
|
||||||
|
private static final int CONNECTION_BUSY = 601;
|
||||||
|
|
||||||
|
public ConnectionBusyException(String msg) {
|
||||||
|
super(CONNECTION_BUSY, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConnectionBusyException(Throwable throwable) {
|
||||||
|
super(CONNECTION_BUSY, throwable);
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,10 @@ public class RemoteException extends NacosRuntimeException {
|
|||||||
super(errorCode);
|
super(errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RemoteException(int errorCode, String msg) {
|
||||||
|
super(errorCode, msg);
|
||||||
|
}
|
||||||
|
|
||||||
public RemoteException(int errorCode, Throwable throwable) {
|
public RemoteException(int errorCode, Throwable throwable) {
|
||||||
super(errorCode, throwable);
|
super(errorCode, throwable);
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,12 @@
|
|||||||
package com.alibaba.nacos.config.server.remote;
|
package com.alibaba.nacos.config.server.remote;
|
||||||
|
|
||||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||||
import com.alibaba.nacos.common.utils.MapUtil;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@ -36,28 +37,27 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
public class ConfigChangeListenContext {
|
public class ConfigChangeListenContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* groupKey-> connnection set.
|
* groupKey-> connection set.
|
||||||
*/
|
*/
|
||||||
private final Map<String, Set<String>> groupKeyContext = new ConcurrentHashMap<String, Set<String>>(128);
|
private ConcurrentHashMap<String, HashSet<String>> groupKeyContext = new ConcurrentHashMap<String, HashSet<String>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* connectionId-> groupkey set.
|
* connectionId-> group key set.
|
||||||
*/
|
*/
|
||||||
private final Map<String, HashMap<String, String>> connectionIdContext = new ConcurrentHashMap<String, HashMap<String, String>>(128);
|
private ConcurrentHashMap<String, HashMap<String, String>> connectionIdContext = new ConcurrentHashMap<String, HashMap<String, String>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add listen .
|
* add listen.
|
||||||
*
|
*
|
||||||
* @param listenKey listenKey.
|
* @param groupKey groupKey.
|
||||||
* @param connectionId connectionId.
|
* @param connectionId connectionId.
|
||||||
*/
|
*/
|
||||||
public void addListen(String listenKey, String md5, String connectionId) {
|
public synchronized void addListen(String groupKey, String md5, String connectionId) {
|
||||||
|
|
||||||
// 1.add groupKeyContext
|
// 1.add groupKeyContext
|
||||||
Set<String> listenClients = groupKeyContext.get(listenKey);
|
Set<String> listenClients = groupKeyContext.get(groupKey);
|
||||||
if (listenClients == null) {
|
if (listenClients == null) {
|
||||||
groupKeyContext.putIfAbsent(listenKey, new HashSet<String>());
|
groupKeyContext.putIfAbsent(groupKey, new HashSet<String>());
|
||||||
listenClients = groupKeyContext.get(listenKey);
|
listenClients = groupKeyContext.get(groupKey);
|
||||||
}
|
}
|
||||||
listenClients.add(connectionId);
|
listenClients.add(connectionId);
|
||||||
|
|
||||||
@ -67,44 +67,70 @@ public class ConfigChangeListenContext {
|
|||||||
connectionIdContext.putIfAbsent(connectionId, new HashMap<String, String>(16));
|
connectionIdContext.putIfAbsent(connectionId, new HashMap<String, String>(16));
|
||||||
groupKeys = connectionIdContext.get(connectionId);
|
groupKeys = connectionIdContext.get(connectionId);
|
||||||
}
|
}
|
||||||
groupKeys.put(listenKey, md5);
|
groupKeys.put(groupKey, md5);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* remove listen context for connection id .
|
* remove listen context for connection id .
|
||||||
*
|
*
|
||||||
* @param listenKey listenKey.
|
* @param groupKey groupKey.
|
||||||
* @param connectionId connection id.
|
* @param connectionId connection id.
|
||||||
*/
|
*/
|
||||||
public void removeListen(String listenKey, String connectionId) {
|
public synchronized void removeListen(String groupKey, String connectionId) {
|
||||||
|
|
||||||
//1. remove groupKeyContext
|
//1. remove groupKeyContext
|
||||||
Set<String> connectionIds = groupKeyContext.get(listenKey);
|
Set<String> connectionIds = groupKeyContext.get(groupKey);
|
||||||
if (connectionIds != null) {
|
if (connectionIds != null) {
|
||||||
connectionIds.remove(connectionId);
|
connectionIds.remove(connectionId);
|
||||||
if (connectionIds.isEmpty()) {
|
if (connectionIds.isEmpty()) {
|
||||||
MapUtil.removeKey(groupKeyContext, listenKey, CollectionUtils::isEmpty);
|
groupKeyContext.remove(groupKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//2.remove connectionIdContext
|
//2.remove connectionIdContext
|
||||||
HashMap<String, String> groupKeys = connectionIdContext.get(connectionId);
|
HashMap<String, String> groupKeys = connectionIdContext.get(connectionId);
|
||||||
if (groupKeys != null) {
|
if (groupKeys != null) {
|
||||||
groupKeys.remove(listenKey);
|
groupKeys.remove(groupKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getListeners(String listenKey) {
|
/**
|
||||||
return groupKeyContext.get(listenKey);
|
* get listeners of the group key.
|
||||||
|
*
|
||||||
|
* @param groupKey groupKey.
|
||||||
|
* @return the copy of listeners, may be return null.
|
||||||
|
*/
|
||||||
|
public synchronized Set<String> getListeners(String groupKey) {
|
||||||
|
|
||||||
|
HashSet<String> strings = groupKeyContext.get(groupKey);
|
||||||
|
if (CollectionUtils.isNotEmpty(strings)) {
|
||||||
|
Set<String> listenConnections = new HashSet<String>();
|
||||||
|
safeCopy(strings, listenConnections);
|
||||||
|
return listenConnections;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* remove the context related to the connectionid.
|
* copy collections.
|
||||||
|
*
|
||||||
|
* @param src may be modified concurrently
|
||||||
|
* @param dest dest collection
|
||||||
|
*/
|
||||||
|
private void safeCopy(Collection src, Collection dest) {
|
||||||
|
Iterator iterator = src.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
dest.add(iterator.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove the context related to the connection id.
|
||||||
*
|
*
|
||||||
* @param connectionId connectionId.
|
* @param connectionId connectionId.
|
||||||
*/
|
*/
|
||||||
public void clearContextForConnectionId(final String connectionId) {
|
public synchronized void clearContextForConnectionId(final String connectionId) {
|
||||||
|
|
||||||
Map<String, String> listenKeys = getListenKeys(connectionId);
|
Map<String, String> listenKeys = getListenKeys(connectionId);
|
||||||
|
|
||||||
@ -115,32 +141,35 @@ public class ConfigChangeListenContext {
|
|||||||
if (CollectionUtils.isNotEmpty(connectionIds)) {
|
if (CollectionUtils.isNotEmpty(connectionIds)) {
|
||||||
connectionIds.remove(connectionId);
|
connectionIds.remove(connectionId);
|
||||||
} else {
|
} else {
|
||||||
MapUtil.removeKey(groupKeyContext, groupKey.getKey(), CollectionUtils::isEmpty);
|
groupKeyContext.remove(groupKey.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MapUtil.removeKey(connectionIdContext, connectionId, MapUtil::isEmpty);
|
|
||||||
|
connectionIdContext.remove(connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get listenkeys.
|
* get listen keys.
|
||||||
*
|
*
|
||||||
* @param connectionId connetionid.
|
* @param connectionId connection id.
|
||||||
* @return
|
* @return listen group keys of the connection id, key:group key,value:md5
|
||||||
*/
|
*/
|
||||||
public Map<String, String> getListenKeys(String connectionId) {
|
public synchronized Map<String, String> getListenKeys(String connectionId) {
|
||||||
return connectionIdContext.get(connectionId);
|
Map<String, String> copy = new HashMap<String, String>(connectionIdContext.get(connectionId));
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get listenkey.
|
* get md5.
|
||||||
*
|
*
|
||||||
* @param connectionId connetionid.
|
* @param connectionId connection id.
|
||||||
* @return
|
* @return md5 of the listen group key.
|
||||||
*/
|
*/
|
||||||
public String getListenKeyMd5(String connectionId, String groupKey) {
|
public String getListenKeyMd5(String connectionId, String groupKey) {
|
||||||
Map<String, String> groupKeyContexts = connectionIdContext.get(connectionId);
|
Map<String, String> groupKeyContexts = connectionIdContext.get(connectionId);
|
||||||
return groupKeyContexts == null ? null : groupKeyContexts.get(groupKey);
|
return groupKeyContexts == null ? null : groupKeyContexts.get(groupKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import com.alibaba.nacos.api.remote.response.AbstractPushCallBack;
|
|||||||
import com.alibaba.nacos.common.notify.Event;
|
import com.alibaba.nacos.common.notify.Event;
|
||||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||||
|
import com.alibaba.nacos.common.remote.exception.ConnectionAlreadyClosedException;
|
||||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||||
import com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;
|
import com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;
|
||||||
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
import com.alibaba.nacos.config.server.utils.ConfigExecutor;
|
||||||
@ -30,9 +31,9 @@ import com.alibaba.nacos.core.remote.Connection;
|
|||||||
import com.alibaba.nacos.core.remote.ConnectionManager;
|
import com.alibaba.nacos.core.remote.ConnectionManager;
|
||||||
import com.alibaba.nacos.core.remote.RpcPushService;
|
import com.alibaba.nacos.core.remote.RpcPushService;
|
||||||
import com.alibaba.nacos.core.utils.Loggers;
|
import com.alibaba.nacos.core.utils.Loggers;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -46,53 +47,50 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@Component(value = "rpcConfigChangeNotifier")
|
@Component(value = "rpcConfigChangeNotifier")
|
||||||
public class RpcConfigChangeNotifier extends Subscriber<LocalDataChangeEvent> {
|
public class RpcConfigChangeNotifier extends Subscriber<LocalDataChangeEvent> {
|
||||||
|
|
||||||
final ConfigChangeListenContext configChangeListenContext;
|
public RpcConfigChangeNotifier() {
|
||||||
|
|
||||||
private final RpcPushService rpcPushService;
|
|
||||||
|
|
||||||
private final ConnectionManager connectionManager;
|
|
||||||
|
|
||||||
public RpcConfigChangeNotifier(ConfigChangeListenContext configChangeListenContext, RpcPushService rpcPushService,
|
|
||||||
ConnectionManager connectionManager) {
|
|
||||||
NotifyCenter.registerSubscriber(this);
|
NotifyCenter.registerSubscriber(this);
|
||||||
this.configChangeListenContext = configChangeListenContext;
|
|
||||||
this.rpcPushService = rpcPushService;
|
|
||||||
this.connectionManager = connectionManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ConfigChangeListenContext configChangeListenContext;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RpcPushService rpcPushService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConnectionManager connectionManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* adaptor to config module ,when server side config change ,invoke this method.
|
* adaptor to config module ,when server side config change ,invoke this method.
|
||||||
*
|
*
|
||||||
* @param groupKey groupKey
|
* @param groupKey groupKey
|
||||||
* @param notifyRequest notifyRequest
|
* @param notifyRequet notifyRequet
|
||||||
*/
|
*/
|
||||||
public void configDataChanged(String groupKey, final ConfigChangeNotifyRequest notifyRequest) {
|
public void configDataChanged(String groupKey, final ConfigChangeNotifyRequest notifyRequet) {
|
||||||
|
|
||||||
Set<String> listeners = configChangeListenContext.getListeners(groupKey);
|
Set<String> listeners = configChangeListenContext.getListeners(groupKey);
|
||||||
if (listeners == null || listeners.isEmpty()) {
|
if (CollectionUtils.isEmpty(listeners)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Set<String> clients = new HashSet<>(listeners);
|
|
||||||
int notifyCount = 0;
|
int notifyCount = 0;
|
||||||
if (!CollectionUtils.isEmpty(clients)) {
|
for (final String client : listeners) {
|
||||||
for (final String client : clients) {
|
Connection connection = connectionManager.getConnection(client);
|
||||||
Connection connection = connectionManager.getConnection(client);
|
if (connection == null) {
|
||||||
if (connection == null) {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notifyRequet.isBeta()) {
|
||||||
|
List<String> betaIps = notifyRequet.getBetaIps();
|
||||||
|
if (betaIps != null && !betaIps.contains(connection.getMetaInfo().getClientIp())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notifyRequest.isBeta()) {
|
|
||||||
List<String> betaIps = notifyRequest.getBetaIps();
|
|
||||||
if (betaIps != null && !betaIps.contains(connection.getMetaInfo().getClientIp())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RpcPushTask rpcPushRetryTask = new RpcPushTask(notifyRequest, 50, client,
|
|
||||||
connection.getMetaInfo().getClientIp(), connection.getMetaInfo().getConnectionId());
|
|
||||||
push(rpcPushRetryTask);
|
|
||||||
notifyCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RpcPushTask rpcPushRetryTask = new RpcPushTask(notifyRequet, 50, client,
|
||||||
|
connection.getMetaInfo().getClientIp(), connection.getMetaInfo().getConnectionId());
|
||||||
|
push(rpcPushRetryTask);
|
||||||
|
notifyCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Loggers.REMOTE_PUSH.info("push [{}] clients ,groupKey=[{}]", notifyCount, groupKey);
|
Loggers.REMOTE_PUSH.info("push [{}] clients ,groupKey=[{}]", notifyCount, groupKey);
|
||||||
@ -104,10 +102,10 @@ public class RpcConfigChangeNotifier extends Subscriber<LocalDataChangeEvent> {
|
|||||||
boolean isBeta = event.isBeta;
|
boolean isBeta = event.isBeta;
|
||||||
List<String> betaIps = event.betaIps;
|
List<String> betaIps = event.betaIps;
|
||||||
String[] strings = GroupKey.parseKey(groupKey);
|
String[] strings = GroupKey.parseKey(groupKey);
|
||||||
String dataId = strings[0];
|
String dataid = strings[0];
|
||||||
String group = strings[1];
|
String group = strings[1];
|
||||||
String tenant = strings.length > 2 ? strings[2] : "";
|
String tenant = strings.length > 2 ? strings[2] : "";
|
||||||
ConfigChangeNotifyRequest notifyRequest = ConfigChangeNotifyRequest.build(dataId, group, tenant);
|
ConfigChangeNotifyRequest notifyRequest = ConfigChangeNotifyRequest.build(dataid, group, tenant);
|
||||||
notifyRequest.setBeta(isBeta);
|
notifyRequest.setBeta(isBeta);
|
||||||
notifyRequest.setBetaIps(betaIps);
|
notifyRequest.setBetaIps(betaIps);
|
||||||
if (PropertyUtil.isPushContent()) {
|
if (PropertyUtil.isPushContent()) {
|
||||||
@ -128,7 +126,7 @@ public class RpcConfigChangeNotifier extends Subscriber<LocalDataChangeEvent> {
|
|||||||
|
|
||||||
class RpcPushTask implements Runnable {
|
class RpcPushTask implements Runnable {
|
||||||
|
|
||||||
ConfigChangeNotifyRequest notifyRequest;
|
ConfigChangeNotifyRequest notifyRequet;
|
||||||
|
|
||||||
int maxRetryTimes = -1;
|
int maxRetryTimes = -1;
|
||||||
|
|
||||||
@ -144,9 +142,9 @@ public class RpcConfigChangeNotifier extends Subscriber<LocalDataChangeEvent> {
|
|||||||
this(notifyRequet, -1, clientId, clientIp, appName);
|
this(notifyRequet, -1, clientId, clientIp, appName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RpcPushTask(ConfigChangeNotifyRequest notifyRequest, int maxRetryTimes, String clientId, String clientIp,
|
public RpcPushTask(ConfigChangeNotifyRequest notifyRequet, int maxRetryTimes, String clientId, String clientIp,
|
||||||
String appName) {
|
String appName) {
|
||||||
this.notifyRequest = notifyRequest;
|
this.notifyRequet = notifyRequet;
|
||||||
this.maxRetryTimes = maxRetryTimes;
|
this.maxRetryTimes = maxRetryTimes;
|
||||||
this.clientId = clientId;
|
this.clientId = clientId;
|
||||||
this.clientIp = clientIp;
|
this.clientIp = clientIp;
|
||||||
@ -159,7 +157,7 @@ public class RpcConfigChangeNotifier extends Subscriber<LocalDataChangeEvent> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
rpcPushService.pushWithCallback(clientId, notifyRequest, new AbstractPushCallBack(3000L) {
|
rpcPushService.pushWithCallback(clientId, notifyRequet, new AbstractPushCallBack(3000L) {
|
||||||
int retryTimes = tryTimes;
|
int retryTimes = tryTimes;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -169,6 +167,9 @@ public class RpcConfigChangeNotifier extends Subscriber<LocalDataChangeEvent> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFail(Throwable e) {
|
public void onFail(Throwable e) {
|
||||||
|
if (e instanceof ConnectionAlreadyClosedException) {
|
||||||
|
Loggers.CORE.warn(e.getMessage());
|
||||||
|
}
|
||||||
push(RpcPushTask.this);
|
push(RpcPushTask.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +180,7 @@ public class RpcConfigChangeNotifier extends Subscriber<LocalDataChangeEvent> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void push(RpcPushTask retryTask) {
|
private void push(RpcPushTask retryTask) {
|
||||||
ConfigChangeNotifyRequest notifyRequet = retryTask.notifyRequest;
|
ConfigChangeNotifyRequest notifyRequet = retryTask.notifyRequet;
|
||||||
if (retryTask.isOverTimes()) {
|
if (retryTask.isOverTimes()) {
|
||||||
Loggers.CORE
|
Loggers.CORE
|
||||||
.warn("push callback retry fail over times .dataId={},group={},tenant={},clientId={},will unregister client.",
|
.warn("push callback retry fail over times .dataId={},group={},tenant={},clientId={},will unregister client.",
|
||||||
|
@ -399,7 +399,7 @@ public class LongPollingService {
|
|||||||
try {
|
try {
|
||||||
getRetainIps().put(ClientLongPolling.this.ip, System.currentTimeMillis());
|
getRetainIps().put(ClientLongPolling.this.ip, System.currentTimeMillis());
|
||||||
|
|
||||||
// Delete subsciber's relations.
|
// Delete subscriber's relations.
|
||||||
allSubs.remove(ClientLongPolling.this);
|
allSubs.remove(ClientLongPolling.this);
|
||||||
|
|
||||||
if (isFixedPolling()) {
|
if (isFixedPolling()) {
|
||||||
|
@ -35,6 +35,7 @@ import com.alibaba.nacos.core.cluster.remote.ClusterRpcClientProxy;
|
|||||||
import com.alibaba.nacos.core.remote.Connection;
|
import com.alibaba.nacos.core.remote.Connection;
|
||||||
import com.alibaba.nacos.core.remote.ConnectionManager;
|
import com.alibaba.nacos.core.remote.ConnectionManager;
|
||||||
import com.alibaba.nacos.core.remote.core.ServerLoaderInfoRequestHandler;
|
import com.alibaba.nacos.core.remote.core.ServerLoaderInfoRequestHandler;
|
||||||
|
import com.alibaba.nacos.core.remote.core.ServerReloaderRequestHandler;
|
||||||
import com.alibaba.nacos.core.utils.RemoteUtils;
|
import com.alibaba.nacos.core.utils.RemoteUtils;
|
||||||
import org.apache.commons.lang3.math.NumberUtils;
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -77,6 +78,9 @@ public class ServerLoaderController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ClusterRpcClientProxy clusterRpcClientProxy;
|
private ClusterRpcClientProxy clusterRpcClientProxy;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ServerReloaderRequestHandler serverReloaderRequestHandler;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ServerLoaderInfoRequestHandler serverLoaderInfoRequestHandler;
|
private ServerLoaderInfoRequestHandler serverLoaderInfoRequestHandler;
|
||||||
|
|
||||||
@ -184,15 +188,9 @@ public class ServerLoaderController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ServerLoaderMetris> responseList = new LinkedList<ServerLoaderMetris>();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ServerLoaderInfoResponse handle = serverLoaderInfoRequestHandler
|
serverReloaderRequestHandler.handle(serverLoaderInfoRequest, new RequestMeta());
|
||||||
.handle(new ServerLoaderInfoRequest(), new RequestMeta());
|
|
||||||
ServerLoaderMetris metris = new ServerLoaderMetris();
|
|
||||||
metris.setAddress(serverMemberManager.getSelf().getAddress());
|
|
||||||
metris.setMetric(handle.getLoaderMetrics());
|
|
||||||
responseList.add(metris);
|
|
||||||
} catch (NacosException e) {
|
} catch (NacosException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,11 @@ public abstract class Connection implements Requester {
|
|||||||
return metaInfo;
|
return metaInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBusy() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return ToStringBuilder.reflectionToString(this);
|
return ToStringBuilder.reflectionToString(this);
|
||||||
|
@ -80,14 +80,17 @@ public class ConnectionManager {
|
|||||||
* @param connectionId connectionId
|
* @param connectionId connectionId
|
||||||
* @param connection connection
|
* @param connection connection
|
||||||
*/
|
*/
|
||||||
public void register(String connectionId, Connection connection) {
|
public synchronized void register(String connectionId, Connection connection) {
|
||||||
Connection connectionInner = connetions.put(connectionId, connection);
|
if (connection.isConnected()) {
|
||||||
if (connectionInner == null) {
|
Connection connectionInner = connetions.put(connectionId, connection);
|
||||||
clientConnectionEventListenerRegistry.notifyClientConnected(connection);
|
if (connectionInner == null) {
|
||||||
Loggers.REMOTE
|
clientConnectionEventListenerRegistry.notifyClientConnected(connection);
|
||||||
.info("new connection registered successfully, connectionid = {},connection={} ", connectionId,
|
Loggers.REMOTE
|
||||||
connection);
|
.info("new connection registered successfully, connectionid = {},connection={} ", connectionId,
|
||||||
|
connection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,7 +98,7 @@ public class ConnectionManager {
|
|||||||
*
|
*
|
||||||
* @param connectionId connectionId.
|
* @param connectionId connectionId.
|
||||||
*/
|
*/
|
||||||
public void unregister(String connectionId) {
|
public synchronized void unregister(String connectionId) {
|
||||||
Connection remove = this.connetions.remove(connectionId);
|
Connection remove = this.connetions.remove(connectionId);
|
||||||
if (remove != null) {
|
if (remove != null) {
|
||||||
remove.close();
|
remove.close();
|
||||||
@ -165,9 +168,6 @@ public class ConnectionManager {
|
|||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Loggers.REMOTE.info("rpc ack size :{}", RpcAckCallbackSynchronizer.CALLBACK_CONTEXT.size());
|
|
||||||
;
|
|
||||||
|
|
||||||
MetricsMonitor.getLongConnectionMonitor().set(connetions.size());
|
MetricsMonitor.getLongConnectionMonitor().set(connetions.size());
|
||||||
|
|
||||||
long currentStamp = System.currentTimeMillis();
|
long currentStamp = System.currentTimeMillis();
|
||||||
@ -184,18 +184,18 @@ public class ConnectionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConnectResetRequest connectResetRequest = new ConnectResetRequest();
|
||||||
|
if (StringUtils.isNotBlank(redirectAddress) && redirectAddress.contains(Constants.COLON)) {
|
||||||
|
String[] split = redirectAddress.split(Constants.COLON);
|
||||||
|
connectResetRequest.setServerIp(split[0]);
|
||||||
|
connectResetRequest.setServerPort(split[1]);
|
||||||
|
}
|
||||||
|
|
||||||
for (String expeledClientId : expelClient) {
|
for (String expeledClientId : expelClient) {
|
||||||
try {
|
try {
|
||||||
Connection connection = getConnection(expeledClientId);
|
Connection connection = getConnection(expeledClientId);
|
||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
|
connection.asyncRequest(connectResetRequest, buildMeta(), null);
|
||||||
ConnectResetRequest connectResetRequest = new ConnectResetRequest();
|
|
||||||
if (StringUtils.isNotBlank(redirectAddress) && redirectAddress.contains(":")) {
|
|
||||||
String[] split = redirectAddress.split(Constants.COLON);
|
|
||||||
connectResetRequest.setServerIp(split[0]);
|
|
||||||
connectResetRequest.setServerPort(split[1]);
|
|
||||||
}
|
|
||||||
connection.request(connectResetRequest, buildMeta());
|
|
||||||
Loggers.REMOTE
|
Loggers.REMOTE
|
||||||
.info("expel connection ,send switch server response connectionid = {},connectResetRequest={} ",
|
.info("expel connection ,send switch server response connectionid = {},connectResetRequest={} ",
|
||||||
expeledClientId, connectResetRequest);
|
expeledClientId, connectResetRequest);
|
||||||
@ -214,7 +214,7 @@ public class ConnectionManager {
|
|||||||
redirectAddress = null;
|
redirectAddress = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
Loggers.REMOTE.error("error occurs when heathy check... ", e);
|
Loggers.REMOTE.error("error occurs when heathy check... ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,9 +52,7 @@ public class ServerReloaderRequestHandler extends RequestHandler<ServerReloadReq
|
|||||||
if (sdkCount <= reloadCount) {
|
if (sdkCount <= reloadCount) {
|
||||||
response.setMessage("ignore");
|
response.setMessage("ignore");
|
||||||
} else {
|
} else {
|
||||||
if (reloadCount * (1 + RemoteUtils.LOADER_FACTOR) < sdkCount) {
|
reloadCount = (int) Math.max(reloadCount, sdkCount * (1 - RemoteUtils.LOADER_FACTOR));
|
||||||
reloadCount = (int) (sdkCount * (1 - RemoteUtils.LOADER_FACTOR));
|
|
||||||
}
|
|
||||||
connectionManager.loadCount(reloadCount, null);
|
connectionManager.loadCount(reloadCount, null);
|
||||||
response.setMessage("ok");
|
response.setMessage("ok");
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package com.alibaba.nacos.core.remote.grpc;
|
package com.alibaba.nacos.core.remote.grpc;
|
||||||
|
|
||||||
import com.alibaba.nacos.api.grpc.auto.Payload;
|
import com.alibaba.nacos.api.grpc.auto.Payload;
|
||||||
|
import com.alibaba.nacos.common.executor.ExecutorFactory;
|
||||||
import com.alibaba.nacos.common.remote.ConnectionType;
|
import com.alibaba.nacos.common.remote.ConnectionType;
|
||||||
import com.alibaba.nacos.common.utils.ReflectUtils;
|
import com.alibaba.nacos.common.utils.ReflectUtils;
|
||||||
import com.alibaba.nacos.common.utils.UuidUtils;
|
import com.alibaba.nacos.common.utils.UuidUtils;
|
||||||
@ -24,6 +25,7 @@ import com.alibaba.nacos.core.remote.BaseRpcServer;
|
|||||||
import com.alibaba.nacos.core.remote.ConnectionManager;
|
import com.alibaba.nacos.core.remote.ConnectionManager;
|
||||||
import com.alibaba.nacos.core.remote.RequestHandlerRegistry;
|
import com.alibaba.nacos.core.remote.RequestHandlerRegistry;
|
||||||
import com.alibaba.nacos.core.utils.Loggers;
|
import com.alibaba.nacos.core.utils.Loggers;
|
||||||
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
import io.grpc.Attributes;
|
import io.grpc.Attributes;
|
||||||
import io.grpc.Context;
|
import io.grpc.Context;
|
||||||
import io.grpc.Contexts;
|
import io.grpc.Contexts;
|
||||||
@ -31,6 +33,7 @@ import io.grpc.Grpc;
|
|||||||
import io.grpc.Metadata;
|
import io.grpc.Metadata;
|
||||||
import io.grpc.MethodDescriptor;
|
import io.grpc.MethodDescriptor;
|
||||||
import io.grpc.Server;
|
import io.grpc.Server;
|
||||||
|
import io.grpc.ServerBuilder;
|
||||||
import io.grpc.ServerCall;
|
import io.grpc.ServerCall;
|
||||||
import io.grpc.ServerCallHandler;
|
import io.grpc.ServerCallHandler;
|
||||||
import io.grpc.ServerInterceptor;
|
import io.grpc.ServerInterceptor;
|
||||||
@ -38,7 +41,6 @@ import io.grpc.ServerInterceptors;
|
|||||||
import io.grpc.ServerServiceDefinition;
|
import io.grpc.ServerServiceDefinition;
|
||||||
import io.grpc.ServerTransportFilter;
|
import io.grpc.ServerTransportFilter;
|
||||||
import io.grpc.internal.ServerStream;
|
import io.grpc.internal.ServerStream;
|
||||||
import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
|
|
||||||
import io.grpc.netty.shaded.io.netty.channel.Channel;
|
import io.grpc.netty.shaded.io.netty.channel.Channel;
|
||||||
import io.grpc.protobuf.ProtoUtils;
|
import io.grpc.protobuf.ProtoUtils;
|
||||||
import io.grpc.stub.ServerCalls;
|
import io.grpc.stub.ServerCalls;
|
||||||
@ -46,6 +48,7 @@ import io.grpc.util.MutableHandlerRegistry;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grpc implementation as a rpc server.
|
* Grpc implementation as a rpc server.
|
||||||
@ -55,6 +58,8 @@ import java.net.InetSocketAddress;
|
|||||||
*/
|
*/
|
||||||
public abstract class BaseGrpcServer extends BaseRpcServer {
|
public abstract class BaseGrpcServer extends BaseRpcServer {
|
||||||
|
|
||||||
|
private static Executor grpcExecutor;
|
||||||
|
|
||||||
private Server server;
|
private Server server;
|
||||||
|
|
||||||
private static final String REQUEST_BI_STREAM_SERVICE_NAME = "BiRequestStream";
|
private static final String REQUEST_BI_STREAM_SERVICE_NAME = "BiRequestStream";
|
||||||
@ -106,8 +111,12 @@ public abstract class BaseGrpcServer extends BaseRpcServer {
|
|||||||
|
|
||||||
addServices(handlerRegistry, serverInterceptor);
|
addServices(handlerRegistry, serverInterceptor);
|
||||||
|
|
||||||
server = NettyServerBuilder.forPort(getServicePort()).fallbackHandlerRegistry(handlerRegistry)
|
grpcExecutor = ExecutorFactory.Managed
|
||||||
.addTransportFilter(new ServerTransportFilter() {
|
.newCustomerThreadExecutor("core", Runtime.getRuntime().availableProcessors(),
|
||||||
|
Runtime.getRuntime().availableProcessors() * 4, 10000,
|
||||||
|
new ThreadFactoryBuilder().setDaemon(true).setNameFormat("nacos-grpc-executor-%d").build());
|
||||||
|
server = ServerBuilder.forPort(getServicePort()).executor(grpcExecutor)
|
||||||
|
.fallbackHandlerRegistry(handlerRegistry).addTransportFilter(new ServerTransportFilter() {
|
||||||
@Override
|
@Override
|
||||||
public Attributes transportReady(Attributes transportAttrs) {
|
public Attributes transportReady(Attributes transportAttrs) {
|
||||||
InetSocketAddress remoteAddress = (InetSocketAddress) transportAttrs
|
InetSocketAddress remoteAddress = (InetSocketAddress) transportAttrs
|
||||||
@ -120,17 +129,17 @@ public abstract class BaseGrpcServer extends BaseRpcServer {
|
|||||||
Attributes attrWraper = transportAttrs.toBuilder()
|
Attributes attrWraper = transportAttrs.toBuilder()
|
||||||
.set(TRANS_KEY_CONN_ID, UuidUtils.generateUuid()).set(TRANS_KEY_CLIENT_IP, remoteIp)
|
.set(TRANS_KEY_CONN_ID, UuidUtils.generateUuid()).set(TRANS_KEY_CLIENT_IP, remoteIp)
|
||||||
.set(TRANS_KEY_CLIENT_PORT, remotePort).set(TRANS_KEY_LOCAL_PORT, localPort).build();
|
.set(TRANS_KEY_CLIENT_PORT, remotePort).set(TRANS_KEY_LOCAL_PORT, localPort).build();
|
||||||
String connectionid = attrWraper.get(TRANS_KEY_CONN_ID);
|
String connectionId = attrWraper.get(TRANS_KEY_CONN_ID);
|
||||||
Loggers.REMOTE.info(" connection transportReady,connectionid = {} ", connectionid);
|
Loggers.REMOTE.info(" connection transportReady,connectionId = {} ", connectionId);
|
||||||
return attrWraper;
|
return attrWraper;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void transportTerminated(Attributes transportAttrs) {
|
public void transportTerminated(Attributes transportAttrs) {
|
||||||
String connectionid = transportAttrs.get(TRANS_KEY_CONN_ID);
|
String connectionId = transportAttrs.get(TRANS_KEY_CONN_ID);
|
||||||
Loggers.REMOTE.info(" connection transportTerminated,connectionid = {} ", connectionid);
|
Loggers.REMOTE.info(" connection transportTerminated,connectionId = {} ", connectionId);
|
||||||
connectionManager.unregister(connectionid);
|
connectionManager.unregister(connectionId);
|
||||||
}
|
}
|
||||||
}).build();
|
}).build();
|
||||||
server.start();
|
server.start();
|
||||||
|
@ -30,8 +30,8 @@ import com.alibaba.nacos.core.remote.Connection;
|
|||||||
import com.alibaba.nacos.core.remote.ConnectionManager;
|
import com.alibaba.nacos.core.remote.ConnectionManager;
|
||||||
import com.alibaba.nacos.core.remote.ConnectionMetaInfo;
|
import com.alibaba.nacos.core.remote.ConnectionMetaInfo;
|
||||||
import com.alibaba.nacos.core.remote.RpcAckCallbackSynchronizer;
|
import com.alibaba.nacos.core.remote.RpcAckCallbackSynchronizer;
|
||||||
import com.alibaba.nacos.core.utils.Loggers;
|
|
||||||
import com.alibaba.nacos.sys.utils.ApplicationUtils;
|
import com.alibaba.nacos.sys.utils.ApplicationUtils;
|
||||||
|
import io.grpc.stub.ServerCallStreamObserver;
|
||||||
import io.grpc.stub.StreamObserver;
|
import io.grpc.stub.StreamObserver;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -90,10 +90,8 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if connnection is already terminated,not register it.
|
//if connection is already terminated,not register it.
|
||||||
if (connection.isConnected()) {
|
connectionManager.register(connectionId, connection);
|
||||||
connectionManager.register(connectionId, connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (plainRequest.getBody() instanceof Response) {
|
} else if (plainRequest.getBody() instanceof Response) {
|
||||||
Response response = (Response) plainRequest.getBody();
|
Response response = (Response) plainRequest.getBody();
|
||||||
@ -104,8 +102,16 @@ public class GrpcBiStreamRequestAcceptor extends BiRequestStreamGrpc.BiRequestSt
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable t) {
|
public void onError(Throwable t) {
|
||||||
Loggers.REMOTE.error("grpc streamObserver error .", t);
|
if (responseObserver instanceof ServerCallStreamObserver) {
|
||||||
responseObserver.onCompleted();
|
ServerCallStreamObserver serverCallStreamObserver = ((ServerCallStreamObserver) responseObserver);
|
||||||
|
if (serverCallStreamObserver.isCancelled()) {
|
||||||
|
//client close the stream.
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
serverCallStreamObserver.onCompleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,6 +27,7 @@ import com.alibaba.nacos.api.remote.response.Response;
|
|||||||
import com.alibaba.nacos.api.utils.NetUtils;
|
import com.alibaba.nacos.api.utils.NetUtils;
|
||||||
import com.alibaba.nacos.common.remote.client.grpc.GrpcUtils;
|
import com.alibaba.nacos.common.remote.client.grpc.GrpcUtils;
|
||||||
import com.alibaba.nacos.common.remote.exception.ConnectionAlreadyClosedException;
|
import com.alibaba.nacos.common.remote.exception.ConnectionAlreadyClosedException;
|
||||||
|
import com.alibaba.nacos.common.remote.exception.ConnectionBusyException;
|
||||||
import com.alibaba.nacos.common.utils.VersionUtils;
|
import com.alibaba.nacos.common.utils.VersionUtils;
|
||||||
import com.alibaba.nacos.core.remote.Connection;
|
import com.alibaba.nacos.core.remote.Connection;
|
||||||
import com.alibaba.nacos.core.remote.ConnectionMetaInfo;
|
import com.alibaba.nacos.core.remote.ConnectionMetaInfo;
|
||||||
@ -34,6 +35,7 @@ import com.alibaba.nacos.core.remote.RpcAckCallbackSynchronizer;
|
|||||||
import com.alibaba.nacos.core.utils.Loggers;
|
import com.alibaba.nacos.core.utils.Loggers;
|
||||||
import io.grpc.StatusRuntimeException;
|
import io.grpc.StatusRuntimeException;
|
||||||
import io.grpc.netty.shaded.io.netty.channel.Channel;
|
import io.grpc.netty.shaded.io.netty.channel.Channel;
|
||||||
|
import io.grpc.stub.ServerCallStreamObserver;
|
||||||
import io.grpc.stub.StreamObserver;
|
import io.grpc.stub.StreamObserver;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -58,7 +60,13 @@ public class GrpcConnection extends Connection {
|
|||||||
|
|
||||||
private void sendRequestNoAck(Request request, RequestMeta meta) throws NacosException {
|
private void sendRequestNoAck(Request request, RequestMeta meta) throws NacosException {
|
||||||
try {
|
try {
|
||||||
streamObserver.onNext(GrpcUtils.convert(request, wrapMeta(meta)));
|
//StreamObserver#onNext() is not thread-safe,synchronized is required to avoid direct memory leak.
|
||||||
|
synchronized (streamObserver) {
|
||||||
|
if (this.isBusy()) {
|
||||||
|
throw new ConnectionBusyException(this.getMetaInfo().getConnectionId() + ",connection busy.");
|
||||||
|
}
|
||||||
|
streamObserver.onNext(GrpcUtils.convert(request, wrapMeta(meta)));
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (e instanceof StatusRuntimeException) {
|
if (e instanceof StatusRuntimeException) {
|
||||||
throw new ConnectionAlreadyClosedException(e);
|
throw new ConnectionAlreadyClosedException(e);
|
||||||
@ -89,14 +97,15 @@ public class GrpcConnection extends Connection {
|
|||||||
String requestId = String.valueOf(PushAckIdGenerator.getNextId());
|
String requestId = String.valueOf(PushAckIdGenerator.getNextId());
|
||||||
request.setRequestId(requestId);
|
request.setRequestId(requestId);
|
||||||
sendRequestNoAck(request, meta);
|
sendRequestNoAck(request, meta);
|
||||||
|
|
||||||
DefaultRequestFuture defaultPushFuture = new DefaultRequestFuture(getMetaInfo().getConnectionId(), requestId,
|
DefaultRequestFuture defaultPushFuture = new DefaultRequestFuture(getMetaInfo().getConnectionId(), requestId,
|
||||||
callBack,
|
callBack, new DefaultRequestFuture.TimeoutInnerTrigger() {
|
||||||
new DefaultRequestFuture.TimeoutInnerTrigger() {
|
@Override
|
||||||
@Override
|
public void triggerOnTimeout() {
|
||||||
public void triggerOnTimeout() {
|
RpcAckCallbackSynchronizer.clearFuture(getMetaInfo().getConnectionId(), requestId);
|
||||||
RpcAckCallbackSynchronizer.clearFuture(getMetaInfo().getConnectionId(), requestId);
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
RpcAckCallbackSynchronizer.syncCallback(getMetaInfo().getConnectionId(), requestId, defaultPushFuture);
|
RpcAckCallbackSynchronizer.syncCallback(getMetaInfo().getConnectionId(), requestId, defaultPushFuture);
|
||||||
return defaultPushFuture;
|
return defaultPushFuture;
|
||||||
}
|
}
|
||||||
@ -137,14 +146,35 @@ public class GrpcConnection extends Connection {
|
|||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
try {
|
try {
|
||||||
streamObserver.onCompleted();
|
if (isConnected()) {
|
||||||
|
closeBiStream();
|
||||||
|
channel.close();
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Loggers.REMOTE.debug(String.format("[%s] connection close exception : %s", "grpc", e.getMessage()));
|
Loggers.REMOTE.debug(String.format("[%s] connection close exception : %s", "grpc", e.getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void closeBiStream() {
|
||||||
|
if (streamObserver instanceof ServerCallStreamObserver) {
|
||||||
|
ServerCallStreamObserver serverCallStreamObserver = ((ServerCallStreamObserver) streamObserver);
|
||||||
|
if (!serverCallStreamObserver.isCancelled()) {
|
||||||
|
serverCallStreamObserver.onCompleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBusy() {
|
||||||
|
if (streamObserver instanceof ServerCallStreamObserver) {
|
||||||
|
return !((ServerCallStreamObserver) streamObserver).isReady();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isConnected() {
|
public boolean isConnected() {
|
||||||
return channel.isActive();
|
return channel != null && channel.isOpen() && channel.isActive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
pom.xml
19
pom.xml
@ -128,6 +128,7 @@
|
|||||||
<!-- dependency version -->
|
<!-- dependency version -->
|
||||||
<spring-boot-dependencies.version>2.1.17.RELEASE</spring-boot-dependencies.version>
|
<spring-boot-dependencies.version>2.1.17.RELEASE</spring-boot-dependencies.version>
|
||||||
<servlet-api.version>3.0</servlet-api.version>
|
<servlet-api.version>3.0</servlet-api.version>
|
||||||
|
<commons-lang.version>2.6</commons-lang.version>
|
||||||
<commons-lang3.version>3.4</commons-lang3.version>
|
<commons-lang3.version>3.4</commons-lang3.version>
|
||||||
<commons-io.version>2.2</commons-io.version>
|
<commons-io.version>2.2</commons-io.version>
|
||||||
<commons-collections.version>3.2.2</commons-collections.version>
|
<commons-collections.version>3.2.2</commons-collections.version>
|
||||||
@ -140,6 +141,7 @@
|
|||||||
<httpcore.version>4.4.1</httpcore.version>
|
<httpcore.version>4.4.1</httpcore.version>
|
||||||
<httpclient.version>4.5</httpclient.version>
|
<httpclient.version>4.5</httpclient.version>
|
||||||
<httpasyncclient.version>4.1.3</httpasyncclient.version>
|
<httpasyncclient.version>4.1.3</httpasyncclient.version>
|
||||||
|
<async-http-client.version>1.7.17</async-http-client.version>
|
||||||
<mysql-connector-java.version>8.0.16</mysql-connector-java.version>
|
<mysql-connector-java.version>8.0.16</mysql-connector-java.version>
|
||||||
<derby.version>10.14.2.0</derby.version>
|
<derby.version>10.14.2.0</derby.version>
|
||||||
<cglib-nodep.version>2.1</cglib-nodep.version>
|
<cglib-nodep.version>2.1</cglib-nodep.version>
|
||||||
@ -303,7 +305,7 @@
|
|||||||
<encoding>UTF-8</encoding>
|
<encoding>UTF-8</encoding>
|
||||||
<consoleOutput>true</consoleOutput>
|
<consoleOutput>true</consoleOutput>
|
||||||
<failsOnError>true</failsOnError>
|
<failsOnError>true</failsOnError>
|
||||||
<excludes>**/istio/model/**,**/nacos/test/**,**/api/grpc/auto/**,**/consistency/entity/**</excludes>
|
<excludes>**/istio/model/**,**/nacos/test/**,**/api/grpc/auto/**</excludes>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
@ -338,7 +340,6 @@
|
|||||||
<exclude>**/consistency/entity/**</exclude>
|
<exclude>**/consistency/entity/**</exclude>
|
||||||
<exclude>**/*.txt</exclude>
|
<exclude>**/*.txt</exclude>
|
||||||
<exclude>**/*.factories</exclude>
|
<exclude>**/*.factories</exclude>
|
||||||
<exclude>/console-ui/**</exclude>
|
|
||||||
</excludes>
|
</excludes>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
@ -734,6 +735,12 @@
|
|||||||
<version>${hessian.version}</version>
|
<version>${hessian.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<version>${commons-lang.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Apache commons -->
|
<!-- Apache commons -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
@ -771,6 +778,7 @@
|
|||||||
<version>${commons-cli.version}</version>
|
<version>${commons-cli.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- Logging libs -->
|
<!-- Logging libs -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
@ -833,6 +841,12 @@
|
|||||||
<version>${httpasyncclient.version}</version>
|
<version>${httpasyncclient.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ning</groupId>
|
||||||
|
<artifactId>async-http-client</artifactId>
|
||||||
|
<version>${async-http-client.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- JDBC libs -->
|
<!-- JDBC libs -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
@ -967,7 +981,6 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- gRPC dependency start -->
|
<!-- gRPC dependency start -->
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.grpc</groupId>
|
<groupId>io.grpc</groupId>
|
||||||
<artifactId>grpc-netty-shaded</artifactId>
|
<artifactId>grpc-netty-shaded</artifactId>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
* Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.alibaba.nacos.client;
|
package com.alibaba.nacos.test.config;
|
||||||
|
|
||||||
import com.alibaba.nacos.api.NacosFactory;
|
import com.alibaba.nacos.api.NacosFactory;
|
||||||
import com.alibaba.nacos.api.PropertyKeyConst;
|
import com.alibaba.nacos.api.PropertyKeyConst;
|
||||||
@ -56,14 +56,14 @@ public class ConfigTest {
|
|||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
properties.setProperty(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848");
|
properties.setProperty(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848");
|
||||||
|
|
||||||
//properties.setProperty(PropertyKeyConst.SERVER_ADDR, "11.160.144.149:8848");
|
properties.setProperty(PropertyKeyConst.SERVER_ADDR, "11.160.144.149:8848");
|
||||||
//properties.setProperty(PropertyKeyConst.SERVER_ADDR, "11.160.67.159:8849");
|
//properties.setProperty(PropertyKeyConst.SERVER_ADDR, "11.160.67.159:7001");
|
||||||
|
|
||||||
//properties.setProperty(PropertyKeyConst.SERVER_ADDR, "11.160.144.149:8848,11.160.144.148:8848,127.0.0.1:8848");
|
//properties.setProperty(PropertyKeyConst.SERVER_ADDR, "11.160.144.149:8848,11.160.144.148:8848,127.0.0.1:8848");
|
||||||
//"11.239.114.187:8848,,11.239.113.204:8848,11.239.112.161:8848");
|
//"11.239.114.187:8848,,11.239.113.204:8848,11.239.112.161:8848");
|
||||||
//"11.239.114.187:8848");
|
//"11.239.114.187:8848");
|
||||||
properties.setProperty(PropertyKeyConst.USERNAME, "nacos");
|
//properties.setProperty(PropertyKeyConst.USERNAME, "nacos");
|
||||||
properties.setProperty(PropertyKeyConst.PASSWORD, "nacos");
|
//properties.setProperty(PropertyKeyConst.PASSWORD, "nacos");
|
||||||
|
|
||||||
configService = NacosFactory.createConfigService(properties);
|
configService = NacosFactory.createConfigService(properties);
|
||||||
//Thread.sleep(2000L);
|
//Thread.sleep(2000L);
|
||||||
@ -189,11 +189,12 @@ public class ConfigTest {
|
|||||||
public void test2() throws Exception {
|
public void test2() throws Exception {
|
||||||
final String dataId = "xiaochun.xxc";
|
final String dataId = "xiaochun.xxc";
|
||||||
final String group = "xiaochun.xxc";
|
final String group = "xiaochun.xxc";
|
||||||
|
Random random = new Random();
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
properties.setProperty(PropertyKeyConst.SERVER_ADDR, "11.160.144.149:8848");
|
properties.setProperty(PropertyKeyConst.SERVER_ADDR, "11.160.144.149:8848,11.160.144.148:8848");
|
||||||
//"
|
//"
|
||||||
List<ConfigService> configServiceList = new ArrayList<ConfigService>();
|
List<ConfigService> configServiceList = new ArrayList<ConfigService>();
|
||||||
for (int i = 0; i < 300; i++) {
|
for (int i = 0; i < 500; i++) {
|
||||||
|
|
||||||
ConfigService configService = NacosFactory.createConfigService(properties);
|
ConfigService configService = NacosFactory.createConfigService(properties);
|
||||||
|
|
||||||
@ -205,8 +206,9 @@ public class ConfigTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
for (int j = 0; j < 50; j++) {
|
||||||
configService.addListener(dataId, group, listener);
|
configService.addListener(dataId + random.nextInt(200), group, listener);
|
||||||
|
}
|
||||||
configServiceList.add(configService);
|
configServiceList.add(configService);
|
||||||
System.out.println(configServiceList.size());
|
System.out.println(configServiceList.size());
|
||||||
}
|
}
|
||||||
@ -223,6 +225,7 @@ public class ConfigTest {
|
|||||||
boolean result = configService.publishConfig(dataId, group, "" + System.currentTimeMillis());
|
boolean result = configService.publishConfig(dataId, group, "" + System.currentTimeMillis());
|
||||||
|
|
||||||
times--;
|
times--;
|
||||||
|
System.out.println("发布配置:" + result);
|
||||||
Thread.sleep(1000L);
|
Thread.sleep(1000L);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -241,21 +244,30 @@ public class ConfigTest {
|
|||||||
public void test() throws Exception {
|
public void test() throws Exception {
|
||||||
|
|
||||||
//SnapShotSwitch.setIsSnapShot(false);
|
//SnapShotSwitch.setIsSnapShot(false);
|
||||||
final Random random = new Random();
|
final Random random = new Random(System.currentTimeMillis());
|
||||||
final String dataId = "xiaochun.xxc";
|
final String dataId = "xiaochun.xxc";
|
||||||
final String group = "xiaochun.xxc";
|
final String group = "xiaochun.xxc";
|
||||||
|
Listener listener = new AbstractListener() {
|
||||||
|
@Override
|
||||||
|
public void receiveConfigInfo(String configInfo) {
|
||||||
|
String[] s = configInfo.split("__");
|
||||||
|
System.out.println("receiveConfigInfo1 content:" + (System.currentTimeMillis() - Long.valueOf(s[1])));
|
||||||
|
}
|
||||||
|
};
|
||||||
Thread th = new Thread(new Runnable() {
|
Thread th = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
int times = 1000;
|
int times = 10000;
|
||||||
while (times > 0) {
|
while (times > 0) {
|
||||||
try {
|
try {
|
||||||
String content1 = System.currentTimeMillis() + "";
|
String content1 = new String(new byte[5000]) + "__" + System.currentTimeMillis();
|
||||||
boolean b = configService.publishConfig(dataId + random.nextInt(20), group, content1);
|
System.out.println(content1.length());
|
||||||
|
boolean b = configService.publishConfig(dataId + random.nextInt(400), group, content1);
|
||||||
times--;
|
times--;
|
||||||
Thread.sleep(1000L);
|
System.out.println("发布配置:" + b);
|
||||||
|
|
||||||
|
Thread.sleep(500L);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -266,29 +278,15 @@ public class ConfigTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
th.start();
|
th.start();
|
||||||
|
|
||||||
Listener listener = new AbstractListener() {
|
for (int i = 0; i < 500; i++) {
|
||||||
@Override
|
String content1 = System.currentTimeMillis() + "";
|
||||||
public void receiveConfigInfo(String configInfo) {
|
configService.getConfigAndSignListener(dataId + i, group, 3000L, listener);
|
||||||
System.out.println(
|
|
||||||
"receiveConfigInfo1 content:" + (System.currentTimeMillis() - Long.valueOf(configInfo)));
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++) {
|
|
||||||
final int ls = i;
|
|
||||||
configService.addListener(dataId + i, group, listener);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread.sleep(1000000L);
|
Thread.sleep(1000000L);
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++) {
|
|
||||||
configService.removeListener(dataId + i, group, listener);
|
|
||||||
}
|
|
||||||
System.out.println("remove listens.");
|
System.out.println("remove listens.");
|
||||||
|
|
||||||
Scanner scanner = new Scanner(System.in);
|
Scanner scanner = new Scanner(System.in);
|
||||||
@ -341,7 +339,6 @@ public class ConfigTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println(times);
|
System.out.println(times);
|
||||||
System.out.println("Write Done");
|
System.out.println("Write Done");
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user