在线协同办公(office在线预览解决方案)

在构建业务系统的时候,经常会涉及到对附件的支持,继而又会引申出对附件在线预览、在线编辑、多人协同编辑等种种能力的诉求。

在线协同办公(office在线预览解决方案)

对于文件的存储管理,直接采用了公司内部私有云的OSS文件托管服务进行实现,实现起来比较简单。文件在线预览与Office文件在线编辑的能力,则选用相关的开源方案来实现。经过一番对比分析,最终选定了两个开源组件:

OnlyOffice用于支持office文档的在线协同编辑、预览等能力。kkFileView用于支持常规文档的在线预览能力

选型确定之后,就是如何与现有业务系统进行整合了。因为开源组件往往都是通用逻辑设计的,而业务系统的逻辑又各不相同,所以如何去整合并方便扩展出自己需要的定制化能力,成了下一步摆在眼前需要处理的问题。

在线协同办公(office在线预览解决方案) 整体适配对接策略

为了保证业务系统的稳定,避免业务系统中强耦合文件预览相关的开源模块,同时也为了方便业务层的调用,所以规划构建一个统一的入口代理转接服务,统一由此服务对业务系统提供预览与在线编辑相关能力,对业务层屏蔽掉底层具体的开源方案整合逻辑。这样的好处是,不管预览与编辑服务这边如何调整,甚至后面更换实现方案,都不会影响到业务层的调用逻辑。

在线协同办公(office在线预览解决方案) 整合OnlyOffice实现Office文档在线预览与编辑让业务代码无耦合的方式使用预览能力

OnlyOffice作为一个负责office在线预览的功能组件,其提供了一个JS API方法。具体使用的时候,需要在html页面中引用其提供的JS文件并调用对应API方法将请求参数传递给OnlyOffice进行处理。这些请求参数里面,既含有对文档在线显示相关的一些属性约定,还包含一个重要的参数,也即需要操作的目标Office文件的获取地址url。在OnlyOffice收到请求之后,需要去给定的地址下载目标Office文件,然后内部解析处理之后,按照请求参数的指定信息,渲染展示到界面上。

在线协同办公(office在线预览解决方案)

在实际的系统规划中,为了便于后续版本升级维护,以及避免OnlyOffice强耦合到各个业务系统中,所以不太倾向于让前端界面直接去集成与调用OnlyOffice相关的JS文件。

所以在实施的时候,在服务端的文件预览编辑服务中进行了封装,对外提供服务端API接口,服务端自带一个简单HTML界面(基于SpringBoot Thymeleaf实现),业务请求对应服务端提供的独立html界面,并在界面中完成使用OnlyOffice的JS api请求的操作。

具体步骤说明如下:

对外提供服务端HttpGet接口,借助Thymeleaf框架,界面跳转出现对应html界面 在线协同办公(office在线预览解决方案) 在独立的JS文件中,接收从JAVA逻辑中传入的参数信息,然后转换封装为OnlyOffice需要的格式,然后调用OnlyOffice的API接口发送请求 在线协同办公(office在线预览解决方案)

对上述步骤解释如下:

在线协同办公(office在线预览解决方案)

也即当用户关闭文档编辑界面之后,会触发文档的保存事件,回调callback接口,将保存事件推送给服务端,并告知服务端变更后的文档地址,这样服务端可以从给定的地址下载变更后的文档,然后更新到自己的存储中。

结合到我们具体的项目使用中,其具体的交互过程展开阐述下,就是下图的过程:

在线协同办公(office在线预览解决方案) OnlyOffice集群化部署

为了保障预览服务的可靠,在生产环境上规划实施集群化部署。 从上一章的阐述中,我们知道OnlyOffice的功能实现严重依赖单机本地的缓存数据信息,在集群部署的场景下,过度依赖本地缓存的弊端就显现出来了。

集群化部署,本以为会很简单,直接部署多个docker节点,然后使用Nginx做一下反向代理以及负载均衡不就可以了嘛?但是实际实施的时候却发现在协同编辑场景下出现了预期之外的问题。因为多人在线协同编辑的能力要求所有人对某篇文档的编辑请求都在同一个OnlyOffice服务节点上才行,而Nginx随机负载分发,会导致同一篇文档的编辑请求分发到不同节点上,这样就会导致编辑的内容相互覆盖。

