Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Support data of configs and overrides from zookeeper registry. #100

Merged
merged 23 commits into from
May 15, 2018

Conversation

SteNicholas
Copy link
Contributor

Motivation:

Zookeeper配置节点观察者未实现具体动态调整Provider/Consumer自定义配置逻辑

Modification:

Zookeeper配置节点观察者实现思路是Zookeeper注册中心修改订阅配置节点subscribeConfig方法,监听配置节点下 子节点增加、子节点删除、子节点Data修改事件的实现即完善ZookeeperConfigObserver配置节点观察者实现,因为该配置节点观察者内部有configListenerMap绑定接口配置和配置监听者,所以实现updateConfig,updateConfigAll,removeConfig三个方法依赖子节点Data,之所以addConfig方法实现逻辑跟updateConfig方法完全一致,是因为ProviderAttributeListener,ConsumerAttributeListener更新属性逻辑决定的。另外removeConfig方法实现需要考虑删除子节点Data需要恢复接口级配置默认值。

Result:

Fixes #98 .
If there is no issue then describe the changes introduced by this PR.

@codecov-io
Copy link

codecov-io commented May 8, 2018

Codecov Report

Merging #100 into master will decrease coverage by 0.77%.
The diff coverage is 21.78%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master     #100      +/-   ##
============================================
- Coverage     65.85%   65.07%   -0.78%     
+ Complexity      648      647       -1     
============================================
  Files           270      271       +1     
  Lines         11407    11583     +176     
  Branches       1903     1951      +48     
============================================
+ Hits           7512     7538      +26     
- Misses         2933     3080     +147     
- Partials        962      965       +3
Impacted Files Coverage Δ Complexity Δ
.../sofa/rpc/registry/zk/ZookeeperConfigObserver.java 15.71% <12%> (-13.7%) 0 <0> (ø)
...ofa/rpc/registry/zk/ZookeeperOverrideObserver.java 15.27% <15.27%> (ø) 0 <0> (?)
.../sofa/rpc/registry/zk/ZookeeperRegistryHelper.java 67.16% <2.77%> (-23.66%) 0 <0> (ø)
...alipay/sofa/rpc/registry/zk/ZookeeperRegistry.java 57.08% <59.09%> (+0.32%) 0 <0> (ø) ⬇️
...sian/MultipleClassLoaderSofaSerializerFactory.java 86.66% <0%> (-6.67%) 4% <0%> (-1%)
...pay/sofa/rpc/transport/ClientTransportFactory.java 60.6% <0%> (-4.55%) 0% <0%> (ø)
...y/sofa/rpc/bootstrap/DefaultProviderBootstrap.java 60.91% <0%> (-2.54%) 0% <0%> (ø)
...ofa/rpc/registry/zk/ZookeeperProviderObserver.java 68.51% <0%> (+1.85%) 0% <0%> (ø) ⬇️
...ofa/rpc/registry/zk/AbstractZookeeperObserver.java 100% <0%> (+25%) 0% <0%> (ø) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 19cf47e...db84b44. Read the comment docs.

String property = childData.getPath().substring(configPath.length() + 1);
//If event type is CHILD_REMOVED, attribute should return to default value
return Collections.singletonMap(property,
remove ? RpcConfigs.getStringValue(property) : new String(childData.getData()));
Copy link
Contributor

@leizhiyuan leizhiyuan May 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个地方property 是一些服务相关的信息,比如 timeout,weight,其他自定义的动态属性 这种 key
基本在这里
com.alipay.sofa.rpc.client.ProviderInfoAttrs 中,可以看下.
RpcConfigs 中是

            // loadCustom
            loadCustom("sofa-rpc/rpc-config.json");
            loadCustom("META-INF/sofa-rpc/rpc-config.json");

这两个文件中的一些默认配置,比如.
"consumer.connect.timeout": 3000

所以这时候这个取值会错误,因为配置文件中其实也是没有这个key的.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

