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

尝试实现双数据源互换实现的透明互换 #2

Open
diguage opened this issue Jul 16, 2021 · 0 comments
Open

尝试实现双数据源互换实现的透明互换 #2

diguage opened this issue Jul 16, 2021 · 0 comments
Labels

Comments

@diguage
Copy link
Owner

diguage commented Jul 16, 2021

学习 Spring 源码时,看到王福强老师的下面这篇文章。感觉这个技术方案,我们也可以用。尝试实现一下。


对双数据源互换实现的改进(improve to 2-dataSource swapping) - 扶墙老师说:一个架构士的思考与沉淀

好久没有写blog了,随便找一个话题吧!就从原来的那个双数据源互换的问题说起吧!

下图是当时的实现演示(图片来自SpringIDE的BeanView):

当时是使用了Spring提供的 org.springframework.jdbc.datasource.DelegatingDataSource 类,使他拥有两个数据源的引用,默认的 targetDataSource 指向第一个数据源,当 ThrowsAdvice 捕获异常之后,重新替换掉 targetDataSource 指向的数据源引用。我不确定这种方式是否是最好的,但是好像某些情况下不是很可靠,所以,后来改为了以下的实现形式:

现在我们采用Spring提供的 org.springframework.aop.target.HotSwappableTargetSource 类,构造的时候就直接让其默认为第一个数据源,bean的配置类似于:

<bean id="hotSwapTarget" class="org.springframework.aop.target.HotSwappableTargetSource">
    <constructor-arg><ref bean="dataSourcePrimary"/></constructor-arg>
</bean>

有了TargetSource之后,我们就可以使用 ProxyFactoryBean 将其包装起来,给外层引用了,但是在这之前,我们要实现我们的主要功能,即某一个数据源崩溃之后,我们要马上切换到可用的数据源:

targetSource.swap(isPrimaryUsed?slave:primary);
isPrimaryUsed = !isPrimaryUsed;

这样,我们所有需要准备的都ok了,最后要做的就是组装 TargetSourceAdvice 了。下面就简单得罗列部分配置,或许更能帮助大家了解SpringAop的使用:

<bean id="swapThrowsAdvice" class="com.livedoor.finance.credit.ivr.aspects.SwapSourceThrowsAdvice">
    <property name="primary"><ref bean="dataSourcePrimary"/></property>
    <property name="slave"><ref bean="dataSourceSecondary"/></property>
    <property name="targetSource"><ref bean="hotSwapTarget"/></property>
</bean>
 
<bean id="swapThrowsAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <property name="advice"><ref local="swapThrowsAdvice"/></property>
    <property name="pattern"><value>.*getConnection.*</value></property>
</bean>
 
<bean id="dataSource" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="targetSource">
        <ref bean="hotSwapTarget"/>
    </property>

    <property name="interceptorNames">
        <list>
            <value>swapThrowsAdvisor</value>
        </list>
    </property>
</bean>

这样,最终外层所引用的dataSource就可以在某个数据源崩溃之后,直接切换到可用的备用数据源,而这些都在Proxy 内部屏蔽掉了,客户端无需关心这些。

好了,今天就扯这些,呵呵

@diguage diguage added the TODO label Jul 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant