MobileFirst 8:存储数据时遇到意外错误

Posted

技术标签:

【中文标题】MobileFirst 8:存储数据时遇到意外错误【英文标题】:MobileFirst 8 : Unexpected error encountered while storing data 【发布时间】:2017-11-13 15:42:35 【问题描述】:

我们正在使用 UserAuthenticationSecurityCheck 对用户进行身份验证。

如果验证成功,MFP服务器将存储用户属性。

public class AuthSecurityCheck extends UserAuthenticationSecurityCheck 

    static Logger logger = Logger.getLogger(AuthSecurityCheck.class.getName());

    private String userId, displayName;
    private JSONObject attrObject;

    private String errorMessage;

    @Override
    protected AuthenticatedUser createUser() 
        Map<String, Object> userAttrsMap = new HashMap<String, Object>();
        userAttrsMap.put("attributes",attrObject); 
        return new AuthenticatedUser(userId, displayName, this.getName(), userAttrsMap);
    
...

但是如果我们存储更大的数据(当 userAttrsMap 足够大时),我们会得到 500 错误。

errorMsg:存储数据时遇到意外错误

错误如下图:

完整源代码在 Github:https://github.com/DannyYang/PMR_CreateUserStoredLargeData

多功能一体机版本:

cordova-plugin-mfp 8.0.2017102115 多功能一体机开发套件:8.0.0.00-20171024-064640

【问题讨论】:

您能说一下您尝试存储的数据有多大吗? 不太清楚数据的确切大小,但是我们在这段代码中使用 largeJSONString 会得到 500 错误(code link) 【参考方案1】:

由于您在 AuthenticatedUser 对象中持有的数据的大小以及因此 Securitycheck 的状态而发生此问题。

MFP 运行时将安全检查的状态与所有属性一起保存到属性存储中。这涉及序列化安全检查状态并将其持久化到数据库。对于大对象(您拥有的自定义映射),此持久性操作失败并以事务回滚结束。发生这种情况是因为您尝试持久化的数据太大并且超出了分配的大小。

SecurityCheck 的设计考虑是将其用于安全检查(验证)并创建身份对象。在您的安全检查实施中,您有以下内容:

//Here the large data is assigned to the variable.
attrObject = JSONObject.parse(largeJSONString);

//This data is set into the AuthenticatedUser object.
Map<String, Object> userAttrsMap = new HashMap<String, Object>();
userAttrsMap.put("attributes",attrObject);
return new AuthenticatedUser(userId, displayName, this.getName(), userAttrsMap);

在这种情况下,这些大数据成为安全检查本身的一部分,并将被序列化并尝试持久化到属性存储中。当此数据不适合列时,事务将回滚并将错误条件传播给最终用户。因此,您看到的错误消息 - “存储数据时发生意外错误”。启用详细跟踪将在服务器跟踪日志中指出问题的实际原因。

无论如何,在生产系统中根本不推荐这种方法,因为:

a) 来自客户端的每个请求到达服务器都会经过安全自检,这将涉及服务器加载、检查和更新安全检查的状态。在承受重负载(生产)的系统上,这可能并且将会产生性能成本。该过程涉及对数据进行序列化并稍后对其进行反序列化。在分布式拓扑(集群或农场)中,请求可能最终出现在任何节点中,这些节点必须加载并稍后将安全检查的状态保存到存储中。所有这些都会影响系统的性能。

b) 在成功认证结束时,AuthenticatedUser 对象被传播到客户端应用程序,指示登录流程完成。即使将 SecurityCheck 状态成功存储在属性存储(带有大数据)中,通过网络传输大量有效负载只是为了指示成功登录也会适得其反。对于最终用户来说,自从他们输入凭据后,它可能看起来好像什么也没发生,而指示成功的数据仍在下载中。

c) 在重负载下,服务器将受到上述 a) 和 b) 的压力。

您应该考虑减少在经过身份验证的用户对象中传播到客户端的数据。保持 AuthenticatedUser 对象中的数据最少。相反,您应该将获取大量数据的工作转移到资源适配器上,成功登录后即可访问。

【讨论】:

以上是关于MobileFirst 8:存储数据时遇到意外错误的主要内容,如果未能解决你的问题,请参考以下文章

MobileFirst Platform CLI 无法使用 JSON 存储构建 xcode 7.2 项目

Drupal的8 - 该网站遇到意外的错误。

提取操作中的 BigQuery 错误:错误处理作业意外。请再试一次

MobileFirst 7.1 Progurd 获取错误返回代码 1

MobileFirst 7.1,Window 8 通用应用程序的 nativeResources 错误

Xcode 8.2,Swift 编译器错误:错误:意外的输入文件