91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在spring事務中正確進行遠程調用

發布時間:2021-07-02 17:44:56 來源:億速云 閱讀:227 作者:chen 欄目:編程語言

本篇內容介紹了“如何在spring事務中正確進行遠程調用”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

前言

最近和朋友聊天,他說他承接的外包項目遇到了分布式事務問題,問我有沒啥解決方案,我本可以直接跟他說,分布式事務方案網上一大堆,什么tcc、可靠消息一致性、最大努力通知之類的,直接網上找個試下,比如直接用阿里的seata。但我并沒有這么做,因為分布式事務,本來就是一個很復雜的課題,真正落地的時候,會發現有時候是多種分布式方案一起混用,而非一種方案走到黑。

因此我就跟他說,能不用分布式事務,就盡量不用,后來我就問了一下他的業務場景,場景也不是很復雜,就是邀請好友注冊,然后可以增加積分,朋友實現邏輯的偽代碼大概如下

    @Transactional(rollbackFor = Exception.class)
    public Boolean inviteUser(..){
        userService.add(..);
        integralService.addIntegration(..,20)
    }

其中integralService是一個遠程積分服務,20為增加的積分值。這代碼乍一看是沒問題,我想可能很多朋友都會這么寫。后邊我就問朋友說你們這個業務場景是否允許如下場景

  • 允不允許邀請的用戶入庫成功,而積分入庫失敗?

  • 允不允許邀請的用戶入庫失敗,而積分入庫成功?

朋友思考了一下,說第二種不允許,第一種方式可以通過補償的方式增加積分。

現在我們回過頭來看這段代碼,我拋出以下兩個問題,看文章的朋友可以思考下

  • 如果添加積分請求耗時特別長,這段代碼有沒有問題?

  • 如果添加積分因為網絡抖動原因出了異常,這段代碼有沒有問題?

這邊說下我的想法

  • 耗時過長,會導致長事務的發生,在并發場景下,可能會導致數據庫連接得不到釋放

  • 網絡抖動出了異常,可能會導致用戶服務的添加邏輯進行回滾

解決耗時過長,有些朋友可能想到可以采用異步的方式,積分抖動異常,可以通過添加熔斷機制,比如積分超時沒響應,就直接進行熔斷

今天我再說一種方案,就是在事務提交后再進行調用,羅里吧嗦一大堆,才剛要進入正題,哈哈

如何在spring的事務中正確的進行遠程調用

通過spring的事務同步管理器

這個是個什么鬼,這是我直譯,它的真身是長如下

org.springframework.transaction.support.TransactionSynchronizationManager

這玩意有啥用,可以利用它注冊一個事務同步器,這個事務同步器,可以允許在事務提交后,做一些事情,核心代碼如下

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                //做你想做的業務
            }
        });

看了代碼,想必大家都知道怎么改造上面邀請用戶,添加積分了吧

 @Transactional(rollbackFor = Exception.class)
    public Boolean inviteUser(..) {
        userService.add(..);
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                integralService.addIntegration(..,20)
            }
        });

但大家發現沒有,每次都要寫這么一坨代碼,看著是不是很惡心,有沒有什么改造的方案。 答案有的,通過注解+aop來整合實現,具體實現邏輯,可以查看下面demo鏈接中的

com.github.lybgeek.transactional

我這邊就不貼具體代碼了,為什么不貼,是因為我要介紹另外一種方案,就是基于spring的事件驅動實現

通過TransactionalEventListener注解+ApplicationEventPublisher

這是spring的事件驅動實現,或者說是觀察者實現方式,不過TransactionalEventListener注解是spring4.2版本之后才提供的注解

通過這種方式如何改造上面邀請用戶,添加積分的實現?

1、在邀請用戶注冊方法中,進行事件發布

偽代碼如下

  @Transactional(rollbackFor = Exception.class)
  public Boolean inviteUser(..) {
        userService.add(..);
         applicationEventPublisher.publishEvent(..);
        });

2、編寫一個事務監聽器,并在里面觸發添加積分實現

偽代碼如下

    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void addIntegration(..){
        integralService.addIntegration(..,20)
    }

這邊有個細節點要注意,就是監聽事件的參數要和發布的參數一致

3、實現核心源碼

@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if (TransactionSynchronizationManager.isSynchronizationActive()) {
			TransactionSynchronization transactionSynchronization = createTransactionSynchronization(event);
			TransactionSynchronizationManager.registerSynchronization(transactionSynchronization);
		}
		else if (this.annotation.fallbackExecution()) {
			if (this.annotation.phase() == TransactionPhase.AFTER_ROLLBACK && logger.isWarnEnabled()) {
				logger.warn("Processing " + event + " as a fallback execution on AFTER_ROLLBACK phase");
			}
			processEvent(event);
		}
		else {
			// No transactional event execution at all
			if (logger.isDebugEnabled()) {
				logger.debug("No transaction is active - skipping " + event);
			}
		}
	}

不知道大家發現沒有,他本質上還是使用了TransactionSynchronizationManager,只是對他再一次進行封裝

總結

在和朋友交流后,發現他們那個外包項目開發人員就只有三個,然后服務拆分了10來個,我就問他說這個外包項目業務有很復雜嗎,他說其實還好,我就問他說業務不復雜,開發人員也不多,為什么不用單體架構,而要用微服務。他給我的答案是甲方爸爸覺得他們項目未來會承載很大的業務量,所以必須得用微服務,而且現在的主流技術棧是微服務。聽到這個答復,我是該說是過度設計還是高瞻遠矚呢?技術日新月異,鬼知道后面會不會出現更厲害的東西,架構從來都不是一步到位,而是逐步演進

demo鏈接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-transation-after-commit

“如何在spring事務中正確進行遠程調用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

屯门区| 英德市| 三原县| 辉南县| 商洛市| 海丰县| 屏南县| 高平市| 洛扎县| 庆元县| 大兴区| 垫江县| 祁门县| 衡水市| 连州市| 永寿县| 嘉荫县| 黔南| 三门县| 溧阳市| 建始县| 文水县| 仪征市| 淮滨县| 香格里拉县| 仪陇县| 望都县| 夹江县| 万全县| 怀柔区| 泌阳县| 浑源县| 大足县| 河津市| 北川| 宝应县| 庆城县| 南京市| 桂林市| 巴马| 慈溪市|