Skip to content

Commit

Permalink
support dynamic config at the interface level
Browse files Browse the repository at this point in the history
  • Loading branch information
Narzisss committed Sep 23, 2024
1 parent 528d0fb commit 853ed3f
Show file tree
Hide file tree
Showing 14 changed files with 618 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import com.alipay.sofa.rpc.config.RegistryConfig;
import com.alipay.sofa.rpc.context.RpcRuntimeContext;
import com.alipay.sofa.rpc.core.exception.SofaRpcRuntimeException;
import com.alipay.sofa.rpc.dynamic.ConfigChangedEvent;
import com.alipay.sofa.rpc.dynamic.ConfigChangeType;
import com.alipay.sofa.rpc.dynamic.DynamicConfigKeys;
import com.alipay.sofa.rpc.dynamic.DynamicConfigManager;
import com.alipay.sofa.rpc.dynamic.DynamicConfigManagerFactory;
Expand All @@ -42,10 +44,7 @@
import com.alipay.sofa.rpc.registry.Registry;
import com.alipay.sofa.rpc.registry.RegistryFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
Expand Down Expand Up @@ -156,13 +155,26 @@ public T refer() {
proxyIns = (T) ProxyFactory.buildProxy(consumerConfig.getProxy(), consumerConfig.getProxyClass(),
proxyInvoker);

//动态配置
//启用请求级别动态配置
final String dynamicAlias = consumerConfig.getParameter(DynamicConfigKeys.DYNAMIC_ALIAS);
if (StringUtils.isNotBlank(dynamicAlias)) {
final DynamicConfigManager dynamicManager = DynamicConfigManagerFactory.getDynamicManager(
consumerConfig.getAppName(), dynamicAlias);
dynamicManager.initServiceConfiguration(consumerConfig.getInterfaceId());
}

//启用接口级别动态配置
final String dynamicUrl = consumerConfig.getParameter(DynamicConfigKeys.DYNAMIC_URL);
if (StringUtils.isNotBlank(dynamicUrl)) {
final DynamicConfigManager dynamicManager = DynamicConfigManagerFactory.getDynamicManagerWithUrl(
consumerConfig.getAppName(), dynamicUrl);

//build listeners for dynamic config
consumerConfig.setConfigListener(buildConfigListener(this,dynamicManager));
}



} catch (Exception e) {
if (cluster != null) {
cluster.destroy();
Expand Down Expand Up @@ -202,6 +214,17 @@ protected ConfigListener buildConfigListener(ConsumerBootstrap bootstrap) {
return new ConsumerAttributeListener();
}

/**
* Build ConfigListener for consumer bootstrap with dynamic config.
*
* @param bootstrap ConsumerBootstrap
* @param dynamicManager DynamicConfigManager
* @return ConfigListener
*/
protected ConfigListener buildConfigListener(ConsumerBootstrap bootstrap, DynamicConfigManager dynamicManager) {
return new ConsumerAttributeListener(dynamicManager);
}

/**
* Build ProviderInfoListener for consumer bootstrap.
*
Expand Down Expand Up @@ -438,8 +461,46 @@ public void updateAllProviders(List<ProviderGroup> groups) {
*/
private class ConsumerAttributeListener implements ConfigListener {

private Map<String, String> newValueMap = new HashMap<>();

ConsumerAttributeListener() {

}

ConsumerAttributeListener(DynamicConfigManager dynamicManager) {
this.initWith(consumerConfig.getInterfaceId(),dynamicManager);
}

public void initWith(String key, DynamicConfigManager dynamicManager) {
dynamicManager.addListener(key, this);
// 初始化配置值
String rawConfig = dynamicManager.getConfig(key);
if (!StringUtils.isEmpty(rawConfig)) {
process(new ConfigChangedEvent(key, "sofa-rpc",rawConfig));
}
}

@Override
public void process(ConfigChangedEvent event){
if (event.getChangeType().equals(ConfigChangeType.DELETED)) {
newValueMap = null;
} else {
// ADDED or MODIFIED
String[] lines = event.getContent().split("\n");
for (String line : lines) {
String[] keyValue = line.split("=", 2);
if (keyValue.length == 2) {
String key = keyValue[0].trim();
String value = keyValue[1].trim();
newValueMap.put(key, value);
}
}
}
attrUpdated(newValueMap);
}

@Override
public void configChanged(Map newValue) {
public void configChanged(Map newValueMap) {

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,24 @@
*/
package com.alipay.sofa.rpc.dynamic.apollo;

import com.alipay.sofa.common.config.SofaConfigs;
import com.alipay.sofa.rpc.auth.AuthRuleGroup;
import com.alipay.sofa.rpc.dynamic.DynamicConfigKeyHelper;
import com.alipay.sofa.rpc.dynamic.DynamicConfigManager;
import com.alipay.sofa.rpc.dynamic.DynamicHelper;
import com.alipay.sofa.rpc.dynamic.*;
import com.alipay.sofa.rpc.ext.Extension;
import com.alipay.sofa.rpc.listener.ConfigListener;
import com.alipay.sofa.rpc.log.Logger;
import com.alipay.sofa.rpc.log.LoggerFactory;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.enums.PropertyChangeType;
import com.ctrip.framework.apollo.model.ConfigChange;

import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
* @author bystander
Expand All @@ -34,11 +45,30 @@
@Extension(value = "apollo", override = true)
public class ApolloDynamicConfigManager extends DynamicConfigManager {

Logger LOGGER = LoggerFactory.getLogger(ApolloDynamicConfigManager.class);

private static final String APOLLO_APPID_KEY = "app.id";

private static final String APOLLO_ADDR_KEY = "apollo.meta";

private static final String APOLLO_PROTOCOL_PREFIX = "http://";

private Config config;

private final ConcurrentMap<String, ApolloListener> watchListenerMap = new ConcurrentHashMap<>();

protected ApolloDynamicConfigManager(String appName) {
super(appName);
config = ConfigService.getAppConfig();
System.setProperty(APOLLO_APPID_KEY, appName);
System.setProperty(APOLLO_ADDR_KEY, APOLLO_PROTOCOL_PREFIX + SofaConfigs.getOrDefault(DynamicConfigKeys.APOLLO_ADDRESS));
config = ConfigService.getConfig(DynamicConfigKeys.DEFAULT_GROUP);
}

protected ApolloDynamicConfigManager(String appName,String address) {
super(appName);
System.setProperty(APOLLO_APPID_KEY, appName);
System.setProperty(APOLLO_ADDR_KEY, APOLLO_PROTOCOL_PREFIX + address);
config = ConfigService.getConfig(DynamicConfigKeys.DEFAULT_GROUP);
}

@Override
Expand Down Expand Up @@ -77,4 +107,49 @@ public AuthRuleGroup getServiceAuthRule(String service) {
//TODO 暂不支持
return null;
}

@Override
public String getConfig(String key){
return config.getProperty(key, DynamicHelper.DEFAULT_DYNAMIC_VALUE);
}

@Override
public void addListener(String key, ConfigListener listener){
ApolloListener apolloListener = watchListenerMap.computeIfAbsent(key, k -> new ApolloListener());
apolloListener.addListener(listener);
config.addChangeListener(apolloListener, Collections.singleton(key));
}

public class ApolloListener implements ConfigChangeListener {

private Set<ConfigListener> listeners = new CopyOnWriteArraySet<>();

ApolloListener() {}

@Override
public void onChange(com.ctrip.framework.apollo.model.ConfigChangeEvent changeEvent) {
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
if ("".equals(change.getNewValue())) {
LOGGER.info("an empty rule is received for key: " + key);
return;
}

ConfigChangedEvent event =
new ConfigChangedEvent(key, change.getNamespace(), change.getNewValue(), getChangeType(change));
listeners.forEach(listener -> listener.process(event));
}
}

private ConfigChangeType getChangeType(ConfigChange change) {
if (change.getChangeType() == PropertyChangeType.DELETED) {
return ConfigChangeType.DELETED;
}
return ConfigChangeType.MODIFIED;
}

void addListener(ConfigListener configListener) {
this.listeners.add(configListener);
}
}
}
Loading

0 comments on commit 853ed3f

Please sign in to comment.