在我們的日常開發中,經常會遇到這樣的問題--"我讓你做一件事情,但是你做得很慢,並不能夠立馬返回給我結果,害我一直在那兒等着你給我返回結果,什么都做不了"。
程序是自上而下順序執行的,很多時候后一步的操作依賴於前一步操作的返回結果,所以必須按照順序依次執行;如果我不想等,那我就需要把操作拆分解耦,解耦我可以做到,就是讓后面的操作不一定非要等到前面操作的完成,不是非要依賴於前面的返回結果,也就是我不用等你了。我們可以把耗時的操作,對整體結構非關鍵部分的操作異步執行。
可是異步執行完,你要通知我,對我說你幫我做好了啊。因為,事情做好了,不管什么結果,我還要接着處理一下啊,不是說異步我丟給你了我就不管了,我只是暫時沒空等你,我希望你在背后幫我完成,做好了你還是要跟我說的,然后我仍需要繼續處理的。可是問題是,你做好了怎么通知我呢?並且到時候你還在不在我都不知道,我收到你的通知怎么告訴你?
問題出來了,那么肯定要想辦法解決啊。首先要解決的就是--"你異步處理完,怎么通知我?",要解決這個問題很簡單--在我讓你異步處理的時候,告訴你一個地址,你處理完后就可以通過這個地址找到我,告訴我你的處理結果。然后問題又來了,你完成后,通過地址通知我,可是不知道我是否接收到,你就會一直通知我。這個問題就更加簡單了,我們約定一個字段,我給你返回特定字段,也就是告訴你我收到通知了,你就不要在通知我了。
上面的思路整清楚了,接下來就要詳細實現。(Java實現)
比如現在我要買一張火車票,我們選擇銀聯支付,支付完成后,我們會收到購票通知,也會收到銀聯給我們返回的扣款通知。這里面就用到了異步通知,在下單的時候,服務端請求銀聯的扣款接口,同時在接口告訴銀聯處理后返回結果通知地址,服務端收到銀聯的通知后,根據返回的支付結果判斷是否出票。
在這個購票過程中,我們需要注意的是--目前主流的服務端框架都是Spring cloud,我們告訴第三方的異步通知地址(其實就是我們的接口請求路徑),第三方處理結果通知到我們服務端,這個過程和客戶端請求接口是很像的。當時目前的框架中都會又一個gateway(網關),在網關內,我們都會進行驗簽、路由等操作,而客戶端和服務端進行交互的時候我們都會約定好驗簽、路由相關的數據或配置,當時和第三方對接時,我們是不可能將這些東西告訴他們的。
所以,在接收第三方異步通知的時候,我們需要考慮的首要事情就是--第三方處理的結果如何成功的通知到我們服務端內部。本地開發時可以按照我的上一篇文章《Mac配置內網穿透》配置本地ip的外網映射。正常的生產開發過程其實還涉及到另外一點--異步通知只能通知到外網地址,需要經過nginx轉發后到我們的程序中,因此還需要在服務器上配置nginx,使得通知能夠通過外網到我們內網服務器地址上(以后會介紹這一塊內容的)。
處理結果的通知順利進入我們程序后,我們還需要根據其返回的格式做處理,目前我對接的第三方異步通知返回的結果各種各樣--JsonObject ,HttpServletRequest...,我們需要根據返回的數據格式合理的選擇接收對象,當然,如果覺得麻煩,也可以自定義注解,然后將返回格式統一成自己喜歡的格式。個人比較喜歡使用HttpServletRequest接收,處理起來方便一點。最后,我們接收到通知之后,需要按照約定,返回第三方所需的字段,自此,整個異步通知過程就結束了。
但是,對於我們服務端而言,返回信息的處理才剛開始,我們需要對異步通知的內容進行驗簽、解密等操作,確認我們接收到的數據是合法、正確的。