微信号:For_programmer

介绍:每天一篇新奇有趣的程序员读物,不让你错过任何一条精彩内容,使你的见解更加独特、深刻.

[译]深入挖掘拳头公司(Riot Games)的游戏API

2016-07-14 17:21 Leigh Estes

原文:THE RIOT GAMES API: DEEP DIVE

译者:杰微刊兼职翻译刘晓鹏


嗨,大家好。我是Leigh Estes,又名aka RiotSchmick。我是一名在拳头游戏公司从事服务可用性方面工作的软件工程师。我们在第一篇文章中阐述了我们的目标,开发人员关系责任和开发者平台团队的API生态系统,以及在我们构建API方案中用到的高层次技术细节。英雄联盟社区已经在拳头游戏公司API之外建立了很多用的工具和网站,包括数据统计网站,如LoLKing.com和op.gg,以及为玩家提供辅助功能的replay.gg网站。正如这篇文章中所承诺的那样,我们将深入挖掘拳头游戏公司API平台的技术架构,包括边缘基础设施以及非底层的代理服务。首先,会列出我们首次决定建立API平台时的一些基本的技术选择。然后我们可以挖掘一些平台中特定的组件。接下来,我将阐述用于构建组件的技术。最后,我将介绍如何在AWS上部署我们的基础设施。


基础选择

正如我们在之前的文章中所提到,我们最初考虑是使用现有的API来管理平台,诸如apigrove和Repose,但后来决定建立我们自己的解决方案,因为这样可以在拳头游戏公司生态系统中为不同的地区,合作伙伴和技术实行定制化工作。我们研究了哪些开源解决方案可以支撑我们的当前的流量规模,最终,我们决定采用Netflix部署的Zuul代理服务器,以及其他一些Netflix的项目,包括Archaius、Ribbon、Hystrix、和Eureka等。许多聪明和有才华的人在Netflix建立了自己的基础设施,以用来处理大量的常数,高带宽流量的服务。因此,我们有理由相信这些代码是经过严格的测试和生产验证的。NetflixZuul提供了一个核心依赖jar包,用于处理HTTP请求和执行过滤器链。以这个依赖jar包为基础,我们写了一些额外的类来实现我们所需要的功能,如自动健康检查,连接池管理和监控,指标处理等,在这个核心代理服务器的最上层,我们实现了自定义的过滤器来处理的其他业务,如授权,认证,速率限制,动态路由,负载平衡,标准集合,白名单,黑名单等等。核心代理服务器由java编写,自定义的过滤器由Groovy编写,它们构建在同一个war包中,然后部署到生产环境,通过Jetty servlet容器来运行。核心架构的其他组件,即在Zuul代理中所提到的,是一些单独的服务,包括速率限制,黑名单,以及度量标准收集和过程。


边缘服务速率限制器

边缘服务速率限制器((ESRL – 读作Ezreal)用于处理速率限制和黑名单。它提供了两个终端,一个使用类似漏桶算法的方式管理核心API的速率限制,另外一个检查,如果一个API密钥列入黑名单(即在一个给定的时间段内违反速率限制的数量)。ESRL的目要是保证一个非常快响应时间,因此我们在试图进行限速管理时不能成为我们请求的瓶颈。我们实现了这一目标,两个终端的的响应时间平均值在2毫秒左右。如下图所示:通过使用Redis的来完成所有的ESRL的操作。每个终端运行一段Lua脚本,通过一次调用,在单个redis连接中执行完所有需要的操作,然后再通过脚本响应来决定给客户端返回什么。


RIOTAPI标准

RiotAPI标准服务用于度量标准的收集和处理。和ESRL一样,我们想确保度量收集不会成为我们请求的瓶颈。为了实现这个目标,我们将HTTP向Zuul的同步请求与实时的度量标准收集进行解耦。向代理服务器发送请求会触发一个度量过滤器,但只简单地将度量信息添加到内存队列中。我们将来可能会将这个队列放在在Redis或其他非内存的缓存中,但一开始我们只想限制Zuul对其他Rest服务调用的依赖,除了Netflix的核心库,没有与第三方依赖建立关系的时间。通过一个线程池来处理队列,现在我们已经成功地将其放在内存中进行管理。线程池中的每个线程都在循环的执行,即从一个线程安全集合中的拉取度量标准项,并将其提交给Riot API的度量服务,如果调用失败,将它重新添加到线程安全集合中,以便可以在以后重新处理。如果队列中没有度量,线程将休眠,以避免忙等消耗CPU周期。Riot API度量服务提供了一个终端来发布度量信息,它只是简单地将其增加到Redis队列中,然后立即返回给客户端。虽然这些请求都是由Zuul异步提交的,我们仍然希望尽可能快的响应时间,如果处理速度跟不上吞吐量,内存队列大小无线增值。该终端的响应时间平均值也在2毫秒以下,如下图所示。度量服务还有一个线程池,在后台执行从队列读取度量项的操作,检查度量项,并通过多种不同的方式保存到MySQL数据库,这样我们就可以做关系查询。


开发者门户

正如我们以前的文章中提到的,我们建立了一个公共开发者门户,以促进开发人员与第三方开发者间进行交互。为了简化开发,我们充分利用已有的MVC框架,我们建立了开发人员门户作为一个Grails应用,该应用是用Java和Groovy编写的,运行在Tomcat下,前端利用Bootstrap实现。当用户第一次登录到开发人员门户时,为他们创建一个开发人员帐户。开发应用会自动创建一个相关的API秘钥以及与之相关联的账户。如果生产环境的应用需要一个更高的速率限制,用户可以注册他们的项目来用于访问一个生产环境的API密钥。应用程序关联到某一层,在这一层中有速率限制的定义。例如,一个演示层可以被定义为每10秒10次调用,每10分钟500次调用。有两个速度限制与一个层绑定,这意味着该层可以管理突发性和持续性调用。应用程序也依赖于策略,这些策略定义了一组应用程序可以访问的API端点。此外,这个应用程序配置,API平台所依赖的配置,包括有效代理服务的描述和物理端点(即IP地址或域名)。一个管理界面允许我们配置一个服务,即API接口主机和服务这些API的物理端点。API可以从策略中添加或删除,应用程序策略和层次的关系也可以进行修改。目前,在生产环境中,层、策略、服务、端点和API的配置是手工完成的。将来,我们会将其转移到到一个能够自动发现服务配置的框架上。


扩展配置

上述关于API平台各种配置数据,包括自动生成的账户,应用程序,和秘,以及手动配置层、政策、服务、终结点和API,都存储在MySQL数据库方案中。一个称之为API配置服务的轻量级服务负责提供配置信息,如一些有效的API密钥列表,边缘服务器应该考虑有效性的URI列表,URI路由的物理终端,每个策略对应的URI列表,每个速率限制层的定义等。


Zuul和ESRL二者需要经常读到这些属性值,并动态地改变它们的值。Netflix Archaius项目的目的就是提供这些功能,该项目中,属性列表的来源可以重新获取并动态的更新内存中的值,所以这能与ESRL和Zuul实现完美的结合。最初我们配置Archaius属性来源来满足API配置服务返回相关的REST 终端。然而,由于种种原因,使这种机制不能可靠的进行频繁的动态属性更新。首先,随着我们的的平台在范围和用户基础上增长,数据库中的配置项的数量也随着时间的增长而增长。这将使得数据库的查询越来越慢,REST端点的响应也越来越慢。有时我们的VPC网络会有问题,使得频繁尝试下载大文件更成问题。


最终,通过在内部网络上的一个REST端点来下载属性文件的服务变得非常不可靠且耗时。因此,我们觉得需要一个CDN-type解决方案,这样我们可以在互联网上可靠地从地理上接近的位置下载大文件。S3提供的正是我们所需要的,所以我们从数据库中读取信息来更新API配置服务,并将关键信息写入到S3桶中。然后Zuul和ESRL被更新,以便它们的Archaius属性来源指向S3桶中的位置,而不是配置服务的REST API端点。这个模型已经被证明是可靠的和高性能的。



技术概述

ESRL,RiotAPI标准,API配置服务都是用Java编写的。最初,他们是使用一种被称为dropwizard的框架编写,该框架在一个可执行Jar中运行JerseyREST服务,而不需要通过嵌入式Jetty将其部署在一个servlet容器中。只是最近,我们利用一个内部的框架(我们称之为Hermes)重新实现这些服务。在前面的一篇文章中,Cam Dunn讨论了Riot如何利用RFC来处理技术设计。Hermes是一个称之为Ambassador规范的实现,该规范开始作为一个RFC(事实上,他的文章的顶部的屏幕截图显示了Ambassador RFC !)。采用Hermes技术(内部建立并已经被广泛采用)等技术重新实现我们,有几个好处,包括以下几个方面:


  1. 当bug或性能问题出现时,我们有内部支持来帮助我们。

  2. 当用户有Hermes的代码权限时,可以工作的更好,并且我们可以反馈基础代码,通过帮助Riot的每一个人来使得它更好。

  3. 当其他开发人员需要查看我们的系统或代码,我们使用的是通用的技术,这为他们理解到底发生了什么提供很大的帮助。

  4. 作为用户,定期反馈代码库,并且有直接访问到它的原始作者,当跟踪问题是,我们更好地理解它。


我们已经发现了Hermes的几个bug和性能问题,并解决了这些问题,提交请求,然后协调使用包含了我们提交的代码框架的新版本。因此,我们感受到采用这个框架为我们的整个团队乃至整个RIOT都获得了巨大的利益和回报。


我之前提到过,在我们的边缘中使了用Hystrix。这项技术提供了检测能力,当调用一个底层服务缓慢时(定义的一个可配置的阈值),会立即返回一个503,而不尝试代理调用。我们做了一些工作,将Hystrix集成到我们的定制Zuul代码,但结果从未令我们满意,所以我们还没有部署到生产环境中去。但是无论是与Hystrix集成还是实现自己的类似的解决方案,这都我们的路线图。API平台配置允许我们连接或读取的代理服务配置超时,以防止边缘的性能配置导致持续缓慢的服务。然而,如上面所描述的短路机制,通过阻止Jetty 工作线程忙或Jetty 接收队列备份影响请求来进一步减少持续性缓慢服务效果。


我们起初使用一个叫做Ribbon的软件来为每个Zuul代理服务来时实现跨服务器组的负载均衡。当我们重构我们的dropwizard项目用于运行Hermes服务器,我们还重构Zuul使用的Hermes客户端,代替Ribbon来实现软件的负载均衡。同样,我们最初使用archaius处理所有的动态配置,包括前面讨论的API平台的配置,以及代理服务器特定环境下的应用配置。最近,我们决定改用另一个名为Configurous的内部解决方案来实现特定环境下的应用配置。我上面已经列举了利用自己技术的好处,所以我这里就不再重复了。像Hermes、Configurous都RFC流程中的概念,公司很多团队采用和实现了这些概念。Configurous的目的是在不同的环境中轻松地管理应用程序配置,包括动态更新。然而,由于Configurous是管理应用程序配置的范围,它只支持小属性值和相对变化较少值。因此,在API平台配置中,我们继续使用Archaius管理大的和不断变化的属性。


最后,我们用Eureka来集成代理,这已经被定义为Riot “Stack”生态系统的一部分,在所有环境中运行起来。这种集成允许我们像前面提到一样,可以自动发现和配置服务。此外还可以自动发现想要代理的底层服务,它还允许每个代理自动定位 ESRL和Riot API标准服务。这个功能目前只在内部环境中测试和启用,但它工作得很好,可以节省大量的手动步骤,如盒子的上下转换。Eureka最终被另一个称为discoverous的Riot技术取代。Discoverous是另一个RFC产品,是基于Eureka实现的,但添加了一些Riot生态系统所需要的自定义的功能。它完全向后兼容Eureka,所以我们这边不需要做任何修改。Hermes,Configurous和Discoverous是Riot服务架构的基本模块,将在以后的博客文章里介绍。


AWS部署

Zuul代理服务器部署在AWS实例上,跨越了3个VPC,东京、爱尔兰和北加州。有4个代理服务器实例,每个ELB的背后VPN都有2个可用性区域。每个VPC又有多个RiotAPI标准和ESRL实例。RiotAPI标准和ESRL也都有自己的redis服务器,以及一个AWS ElasticCache实例。北加州的Riot API标准被认为是度量标准的主服务器,由一个MySQL数据库(一个AWS的RDS实例)备份。爱尔兰和东京Riot API标准在被认为是从服务器,当它们的线程执行度量数据持久化操作时,它们需要将DTO序列化为JSON,并通过REST调用到主服务器。然后,主服务器将数据保存到数据库。这个模型允许我们在任何一个区域的某个数据库中保存度量数据,然后我们就可以查询。当主服务器执行持久性步骤,直接将DRO保存到数据库。API配置服务只运行北加州的VPC上,并将必要的文件写入各区域S3桶中。每个Zuul和ESRL从自身所在区域中读取S3 桶的值,以减少延迟。


结论

随着API的开放,边缘服务和相关的基础设施近年来不断发展。我们已经性能,可靠性,不同的成熟技术力量,以及生产环境的架构等方面得到了改善。展望未来,边缘基础设施将在每一个riot数据中心进行部署,来帮助管理ACL和速度限制,为所有API提供一个简单的单点访问共享服务,并利用边缘提供的所有其他特性和优点。当我们推出的框架,允许边缘自动发现和配置服务,它将成为一个更强大的机制,允许服务在可控制,可预测,和可靠的方法内进行自动的交互。这个框架将使团队更快地专注于提供对玩家有价值的服务,而不必担心他们在写新的服务时一遍又一遍地解决同样的问题。


边缘的诞生,作为解决我们平台上具体问题中的一部分,已逐渐成长和成熟,它的定位是一个Riot正在建设的关键的微服务架构。我们很高兴地看到,它已经从一个微小的开端逐渐强大,并期待着为公司的边缘服务提供更广泛的解决方案。感谢您的阅读!如果您有任何意见或问题,我恳请你们在下面留言。在不久的将来我会回来写一篇文章,探讨优化我们对Riot代理层的研究。

JF

微信关注《大话程序员》,

每天两篇新奇有趣的互联网读物。


扫描或长按识


 
大话程序员 更多文章 开发者MAC电脑里的十八般兵器 [译]微服务注册构架II-代理模型 [转]HTTPS的七个误解 [译]Segment是如何做持续集成的 《神秘的程序员们》--一个关于乔贝穆凯的故事
猜您喜欢 携程无线新旅程 30分钟3300%性能提升:python+memcached网页优化小记 无实例无真相 透过真实例子看大数据应用 精益企业—建立高适应力、持续创新的高绩效组织 mnv*框架时代