根据线下讨论,今天我尽快修复这块代码错误。

@leizhiyuan
Copy link
Contributor

还有个问题,以com.alipay.sofa.rpc.bootstrap.DefaultProviderBootstrap为例

@Override
        public synchronized void attrUpdated(Map newValueMap) {
            String appName = providerConfig.getAppName();
            // 可以改变的配置 例如tag concurrents等
            Map<String, String> newValues = (Map<String, String>) newValueMap;
            Map<String, String> oldValues = new HashMap<String, String>();
            boolean reexport = false;

            // TODO 可能需要处理ServerConfig的配置变化
            try { // 检查是否有变化
                  // 是否过滤map?
                for (Map.Entry<String, String> entry : newValues.entrySet()) {
                    String newValue = entry.getValue();
                    String oldValue = providerConfig.queryAttribute(entry.getKey());
                    boolean changed = oldValue == null ? newValue != null : !oldValue.equals(newValue);
                    if (changed) {
                        oldValues.put(entry.getKey(), oldValue);
                    }
                    reexport = reexport || changed;
                }
            } catch (Exception e) {
                LOGGER.errorWithApp(appName, "Catch exception when provider attribute compare", e);
                return;
            }

如果用户删除了一个自定义配置,这情况下,newValues少了一个值,就不会被更新.这个不太符合期望

现在内存中对于ProviderConfig/ConsumerConfig 这种,是没有保存原始 weight信息的,所以删除动态值的时候,这些值没办法恢复成用户之前设置的值. @ujjboy

@ujjboy
Copy link
Member

ujjboy commented May 9, 2018

首先需要讨论下恢复默认配置是否合适? 如果用户原来配置的不是默认值,那是不是反而会有不好的影响?

如果的确要恢复默认配置,建议直接new一个空Config对象获取里面的值,而不是自己去取参数?

@SteNicholas
Copy link
Contributor Author

@ujjboy 那关于恢复默认配置的话,假如用户原来配置的不是默认值,当删除掉这条配置的时候意味着这条配置用户其实就想用系统提供的默认值吧?出于这点考虑所以通过RpcConfigs.getStringValue(property)去捞取系统提供的默认值。

@leizhiyuan
Copy link
Contributor

@SteNicholas 不可以,默认值只是用户没有设置的情况下的默认值,用户可以通过 xml 等设置来改掉的.也就是他的初始值并不是默认值.恢复是要恢复到他的初始值.

@SteNicholas
Copy link
Contributor Author

@leizhiyuan 好的,我清楚啦,那我今天修改下这块默认配置的取值逻辑。那关于恢复用户的初始值的话就像你说的内存中对于ProviderConfig/ConsumerConfig没有保存初始的配置,这个时候放ThreadLocal里面保存下可以吗?ThreadLocal里面如果拿不到初始值就用系统默认的取值。

@leizhiyuan
Copy link
Contributor

@SteNicholas 稍等下,等我我补充一下这部分整体的流程说明.之后你再修改

@SteNicholas
Copy link
Contributor Author

@leizhiyuan 由于之前混淆Ip级配置跟接口级配置导致convert的地方有问题,已按照你提供的流程增加override目录新增修改删除事件的监听观察者ZookeeperOverrideObserver,因为服务发布暂时不支持动态配置,暂时支持订阅ConsumerConfig参数设置缘故,故subscribeOverride方法只支持服务调用参数设置,即获取服务注册InterfaceConfig的地方暂时只支持ConsumerConfig类型。原本的ZookeeperConfigObserver保持不变,就是观察处理/config目录的事件变化。ZookeeperRegistryHelper类convertOverrideToAttribute方法提取属性的时候我根据convertProviderToUrls/convertConsumerToUrls得到ip级涉及到的属性变化的key筛选。请您帮忙Review这次修改,谢谢。

return attributes;
}

for (ChildData childData : currentData) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个方法里,如果传进来的数据是两条,其中一条的 ip 是当前机器,转换的时候会怎么样

