本篇參考:https://resources.docs.salesforce.com/sfdc/pdf/integration_patterns_and_practices.pdf
我們在專案中,經常會遇見一個自定義頁面的按鈕或者一個 quick action點選,或者頁面初始化,會對外部系統做一個 callout,然後獲取對方的資料以後做一些邏輯進行操作,這種場景實在是太常見了。這種場景通常有幾個特點:
- 實時性
- 資料量不大
- 對端響應快
當然可能還有很多的特點,這裡不多描述。salesforce針對這種我們常用的場景整理成一個整合模式,名稱為: 遠端程式呼叫--請求和響應。那麼請求和響應的詳細描述是什麼,有哪些限制,針對這種整合模式有哪些解決方案,解決方案的適配度如何呢?我們接下來慢慢的描述。
一. 上下文
其實通過上面的描述中我們大概已經能聯想到我們實際的應用的上下文。這裡還是拿出來一個官方的例子去更好的進行一下描述。
您可以使用Salesforce跟蹤銷售線索、管理銷售渠道、建立銷售機會,並捕獲將銷售線索轉換為客戶的訂單詳細資訊。但是,Salesforce系統不包含或處理訂單。在Salesforce中捕獲訂單詳細資訊後,將在遠端系統中建立訂單,該系統將管理訂單直至結束。
當您實現此模式時,Salesforce呼叫遠端系統來建立訂單,然後等待成功完成。如果成功,遠端系統會同步回覆訂單狀態和訂單號。作為同一個transaction的一部分,Salesforce在內部更新訂單號和狀態。訂單號用作遠端系統後續更新的外來鍵(External Id)。
通過這個描述,我們就可以清楚了這個case是Opportunity Close Won建立訂單,訂單號需要維護到外部系統,需要同步的call外部系統然後作為外來鍵更新到SF的訂單的記錄。
二. 問題和考慮因素
問題: 當一個事件從salesforce觸發時,如何在遠端系統中啟動(初始化)流程,將所需資訊傳遞給該流程,從遠端系統接收response,然後使用該響應資料在Salesforce中進行更新?
考慮因素:在基於此模式應用解決方案時需要考慮以下因素。
- 對遠端系統的呼叫是否要求Salesforce在response回來之前等待響應?對遠端系統的呼叫是同步請求-應答還是非同步請求?
- 如果對遠端系統的呼叫是同步的,Salesforce是否必須將response作為與初始呼叫相同的事務的一部分進行處理?
- 訊息大小是小還是大?
- 整合是否基於特定事件的發生,例如Salesforce使用者介面中的按鈕點選,或基於DML的事件?
- 遠端端點(endpoint)是否能夠以低延遲響應請求?有多少使用者可能在高峰期執行此事務?
這些考慮因素很重要,會影響我們的解決方案的使用以及影響到我們當前的模式是否適用於當前的case。所以針對上述的考慮因素一定要慎重地思考。
三. 解決方案
針對此種解決方案 Salesforce提供了5種解決方案,不同的解決方案適用於不同的考慮因素點,當然有一個列表是適配度,描述當前是最好的方案還是次優的方案,當然,這個也不一定是絕對的,我們考慮整合方案的時候,除了考慮這種 best practice以外,還需要考慮 effort以及是否擁有 resource以及很多外部的因素。
解決方案 | 適配度 | 詳細說明 |
增強的外部服務來呼叫來呼叫一個REST API | BEST |
增強的外部服務允許我們以宣告方式呼叫外部託管的服務(不需要程式碼)。當滿足以下條件時,最好使用此功能特性: •外部託管服務是RESTful服務,並且這個定義在OpenAPI 2.0 JSON格式下可用。 •請求和響應定義包含基礎的資料型別,如boolean、datetime、double、integer, String或Array(正規化內容為基礎型別)。 巢狀物件(Nested Object)型別,並且在HTTP request裡傳送例如headers的引數也是支援的。 •這個Transaction可以從flow呼叫 |
Salesforce Lightning-元件或頁面以同步方式啟動 Apex SOAP或REST呼叫。 Salesforce classic-自定義 Visualforce頁面或按鈕以同步方式啟動 Apex SOAP呼叫。 如果遠端端點(endpoint)具有高延遲響應的風險,則建議使用非同步呼叫+回撥函式來避免達到同步 Government limitation. |
BEST |
Salesforce使您能夠使用WSDL並生成代理Apex Class。此類提供呼叫遠端服務所需的邏輯。 Salesforce還允許您使用標準的GET、POST、PUT和DELETE方法呼叫HTTP(REST)服務 在Visualforce頁或Lightning頁上由使用者啟動的操作隨後呼叫Apex Controller的操作,該操作隨後執行上述說的代理Apex類以執行遠端呼叫。 這種場景在Salesforce app中需要Visualforce頁面和Lightning頁面自定製。
|
自定義Visualforce頁面或按鈕以同步方式啟動Apex HTTP callout | BEST |
Salesforce使您能夠使用標準的GET、POST、PUT和DELETE方法呼叫HTTP服務。可以使用幾個HTTP類與RESTful服務整合。也可以通過手動構造SOAP訊息來整合到基於SOAP的服務。不建議使用後者,因為Salesforce可以使用wsdl生成代理類。 Visualforce頁上的使用者啟動的操作隨後呼叫Apex Controller的action,該操作隨後執行此代理Apex類以執行遠端呼叫。Visualforce頁面需要在Salesforce APP中自定義 |
Salesforce資料更改以後通過trigger以同步方式呼叫一個 apex SOAP或者一個 http callout |
Suboptimal 次優 |
可以使用Apex Trigger根據資料更改執行自動化操作。 Apex代理類可以通過使用Apex Trigger作為DML操作的結果來執行。但是,從Trigger上下文中發出的所有呼叫都必須從時間初始化時非同步執行。因此,不建議將此解決方案用於此整合問題。此解決方案更適合於遠端程式呼叫Fire-and-Forget模式。 |
Apex Batch Job以同步方式去執行 Apex SOAP或者 Http Callout |
Suboptimal 次優 |
可以從批處理作業呼叫遠端系統。此解決方案允許批處理遠端程式執行和處理Salesforce中遠端系統的響應。但是,給定的批處理對呼叫數有限制。可能觸發government limitation 給定的批處理執行可以執行多個事務上下文(通常以200條記錄為間隔)。每個事務上下文都會重置調控器限制。 |
針對次優的方法我們通常不建議使用,除非針對這個case特別特殊。針對這五種解決方案,再擴充套件一下第二點中的非同步呼叫方法。
先說一個我們最簡單的一個 callout的demo。 下面的這個程式碼是最簡單的一個 callout操作,通過標準的 httprequest 的get方法獲取指定 endpoint的內容。
// Instantiate a new http object Http h = new Http(); // Instantiate a new HTTP request, specify the method (GET) as well as the endpoint HttpRequest req = new HttpRequest(); req.setEndpoint(url); req.setMethod('GET'); // Send the request, and return a response HttpResponse res = h.send(req); return res.getBody();
這種程式碼和我們實際的場景可能也就缺少一個OAuth的邏輯,剩下的如出一轍。那麼如果遠端系統的 endpoint在高峰期處理的時候沒法達到低延遲響應的情況下,前端很容易假死,也很容易超時。這種情況我們就建議使用非同步的 + callback方式來處理這種 高延遲的case。下面是官方推薦的程式碼:
public Object startRequest() { // Create continuation with a timeout Continuation con = new Continuation(40); // Set callback method con.continuationMethod='processResponse'; // Create callout request HttpRequest req = new HttpRequest(); req.setMethod('GET'); req.setEndpoint(LONG_RUNNING_SERVICE_URL); // Add callout request to continuation this.requestLabel = con.addHttpRequest(req); // Return the continuation return con; } // Callback method public Object processResponse() { // Get the response by using the unique label HttpResponse response = Continuation.getResponse(this.requestLabel); // Set the result variable that is displayed on the Visualforce page this.result = response.getBody(); // Return null to re-render the original Visualforce page return null; }
visualforce的呼叫demo可參考:https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_continuation_overview.htm
lwc的呼叫demo可參考:Salesforce LWC學習(十四) Continuation進行非同步callout獲取資料
四. 流程草圖
1. 在Visualforce Page或者 Lightning中進行了某個操作,比如點選了某個按鈕
2. 瀏覽器(如果是Lightning元件,則通過客戶端控制器)執行HTTP POST,該HTTP POST反過來對相應的Apex Controller執行操作(執行某個方法)。
3. controller對遠端web service進行實際的呼叫。
4. 來自遠端系統的響應返回到Apex Controller。Controller處理response,根據需要更新Salesforce中的資料,並reRender頁面操作。
五. 其他關鍵點
1. Error Handling考慮: 當我們在進行整體設計時,我們需要考慮錯誤處理以及資料恢復的策略。
• Error Handling:當error發生時(異常或者錯誤的code),呼叫者管理錯誤處理。比如頁面展示錯誤資訊或者跳轉到共用頁面等等。
• Recovery:呼叫者接收到成功的response以後才可以將資料commit到資料庫。如果失敗(連線失敗等)有必要可以重試連線
2. 冪等性(Idempotent)考慮:在程式設計中一個冪等操作的特點是其任意多次執行所產生的影響均與一次執行的影響相同。冪等函式,或冪等方法,是指可以使用相同引數重複執行,並能獲得相同結果的函式。這些函式不會影響系統狀態,也不用擔心重複執行會對系統造成改變。
確保所呼叫的遠端過程是冪等的是很重要的。幾乎不可能保證Salesforce只呼叫一次,特別是當呼叫是由使用者介面事件觸發時。即使Salesforce發出一個呼叫,也不能保證其他程式(例如中介軟體)也會這樣做。構造冪等接收器的最典型方法是: 它基於使用者傳送的唯一訊息識別符號(unique key)來跟蹤重複項(duplicate records)。Apex web service或REST必須自定義去傳送唯一的訊息ID。此外,在遠端系統中建立記錄的操作必須在插入之前檢查重複項,我們可以通過從Salesforce傳遞唯一的記錄ID進行檢查。如果遠端系統中存在該記錄,請更新該記錄。在salesforce的世界裡面很好理解,就是 upsert操作,我們需要建立一個外來鍵,這個外來鍵設定唯一即可。
3. 安全性考慮: 當我們呼叫遠端系統失敗以後,首先需要考慮 remote site setting是否配置了這個站點的URL,其次看一下CSP 是否配置。這兩個是專案中大部分場景都需要配置的。除此以外,對遠端系統的任何呼叫都必須保持請求的機密性、完整性和可用性。當我們在這種模式中使用apexsoap和HTTP呼叫時,我們需要考慮以下:
•預設情況下啟用單向SSL,但雙向SSL也要被self-signed 和 CA-signed 證書支援,以保持客戶端和伺服器的真實性。
•Salesforce目前不支援WS-Security。
在必要時,考慮使用單向加密或數字簽名,使用Apex Crypto類方法來確保請求完整性。
•必須通過實施適當的防火牆機制來保護遠端系統。
4. 及時性以及使用者友好性:在這種模式中,及時性非常重要。通常:
•請求通常從使用者介面呼叫,因此該過程不能讓使用者等待(使用者期望時間最多不能超過10秒,否則會很煩的)。
•Salesforce對來自Apex的call out最多可以配置到120秒的 timeout
•及時完成遠端流程,在Salesforce超時限制和使用者期望範圍內完成。
•外部呼叫受Apex synchronous transaction governor限制,因此應注意降低例項化10個以上事務(每個事務執行時間超過5秒)的風險。
官方的介紹:If more transactions are started while the 10 long-running transactions are still running, they’re denied. HTTP callout processing time isn’t included when calculating this limit.
除了確保外部endpoint的效能外,減輕超時風險的選項還包括
–將callout的超時設定為5秒
–在Visualforce或Lightning元件中使用continuation來處理長時間執行的事務
補充知識:Apex Continuations是Salesforce平臺提供的一種機制,允許您向外部Web服務發出非同步長時間執行的請求。該服務支援對SOAP或restweb服務的呼叫,最大超時為120秒(而標準同步呼叫為10秒)。
5. 資料量考慮:此模式主要用於小容量的實時活動,因為Apex呼叫解決方案的超時值較小,請求或響應的大小也最大。當批處理的場景,包含資料負載的情況下不要使用此模式。
6. 遠端系統的EndPoint 能力和標準支援:針對 endpoint的需要的能力和標準的服務取決於我們選擇的哪種解決方案
六. 常見考題
Question: Universal Containers is a global financial company that sells financial products and services including, bank accounts, loans, and insurance. UC uses Salesforce Service cloud to service their customer via calls, live chat. The support agents would open bank accounts on the spot for customers who are inquiring about UC bank accounts. UC Core banking system is the system of record for bank accounts and all accounts opened in salesforce have to be synced in real-time to the core banking system. Support agents need to inform the customers with the newly created bank account ID which has to be generated from the core banking system. Which integration pattern is recommended for this use case? Answer: Use request and reply. Question: Universal Containers wants to gather information from a third-party application to update shipping information for an order inside Salesforce. A salesperson could trigger an update and the user interface would refresh with the current status. Which are two recommended options for this when utilizing a Remote Process Invocation-Request and Reply pattern? Answer: A custom Visualforce page or button that initiates an Apex REST callout in a synchronous manner. A custom Visualforce page or button that initiates an Apex SOAP callout in a synchronous manner.
總結:篇中主要介紹了遠端程式呼叫--請求和響應的整合模式,這個在實際專案場景是最常用到的,所以大家理解也相對方便。篇中有錯誤歡迎指出,有不懂歡迎留言。