apache / incubator-seata

:fire: Seata is an easy-to-use, high-performance, open source distributed transaction solution.
https://seata.apache.org/
Apache License 2.0
25.25k stars 8.77k forks source link

GlobalTransactionScanner 多例bean问题 #6568

Open StephenFaust opened 4 months ago

StephenFaust commented 4 months ago

Ⅰ. Issue Description

在sprigboot中对注解的目标类进行代理时,为啥需要判断PROXYED_SET,如果是多例bean,每次都返回的都是原始对象,而非代理对象

image
funky-eyes commented 4 months ago

In my opinion, this code is just to avoid duplicate proxies. @wangliang181230 , @slievrly , @xingfudeshi , please help to answer this question.

xingfudeshi commented 4 months ago

In my opinion, this code is just to avoid duplicate proxies. @wangliang181230 , @slievrly , @xingfudeshi , please help to answer this question.

You already answered the question.

StephenFaust commented 4 months ago
image

在我的bean使用原型模式

image

容器启动的时候,由于proxyed_set中没有beanName所以可以正常代理成功

image

当我再次从容器获取该bean时,由于使用原型模式,因此,会返回一个新的对象,即需要重新代理它,但是由于proxyed_set已经包含该beanName,因此会直接返回,所以最好我得到的是一个未被代理的原始对象

StephenFaust commented 4 months ago
image

最后获取的是原始对象

StephenFaust commented 4 months ago

你们所说重复代理,指的是什么情况下会发生重复代理?

funky-eyes commented 4 months ago

In my opinion, this code is just to avoid duplicate proxies. @wangliang181230 , @slievrly , @xingfudeshi , please help to answer this question.

You already answered the question.

这么看来,我们应该缓存bean,而不是beanname,否则多例情况下将不会进行代理 In this case, we should cache the bean instead of the bean name. Otherwise, if there are multiple instances, no proxy will be created.

StephenFaust commented 4 months ago

In my opinion, this code is just to avoid duplicate proxies. @wangliang181230 , @slievrly , @xingfudeshi , please help to answer this question.

You already answered the question.

这么看来,我们应该缓存bean,而不是beanname,否则多例情况下将不会进行代理 In this case, we should cache the bean instead of the bean name. Otherwise, if there are multiple instances, no proxy will be created.

如果直接缓存bean,那是否失去了多例bean的意义,所以,我只是想知道,这个proxyed_set 你们在设计时,是考虑到了重复代理的情况,我想知道,在哪种场景下会出现重复代理?

funky-eyes commented 4 months ago

In my opinion, this code is just to avoid duplicate proxies. @wangliang181230 , @slievrly , @xingfudeshi , please help to answer this question.

You already answered the question.

这么看来,我们应该缓存bean,而不是beanname,否则多例情况下将不会进行代理 In this case, we should cache the bean instead of the bean name. Otherwise, if there are multiple instances, no proxy will be created.

如果直接缓存bean,那是否失去了多例bean的意义,所以,我只是想知道,这个proxyed_set 你们在设计时,是考虑到了重复代理的情况,我想知道,在哪种场景下会出现重复代理?

我说的缓存bean是将bean缓存起来,只是用来比较bean是否已经被seata所代理过,不过我目前感觉这种方式也不好,针对多例bean反而可能会出现oom,因为被seata一直引用着。大家可以在这讨论出一个合适的方案来解决这个问题。 What I meant by caching beans is to cache the beans and use them only to check whether they have been proxied by Seata. However, I currently feel that this approach may not be ideal, as it could potentially lead to out-of-memory errors for prototype beans, which are constantly referenced by Seata. Let's discuss and come up with a suitable solution to address this issue.

StephenFaust commented 4 months ago

In my opinion, this code is just to avoid duplicate proxies. @wangliang181230 , @slievrly , @xingfudeshi , please help to answer this question.

You already answered the question.

这么看来,我们应该缓存bean,而不是beanname,否则多例情况下将不会进行代理 In this case, we should cache the bean instead of the bean name. Otherwise, if there are multiple instances, no proxy will be created.

如果直接缓存bean,那是否失去了多例bean的意义,所以,我只是想知道,这个proxyed_set 你们在设计时,是考虑到了重复代理的情况,我想知道,在哪种场景下会出现重复代理?

我说的缓存bean是将bean缓存起来,只是用来比较bean是否已经被seata所代理过,不过我目前感觉这种方式也不好,针对多例bean反而可能会出现oom,因为被seata一直引用着。大家可以在这讨论出一个合适的方案来解决这个问题。 What I meant by caching beans is to cache the beans and use them only to check whether they have been proxied by Seata. However, I currently feel that this approach may not be ideal, as it could potentially lead to out-of-memory errors for prototype beans, which are constantly referenced by Seata. Let's discuss and come up with a suitable solution to address this issue.

所以我还是需要了解到这个proxyed_set到底是为了避免那种场景下的重复代理,因为在spring中默认是单例模式,warpIfNecessary()只会走一次,生成的代理对象会放在单例池中,后续也不会出现重复代理的情况

tanyaofei commented 2 months ago

In my opinion, this code is just to avoid duplicate proxies. @wangliang181230 , @slievrly , @xingfudeshi , please help to answer this question.

You already answered the question.

这么看来,我们应该缓存bean,而不是beanname,否则多例情况下将不会进行代理 In this case, we should cache the bean instead of the bean name. Otherwise, if there are multiple instances, no proxy will be created.

如果直接缓存bean,那是否失去了多例bean的意义,所以,我只是想知道,这个proxyed_set 你们在设计时,是考虑到了重复代理的情况,我想知道,在哪种场景下会出现重复代理?

我说的缓存bean是将bean缓存起来,只是用来比较bean是否已经被seata所代理过,不过我目前感觉这种方式也不好,针对多例bean反而可能会出现oom,因为被seata一直引用着。大家可以在这讨论出一个合适的方案来解决这个问题。 What I meant by caching beans is to cache the beans and use them only to check whether they have been proxied by Seata. However, I currently feel that this approach may not be ideal, as it could potentially lead to out-of-memory errors for prototype beans, which are constantly referenced by Seata. Let's discuss and come up with a suitable solution to address this issue.

似乎使用弱引用可以解决这个问题?