我觉得应该在这里过滤掉非本 ip 的配置,然后转换.这样传给 ConfigLisenter 的时候,ConfigLisenter就可以直接进行处理

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

嗯,我加一层ip校验过滤,只有本ip的才能交给ConfigListener处理,除了这些还有其他问题吗?

Map<String, String> attribute = ZookeeperRegistryHelper.convertConfigToAttribute(configPath, data,
false);
for (ConfigListener listener : configListeners) {
listener.attrUpdated(attribute);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里改成调用 listener.ConfigChanged , attrUpdated 是给你添加的 override 用的.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好的,我这就修改下,因为configChanged我看重写的方法没具体实现所以就用attrUpdated了。

import com.alipay.sofa.rpc.listener.ProviderInfoListener;
import com.alipay.sofa.rpc.registry.RegistryFactory;
import com.google.common.collect.Maps;
Copy link
Member

@ujjboy ujjboy May 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

用到guava的类的地方修改下,减少第三方强制依赖。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

就直接用原生的JDK集合类是吧?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是的

import com.alipay.sofa.rpc.config.AbstractInterfaceConfig;
import com.alipay.sofa.rpc.config.ConsumerConfig;
import com.alipay.sofa.rpc.config.ProviderConfig;
import com.alipay.sofa.rpc.config.ServerConfig;
import com.alipay.sofa.rpc.context.RpcRuntimeContext;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
Copy link
Member

@ujjboy ujjboy May 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

用到guava的类的地方修改下,减少第三方强制依赖。

AbstractInterfaceConfig registerConfig) throws Exception {
if (data == null) {
if (LOGGER.isInfoEnabled(config.getAppName())) {
LOGGER.info("data is null");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

应该是之前代码问题,修改为 LOGGER.infoWithApp,类似的统一修改下。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

就只有这个地方用了info方法,我看之前的代码就是这么打印log的,没敢改动,我改下。

@SteNicholas
Copy link
Contributor Author

@ujjboy @leizhiyuan 按照你们Code Review地方修改完成,改动点包括1.convertOverrideToAttributes增加对当前机器IP校验,能够过滤掉非本IP配置转换属性传给ConfigLisenter处理;2.ZookeeperConfigObserver修改对ConfigListener调用,改成调用configChanged方法;3.ZookeeperRegistryHelper/ZookeeperRegistryTest改用原生JDK集合类,去掉guaua包第三方依赖;4.ZookeeperConfigObserver/ZookeeperOverrideObserver打印日志改成调用infoWithApp方法。请再次帮忙Review下,谢谢。

/**
* ZookeeperObserver for config node.
* ZookeeperObserver for override node,subscribe interface level provider/consumer config.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里应该是 config node

* @param currentData 子节点Data列表
*/
public void updateConfigAll(AbstractInterfaceConfig config, String overridePath, List<ChildData> currentData)
throws UnsupportedEncodingException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里会抛这个异常吗? 确认下,没有抛的话删掉,会抛的话,注释里加上 @throws

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好的。我现在检查下

* @param overridePath 覆盖Path
* @param data 子节点Data
*/
public void updateConfig(AbstractInterfaceConfig config, String overridePath, ChildData data) throws Exception {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里会抛出异常吗? 确认下,没有抛的话删掉,会抛的话,注释里加上 @throws, 我看有不少这样的地方,一起检查下。

@SteNicholas
Copy link
Contributor Author

@ujjboy @throws注释已修改,麻烦您再看下是否还有问题,非常感谢。

@ujjboy ujjboy merged commit 22b4bc3 into sofastack:master May 15, 2018
@ujjboy ujjboy changed the title 添加ZookeeperConfigObserver功能 Support data of configs and overrides from zookeeper registry. May 15, 2018
@ujjboy ujjboy added the enhancement New feature or request label May 15, 2018
@ujjboy ujjboy added this to the 5.4.0 milestone May 15, 2018
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants