Forge雲服務的本地化經驗總結與優化實戰

Autodesk Forge API服務的數據中心是基於AWS的海外服務搭建的,於是,因爲衆所周知的緣由,國內部分地區(依ISP而異)訪問Forge雲端口的速度會受到必定程度的影響。特別是Forge Viewer瀏覽大型模型,以及對反饋時間比較銘感且涉及關鍵業務的工做流等諸多場景,對於服務端的存取效率有者較高要求。因此,如何處理好雲端數據的訪問與協同工做流,包括離線加載、雲端緩存等方案的最佳實踐,是你們一直關注的問題。今天,咱們就總結一下幾種常見的實現方式,以期實現流程與性能的優化。css

離線模型加載

往期有這兩篇文章可供參考:離線模型的下載和部署Viewer模型加載本地離線緩存實戰,該文介紹了使用新近瀏覽器原生的Service-Worker和Cache API緩存模型的方案。react

可是在Viewer模型加載本地離線緩存實戰實例代碼中,針對Viewer庫和線上模型資源自己的緩存是經過靜態路徑實現的:git

//https://github.com/petrbroz/forge-disconnected/blob/master/public/service-worker.js
const STATIC_URLS = [
    'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/style.css',
    'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/viewer3D.js',
    'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/lmvworker.js',
    'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/res/locales/en/allstrings.json',
    'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/res/environments/SharpHighlights_irr.logluv.dds',
    'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/res/environments/SharpHighlights_mipdrop.logluv.dds',
...

該實現存在幾點問題:github

  • 待緩存的靜態連接是根據展現用的模型所需配置的,模型更換後靜態連接也須要手動更新
  • 一次性緩存了全部實例模型所需的資源,超配且沒必要要,影響加載性能
  • Viewer庫版本一旦更新,需手動更新緩存的靜態資源連接

所以,在咱們後續的實戰Forge Viewer漸進應用一文中,採用先註冊完成緩存任務的Service Worker再加載Viewer庫的流程。如此一來,Viewer庫依賴與模型資源的加載請求也會自動獲得緩存,無需手動干預緩存過程,大幅增進代碼的可維護性:web

navigator.serviceWorker.register('/service-worker.js').then((registration) => {
        let script = document.createElement('script');
        script.onload = function () {
            const viewer = new Autodesk.Viewing.Private.GuiViewer3D(myViewerDiv);

            Autodesk.Viewing.Initializer(options, () => {

                ... //按需以在線或離線模式初始化Viewer並加載模型

                viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, () => {

                    const channel = new MessageChannel();
                    channel.port1.onmessage = (event) => console.log(event);

                    navigator.serviceWorker.controller.postMessage({ operation: 'EXECUTE_CACHE' }, [channel.port2]);  // 模型加載完成,該模型所需資源已做記錄,遂向ServiceWorker發送消息,開始緩存所需資源
                    })
            });
        };
        script.src = "https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/viewer3D.min.js";
        document.head.appendChild(script) //待Worker註冊完畢開始做動後再載入Viewer,實現Viewer庫及其依賴的自動緩存

})

在線模型加載

  • 建議參考下文的數據服務的優化,爲Viewer的加載提供代理,增進國內訪問的速度。
  • 在Viewer上實現代理的方法主要經過Autodesk.Viewing.endpoint.setEndpointAndApi來重定向獲取模型數據的URL:
Autodesk.Viewing.Initializer(options, function(){
  Autodesk.Viewing.endpoint.setEndpointAndApi('https://yourhostname/your/proxy/service/path')
...

隨後在你的服務端將Viewer發來的請求代理至Forge API雲服務https://developer.api.autodesk.com便可,注意保留Viewer原生請求的路徑,這裏還能夠根據Forge服務上的模型所在的數據中心按需爲轉發目的地做進一步設置,詳見:BIM 360 Docs API在操做歐洲數據中心內容的一些調整spring

  • 亦可設置Viewer發送的請求頭,以AOP的設計模式實現本身的訪問控制等邏輯:
Autodesk.Viewing.Initializer(options, function(){
          Autodesk.Viewing.endpoint.HTTP_REQUEST_HEADERS = {'X-My-Custom-Header':'233', ...}
...

固然,咱們還需在本身的服務端設置預檢請求(Pre-flight)的返回中Access-Control-Allow-Headers的請求頭,容許以前爲Viewer設置的請求頭不被瀏覽器的跨域安全機制攔截。apache

  • 固然,你們熟悉的Viewer原生的getAccessToken等都是依舊有效的。

Android

  • 如本地的模型,因爲Viewer不支持基於File協議的模型加載,須要經過重寫WebView並攔截http請求,返回靜態資源。
webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("http://my/path/to/svf")) {
            // 返回靜態模型資源
            return true;
        }
    }
});
  • Viewer加載模型的URL維持http協議便可

iOS

  • 同理,iOS的實現思路是:
func webView(_ webView: WKWebView, decidePolicyFor
       navigationAction: WKNavigationAction,
       decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {


    if navigationAction.navigationType == .linkActivated {
        if webView.url!.absoluteString == "http://path/to/my/static/svf" {
            //返回靜態模型資源
            return
        }
    }
    decisionHandler(.allow)
}

跨平臺

針對跨平臺的框架,不建議使用搭設本地靜態服務器的方式克服Viewer不支持File協議的問題,由於不少Android ROM處於安全考量已經屏蔽了該特性。json

  • React Native框架: 推薦使用react-native-webview,再經過onShouldStartLoadWithRequest攔截並返回靜態模型:
onShouldStartLoadWithRequest = (event) => {
        var url = event.url;
        if (url && url.length) {
            if (url.indexOf('http://my/path/to/svf') == 0) {
                //返回靜態模型資源
            }
        }
        return true;
    };

數據服務的優化

  • 建議自建雲服務訪問Forge API或部署代理,以便實現諸多優化事項,如緩存(可使用http-cache等庫),如集中統籌Access Token,避免爲每一個客戶端服務請求逐一做Forge認證,提高效率的同時加強Forge App密鑰和Token的安全性,亦便於實現高度自定的工做流。
  • 建議搭建位於海外機房的節點做代理,地理位置推薦香港或接入電信CN2線路的北美機房,訪問速度會有不小提高,詳情能夠自行搜索瞭解。
  • 亦可搭建本身的雲存儲,便於實現高度自定義的工做流與高規格的安全機制,能夠經過等Cephminio等技術實現。
  • 活用Forge Webhook API,實現基於事件回調的異步工做流,節省資源的同時提升可靠性,詳情能夠參考這些樣例

Q&A

Q:可否避免將模型上傳到Forge數據平臺,直接進行轉換?
  • A:Forge服務只能轉換存儲在Forge數據平臺的模型,轉換功能沒法做本地部署,如模型涉密,能夠再轉換完成後當即從Forge數據平臺刪除,Forge對用戶數據不做任何備案。
Q:能否實現Viewer的徹底本地化?即將Viewer庫和模型渲染資源下載到本地?
  • A:Forge Viewer使用許可禁止將Viewer庫下載至本地加載,亦禁止對代碼進行修改
Q: 那如何修改Viewer源代碼?我有擴展原生邏輯的需求。
  • A: 可使用Piggyback的方式,即在本身的邏輯中動態的替換、擴展Viewer自身的函數
Q: 針對離線加載模型的場景,如何有效的提取Viewer可讀的模型文件(SVF)到本地?
相關文章
相關標籤/搜索