Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

dubbo-admin同时对多个ip进行黑名单访问控制无效 #181

Open
dimmacro opened this issue Sep 1, 2016 · 5 comments
Open

dubbo-admin同时对多个ip进行黑名单访问控制无效 #181

dimmacro opened this issue Sep 1, 2016 · 5 comments

Comments

@dimmacro
Copy link

dimmacro commented Sep 1, 2016

在dubbo-admin中对一个服务可以按ip进行访问控制,测试中发现只禁用一个ip才有效果,但是同时禁用多个ip则会整个禁用控制失效,经跟踪代码发现com.alibaba.dubbo.rpc.cluster.router.condition.ConditionRouter.java里的
private static final class MatchPair { final Set<String> matches = new HashSet<String>(); final Set<String> mismatches = new HashSet<String>(); public boolean isMatch(String value, URL param) { for (String match : matches) { if (! UrlUtils.isMatchGlobPattern(match, value, param)) { return false; } } for (String mismatch : mismatches) { if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) { return false; } } return true; } }
ismacth方法,当有多个不同的ip禁用时,如上代码所示,只要有一个match值与value不一致,就会返回false,从而使需要禁用的ip也能匹配失败。

@phoebechengz
Copy link

路由的时候遇到相同的问题,后面换用IP段来路由。

@daleyzou
Copy link

daleyzou commented May 6, 2020

确实,com.alibaba.dubbo.rpc.cluster.router.condition.ConditionRouter.MatchPair#isMatch 这个方法判断是否匹配有问题

@dynastqin
Copy link

dynastqin commented Dec 30, 2020

通过自定RouterFactory拓展点可以解决此问题,如下是本人的解决方案:

  1. 定义如下类MyConditionRouterFactory
public class MyConditionRouterFactory implements RouterFactory {
    public static final String NAME = "myCondition";
    public Router getRouter(URL url) {
        return new MyConditionRouter(url);
    }
}
  1. 增加类MyConditionRouter,基于源码com.alibaba.dubbo.rpc.cluster.router.condition.ConditionRouter,并修改如下关键方法
...
private static final class MatchPair {
        final Set<String> matches = new HashSet<String>();
        final Set<String> mismatches = new HashSet<String>();

        public boolean isMatch(String value, URL param) {

            for (String mismatch : mismatches) {
                if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) {
                    return false;
                }
            }

            if (matches.isEmpty()) return true;
           //这里只要任意个匹配,直接返回,形如 application=myConsumer => host = 127.0.0.1,127.0.0.2
            for (String match : matches) {
                if (UrlUtils.isMatchGlobPattern(match, value, param)) {
                    return true;
                }
            }

            return false;
        }
    }
...
  1. 在 META-INF/dubbo增加拓展点配置文件com.alibaba.dubbo.rpc.cluster.RouterFactory,内容:
    myCondition=xxx.MyConditionRouterFactory

  2. 使用上述自定义路由规则,举例:

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://xxx:2181"));
        
//注意这里改为myCondition(协议?^_^)
final URL url = URL.valueOf("myCondition://0.0.0.0/xxx.DemoService?category=routers&force=true&enabled=true&dynamic=false&rule=" +
                URL.encode("application = myConsumer => host = 127.0.0.1,127.0.0.2"));

registry.register(url);

以上

@dynastqin
Copy link

dynastqin commented Feb 25, 2021

方案二:基于script的路由,思路与myCondition路由大同小异,这是在不改任何源代码的方式来实现(dubbo的script路由很灵活),定义如下:

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://xxx:2181"));

String script = "(function route(invokers,invocation){var routeApp='myConsumer';var routeHosts='127.0.0.1,127.0.0.2'.split(',');var result=new java.util.ArrayList();for(var i=0;i<invokers.size();i++){var url=invokers.get(i).getUrl();if(url.getParameter('application')!==routeApp){result.add(invokers.get(i))}else if(routeHosts.indexOf(url.getHost())>=0){result.add(invokers.get(i))}}return result}(invokers,invocation));";

URL url = URL.valueOf("script://0.0.0.0/xxx.DemoService?category=routers&force=true&enabled=true&dynamic=false&type=javascript&rule=" + URL.encode(script));

registry.register(url);

ps
完整的script如下:

(function route(invokers, invocation) {

    var routeApp = 'myConsumer';
    var routeHosts = '127.0.0.1,127.0.0.2'.split(',');

    var result = new java.util.ArrayList();

    for (var i = 0; i < invokers.size(); i++) {
        var url = invokers.get(i).getUrl();

        if (url.getParameter('application') !== routeApp) {
            result.add(invokers.get(i));
        } else if (routeHosts.indexOf(url.getHost()) >= 0) {
            result.add(invokers.get(i));
        }
    }
    return result;
}(invokers, invocation));

@daleyzou
Copy link

daleyzou commented Mar 2, 2021

方案二:基于script的路由,思路与myCondition路由大同小异,这是在不改任何源代码的方式来实现(dubbo的script路由很灵活),定义如下:

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://xxx:2181"));

String script = "(function route(invokers,invocation){var routeApp='myConsumer';var routeHosts='127.0.0.1,127.0.0.2'.split(',');var result=new java.util.ArrayList();for(var i=0;i<invokers.size();i++){var url=invokers.get(i).getUrl();if(url.getParameter('application')!==routeApp){result.add(invokers.get(i))}else if(routeHosts.indexOf(url.getHost())>=0){result.add(invokers.get(i))}}return result}(invokers,invocation));";

URL url = URL.valueOf("script://0.0.0.0/xxx.DemoService?category=routers&force=true&enabled=true&dynamic=false&type=javascript&rule=" + URL.encode(script));

registry.register(url);

ps
完整的script如下:

(function route(invokers, invocation) {

    var routeApp = 'myConsumer';
    var routeHosts = '127.0.0.1,127.0.0.2'.split(',');

    var result = new java.util.ArrayList();

    for (var i = 0; i < invokers.size(); i++) {
        var url = invokers.get(i).getUrl();

        if (url.getParameter('application') !== routeApp) {
            result.add(invokers.get(i));
        } else if (routeHosts.indexOf(url.getHost()) >= 0) {
            result.add(invokers.get(i));
        }
    }
    return result;
}(invokers, invocation));

相当于是推了个js脚本到zookeeper中下发,从ip规则转为脚本规则。 感觉还是升级大法好,哈哈

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants