REST 是用于将外部应用程序与平台集成的强大工具。您从一开始没有意识到这些方面,REST 的某些方面可能会影响应用程序的性能。本指南将帮助您克服这些障碍,以帮助您构建功能强大且响应迅速的 REST 应用程序。
有 2 个主要的 REST 特定因素可能会在应用程序中造成瓶颈。首先是一个简单的事实,即 REST 基于通过 HTTP(S) 发出请求。这意味着您不仅依赖于平台来处理您的请求,还必须通过网络将数据发送到平台或从平台接收数据。此外,您请求的数据越多,通过网络发送的有效负载就越大,这也可能降低应用程序的速度。
同步与异步
有两种使用异步模式的方法,一种特定于服务器端交互,另一种与接口响应性相关。
服务器端代码的异步模式和实践
以下内容适用于使用 .NET 编写集成。如果您使用的是其他技术,请参阅该技术文档以获取类似的功能。
在 .NET 4.5 中引入了异步编程,这大大减少了创建异步代码所需的工作量。该模型已扩展到常见的类,例如 HttpClient,这些类在通过 HTTP(S) 与 REST 通信时是关键。从本质上讲,此模式允许关键执行方法(特别是基于通信的方法)在进程外发生,以便您可以执行它们,但不需等待它们完成才能继续执行工作。通过这种方式,您可以处理不相关的逻辑或不相互依赖且独立的后台请求。实现此类模式的详细信息已超出了本文的范围,但您可以通过查看 MSDN 文档 来阅读有关其工作原理的信息。
如果您使用的是 REST SDK,则它已有基于异步/任务的方法可供您使用。
用户界面的异步模式
对于应用程序来说,可能发生的最糟糕的事情是,当用户在等待页面加载不合理的时间时,可能会遇到这种情况。如果您在加载页面期间发出多个请求,则可能会发生这种情况。在设计应用程序时,您应该在加载页面时加载最少量的有用信息(可能什么都没有),然后通过 javascript 异步加载辅助信息。在 Web 设计的术语是 AJAX(异步Javascript和XML)。例如,如果您有一个列出论坛主题的页面,则可以考虑先仅加载论坛信息,然后在页面中使用 Javascript 提供信息,以便它可以加载论坛主题。通过这种方式,您可以立即向用户提供有关论坛的信息,但在事后才加载主题,以便您可以向用户提供页面仍在工作的反馈(spinner 或加载某种动画)。这种做法在平台界面的许多地方也都使用了,“动态”就是一个重要的例子。列出“动态”是一项代价高昂的操作,因此我们在页面加载后异步加载它们。
您需要记住,出于安全原因,javascript 仅允许您在同一域上发出请求,而无需启用 CORS(跨源资源共享)或使用域上代理(如自定义 http 处理程序(.net)。您可以在管理>Integration->CORS 中为您的平台启用 CORS,但如果您还不熟悉 CORS,请务必了解有关 CORS 的详细信息,以便了解任何潜在的安全风险。如果选择编写代理并且使用的是 .NET,则还可以使用前面讨论的在服务器端实现的异步编程模式。
批处理
如果必须一次发出多个请求,并且异步不是一个选项,则可以使用 Batch REST 端点在单个 HTTP 调用中叠加所有这些请求。此单个调用将在服务器上处理中包含多子请求,而不是为每个子请求发出网络请求。但是,您在这里也应该小心,因为当您将子请求添加到批处理请求时,您将增加请求和您将收到的响应的大小。
控制 HTTP 有效负载
除了简单地限制您的请求并小心批处理之外,您还可以通过其他一些方式控制从平台返回的有效负载。您还可以返回不同类型的数据,例如预先格式化的 html。有4种主要方法可以管理有效负载,有些确实需要不同程度的额外开发工作,而另一些则可以自动使用,或者只需对请求本身进行简单的更改即可使用。
分页
这仅适用于 LIST 请求,或对数据集的请求,而不是单个项目的请求。大多数 LIST 请求都是分页的集合,因此您不一定要获得所请求集合中的所有项目。您得到的是集合中的当前页面、每个页面中的项目数以及整个数据集的总项目数。下面是用户列表端点中的示例:
{ "PageSize": 10, "PageIndex": 0, "TotalCount": 2345, "Users": [...] }
或者 XML
<Response> <Info /> <Warnings /> <Errors /> <Users PageSize="10" PageIndex="0" TotalCount="2345"> ..... </Users> </Response>
使用此信息,您可以在用户界面中创建分页。创建分页超出了本主题的范围,但此信息足以开发自定义分页或可能查看要使用的第三方库。重要的是分页限制了有效负载大小。REST 允许您将页面大小设置为最大 100,因此,如果您有 101 个或更多项目的列表,则最小值为 2 页。如果您尝试请求超过 100,则默认为 100。如果未指定页面大小,则默认情况下为 20。
在运行并将页面大小设置为 100 或接受默认值之前,请先了解响应的大小。最简单的思考方法是“总大小 = 1 个对象的大小 * 最小页面大小,这是假设大小相等的对象,但情况并非如此。如果您查看单个用户 REST 请求的示例响应,您可以看到这可能是大量的数据。还要考虑您的实际需求。是否真的有必要立即在列表中显示20篇博客文章,或者由于大多数人只关心最新内容,因此使用分页显示5篇博客文章就足够了?
如前所述,您可以在切换页面时通过异步加载来进一步改进分页结果。
包含字段
减少负载的最简单方法是在 REST 请求上使用包含字段功能。通过将 IncludeFields 与单独的属性名称列表一起添加到查询字符串,响应将仅包含这些字段和顶级对象。这仅适用于基本属性,不能排除完整对象。如果您的响应包含 2 个对象,这两个对象都具有相似名称的属性,则它将同时包含这两个对象。例如,如果我们调用 Info REST 端点,我们通常会返回 4 个完整对象,即 SiteSettings、ApplicationConfiguration、AccessingUser 和 InfoResult(不包括标准 Info/Errors 和 Warnings)。如果我们只需要来自 AccessingUser 的 UserId、Username和Timezone,并且只需要 InfoResult 的 SiteName,我们可以这样格式化URL:
http://mylimyeesite.com/api/v1/info.json?IncludeFields=SiteName,Username,Id,Timezone
我们的结果将如下所示:
{ "InfoResult": { "SiteName": "Your Site Name","TimeZone":-6 } ,"SiteSettings": null ,"ApplicationConfiguration": null ,"AccessingUser": { "Username": "test", "Id": 2210,"TimeZone":-6 } ,"Info": [] ,"Warnings": [] ,"Errors": [] }
请注意,主要对象仍然存在,但只有与我们的列表匹配的属性才会返回。另请注意,AccessingUser 和 InfoResult 都有一个时区属性,虽然这不是故意的,但你会同时取回这两个属性。
脚本化自定义端点
脚本化自定义端点在 2 个方面非常强大。最大的问题是,它本质上是在平台上执行一个小组件,并通过 REST 返回输出。无需编写、编译和部署 C# 代码,而是可以使用 Limyee 电商平台中的小组件编辑器来设计逻辑,然后直接从管理界面轻松进行调整,就像自定义 UI 一样。此方法允许您访问所有小组件 API,因此您可以在小组件中实际进行小组件 API 调用,并将响应重新格式化为您自己的 JSON 有效负载。如果您想在外部站点中显示某些内容,但希望平台管理 HTML 标记,而不担心处理的 JSON,则可以返回已在平台 API 填充的预格式化 html。你唯一不能做的就是依赖任何平台 javascript API 或库。您应该只使用纯 HTML。您可以在脚本化端点部分查看示例并了解如何使用此功能。
自定义 REST 端点
最后,如果您愿意,只需创建自己的端点即可。 自定义 REST 端点不仅适用于自定义数据,还可以基于进程 API 数据创建自己的响应 。您只需创建自己的包含所需字段的封装对象,然后从一个或多个进程 API 调用中检索信息并填充它。
缓存响应数据
还要考虑以某种方式缓存检索的数据。对于 .NET 应用程序,这可以简单地使用 ASP.NET 缓存或简单的内存缓存。如果不是 .NET,请查阅有关缓存选项的特定技术文档。
平台本身广泛缓存数据,以防止持续的数据库跳动。REST 从中受益,因为一旦收到请求,它可能就不需要查询数据,但它对该数据的实际传输没有帮助。您的应用程序可以接受常见请求并在短时间内缓存它们,以避免进行不必要的 HTTP 调用。例如,对于不更改的公开可用的论坛列表,您可以缓存它,以避免在访问页面时必须通过 REST 不断请求它。您可能将其缓存一两分钟以避免过时,但如果它很少更改数据,则可能会更长。还要注意用户特定的数据。只要您记得按用户进行区分(通常在缓存名称中使用用户标识符),就可以缓存它,以避免将一个用户缓存的数据显示给另一个用户来的信息泄露安全漏洞。