在线协同办公(office在线预览解决方案)

因为用户的请求并不是直接打到OnlyOffice地址上的,而是先打到文件预览服务中,然后由文件预览服务经过某种策略处理后,再将请求重定向到OnlyOffice服务上进行文档操作的,所以这里我们可以通过增加一个简单的分发策略,保证对同一个文档的所有的请求操作,都被分发到固定的一个OnlyOffice服务上处理即可。

这里的分发策略,考虑有2种方案:

根据每个文档的唯一ID计算hashcode值,然后与OnlyOffice节点数取余,决定每个文档分别有哪个OnlyOffice服务处理。此方案实现起来最为简单,但是存在的问题也不少(比如节点新增或者删除的时候存在问题,需要上一致性hash算法)。通过随机分发 Redis记住文档与节点映射的方式,先随机选择一个节点,然后记录下此文件与OnlyOffice节点之间的映射关系,然后后面对此文件的请求始终分发到该OnlyOffice节点上。 在线协同办公(office在线预览解决方案)

这里我们实现的时候采用了第2种方案,借助redis缓存来实现,整体策略如上图示意。具体实现的时候对缓存数据增加了一定的过期与续期策略,既保证同一文档请求分发到同一节点,又保证一定时间之后文档分发缓存消失,可以重新分配空闲的OnlyOffice服务器(因为开源版本OnlyOffice只支持最大20并发量,所以可以在此层级进行分配调整)。

具体代码逻辑如下:

public NodeServerInfo getOnlyOfficeServer(String fileUniqueId) { // 从redis中先看下是否有分配过,如果有,继续使用 NodeServerInfo existServer = redisCacheOperateService.getExistOnlyOfficeServerByFileId(fileUniqueId); if (existServer != null) { if (serverAvailable(existServer)) { // 延长有效期 redisCacheOperateService.renewalOnlyOfficeMapExpireDays(fileUniqueId, onlyOfficeServerCacheDays); return existServer; } else { // 删除无效的缓存 redisCacheOperateService.deleteExistOnlyOfficeServerMapping(fileUniqueId); } } // 重新选择一个可用的server NodeServerInfo nodeServerInfo = chooseAvaliableServer(); // 将文件与服务器之间映射关系存储redis中 redisCacheOperateService.saveFileAndOnlyOfficeServerMapping(fileUniqueId, nodeServerInfo, onlyOfficeServerCacheDays); return nodeServerInfo;}

至此呢,集群化部署的问题解决,可用性上得到的有效保证。并且通过定期探测机制,及时将不可用的OnlyOffice节点从候选列表中剔除掉,保证了请求始终在可用节点上,有效避免了单点问题的出现,也一定程度上缓解单个节点的压力(社区版本同时仅支持20并发数、通过一定策略可以分散不同文件的请求到不同节点上)。

在线协同办公(office在线预览解决方案) 两者融合:缓解OnlyOffice加载慢问题

基于前面整体的规划策略,Office文档使用OnlyOffice进行预览操作,非Office文档则由kkFileView实现预览操作(业务调用方无感知,都是统一一个url地址)。开发完成部署上线之后,功能也都一切正常。

但是自从上线之后,用户普遍吐槽在线Office文档预览的加载速度太慢,难以忍受。因为首次使用的时候OnlyOffice会在浏览器本地加载一个30M左右的缓存数据,而我们的服务部署在公司内网机房里面,通过多层代理开放到公网中,用户在公司办公网络中访问的时候,相当于绕了多层网络代理,且由于公司办公网络对客户端单机下行速率有限制,导致这个第一次加载缓存数据的时间需要10-15s左右才能加载出文件。

在线协同办公(office在线预览解决方案)

当业务系统中的文件内容有新增或者变更的时候,具体的异步转换处理的时序操作逻辑如下:

在线协同办公(office在线预览解决方案)

本文来自作者:路逸轿运-,不代表小新网立场!

转载请注明:https://www.xiaoxinys.cn/597510.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。