架构设计|找错(ZdalRuleCalculateException: 规则引擎计算出错,拆分值=)

序言

这一段是我遇上问题的过程,可以直接跳转到下面的正文
在刚写的博客《Zdal分库分表介绍、超详细一步一步搭建简单的zdal框架》
【架构设计|找错(ZdalRuleCalculateException: 规则引擎计算出错,拆分值=)】中,是通过向线程中存放数据库远程路由来指定操作哪个数据库,在mybatis执
行插引用块内容入操作时,会从数据库中取出该数据库远程路由,执行插入。代码
如下:
//得到 数据库选择器标识路由条件---确定是存在哪一个数据库中 DBSelectorIDRouteCondition dbSelectorIDRouteCondition = new DBSelectorIDRouteCondition("t_blog", dbSelectorID, physicTableName); //将分库分表添加到线程中 ThreadLocalMap.put(ThreadLocalString.ROUTE_CONDITION, dbSelectorIDRouteCondition);

其实zdal在执行插入、更新、删除这种有确定的索引(对应zdal-dev-rule.xml中
配置的映射规则的索引),是 不需要在执行数据库操作前指定操作的数据库,可
以直接进行插入、更新、删除。下面是我在直接删除时出现的报错,以及解决的
过程。
处理异常正文
记一次找BUG的过程。希望能对有类似bug的你有所帮助。

1、异常错误内容
### Cause: com.alipay.zdal.rule.ruleengine.exception.ZdalRuleCalculateException: 规则引擎计算出错,拆分值={id=8} at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:200) at org.apache.ibatis.session.defaults.DefaultSqlSession.delete(DefaultSqlSession.java:213) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:434) ... 30 more Caused by: com.alipay.zdal.rule.ruleengine.exception.ZdalRuleCalculateException: 规则引擎计算出错,拆分值={id=8} at com.alipay.zdal.rule.groovy.GroovyListRuleEngine.evalueateSamplingField(GroovyListRuleEngine.java:139) at com.alipay.zdal.rule.ruleengine.rule.CartesianProductBasedListResultRule.evalOnceAndAddToReturnMap(CartesianProductBasedListResultRule.java:321) at com.alipay.zdal.rule.ruleengine.rule.CartesianProductBasedListResultRule.evalElement(CartesianProductBasedListResultRule.java:254) at com.alipay.zdal.rule.ruleengine.rule.CartesianProductBasedListResultRule.eval(CartesianProductBasedListResultRule.java:49) at com.alipay.zdal.rule.bean.LogicTable.calculate(LogicTable.java:255) at com.alipay.zdal.client.controller.SpringBasedRuleMatcherImpl.match(SpringBasedRuleMatcherImpl.java:71) at com.alipay.zdal.client.controller.SpringBasedDispatcherImpl.getDBAndTables(SpringBasedDispatcherImpl.java:87) at com.alipay.zdal.client.jdbc.ZdalStatement.getExecutionMetaData(ZdalStatement.java:720) at com.alipay.zdal.client.jdbc.ZdalStatement.getExecutionContext1(ZdalStatement.java:562) at com.alipay.zdal.client.jdbc.ZdalStatement.getExecutionContext(ZdalStatement.java:417) at com.alipay.zdal.client.jdbc.ZdalPreparedStatement.executeUpdate(ZdalPreparedStatement.java:481) at com.alipay.zdal.client.jdbc.ZdalPreparedStatement.execute(ZdalPreparedStatement.java:226) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59) at com.sun.proxy.$Proxy24.execute(Unknown Source) at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:46) at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74) at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50) at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76) at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198) ... 36 more Caused by: java.lang.IllegalArgumentException: 调用方法失败: public java.lang.Object RULE.eval(java.util.Map) at com.alipay.zdal.rule.groovy.GroovyListRuleEngine.invoke(GroovyListRuleEngine.java:176) at com.alipay.zdal.rule.groovy.GroovyListRuleEngine.imvokeMethod(GroovyListRuleEngine.java:150) at com.alipay.zdal.rule.groovy.GroovyListRuleEngine.evalueateSamplingField(GroovyListRuleEngine.java:132) ... 59 more Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.alipay.zdal.rule.groovy.GroovyListRuleEngine.invoke(GroovyListRuleEngine.java:172) ... 61 more Caused by: groovy.lang.MissingPropertyException: No such property: com for class: RULE at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:49) at org.codehaus.groovy.runtime.callsite.GetEffectivePogoPropertySite.getProperty(GetEffectivePogoPropertySite.java:71) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:241) at RULE.eval(script1501492281398.groovy:1) ... 66 more

2、解决过程
报错是ZdalRuleCalculateException:规则引擎计算出错,拆分值={id=8}
在检查了三遍相关配置文件,还有路由规则,还是没找到问题。实在没办法后,我通过设置断点,debug查看源码。定位到执行出错的地方在最后调用Method.invoke方法,如下图:
架构设计|找错(ZdalRuleCalculateException: 规则引擎计算出错,拆分值=)
文章图片

发现method中参数不对,同我配置的映射规则不对,然后我开始定位是哪一步导致method中参数出的问题,发现method是在GroovyListRuleEngine类中初始化加载,随后我断点设置在初始化开始debug,如下图:
架构设计|找错(ZdalRuleCalculateException: 规则引擎计算出错,拆分值=)
文章图片

问题查到这儿,发现这里的expression表达式对应的值不对,方法名对了,但是报名没有完全对上,个人的 zdal-dev.rule.xml配置文件为:
架构设计|找错(ZdalRuleCalculateException: 规则引擎计算出错,拆分值=)
文章图片

3、解决问题
导致BUG出现的还是配置文件出错,大家别光看类名.方法名以及方法内容是否出错,再次检查一下前置包名是否有问题。
最后的结果很简单,寻找的过程比较曲折,绕了很多的弯,技巧就是耐心的看下去,会能看到zdal框架的一个运行整体流程。

    推荐阅读