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)到本地?
相关文章
相关标签/搜索