《英雄联盟》在线服务运维之道 - InfoQ https://www.infoq.cn/article/running-online-services-riot/

第一章 简 介

我是Jonathan McCaffrey,来自Riot公司的基础设施团队。在讲述我们 如何进行后端应用的部署和运维之前,首先要先了解一下我们是如何看待 我们的应用开发的。游戏玩家的价值对于Riot来说是至高无上的,我们的 开发团队经常与玩家社区互动,为了给玩家们提供最佳的游戏体验,我们 必须具备根据玩家反馈快速做出变更的能力。基础设施团队的使命就是为 开发人员提供支持,我们提供支持的力度越大,玩家们就能越快体验到最 新的功能。

当然,说起来容易做起来难!因为部署的多元化,我们面临着很多 挑战。我们有公有云服务器,也有本地数据中心,还要与腾讯和Garena 合作。这些环境的复杂性给开发团队增加了不少负担,于是就有了基 础设施团队。我们使用基于容器的内部云来简化部署,这个云叫作 “rCluster”。在这篇文章里,我将介绍Riot从手动部署到使用rCluster进 行部署的演变过程。为了更好地描述rCluster,我将以海克斯工匠系统 (Hextech Crafting System)作为例子。

历史背景简述

我在七年前加入Riot,当时我们并没有那么多部署流程和服务器管理 流程,我们还只是一个怀揣大梦想的初创公司。我们的预算很有限,做什 么事情都要求快。我们为《英雄联盟》构建了一套基础设施,努力满足游 戏不断增长的需求,为开发团队提供支持,同时还要支持区域团队拓展新 的疆域。我们通过手动配置服务器和应用程序,没有太多指南和战略规划 之类的东西。

后来,我们使用Chef来完成常见的部署和基础设施任务,使用公有云 进行大数据计算和提供Web服务。在这一过程中,我们多次重新设计了我 们的网络,也更换过供应商,甚至重组了整个团队结构。

我们的数据中心有数千台服务器,每新增一个应用程序就要添加新的 服务器。新服务器被接入手动创建的虚拟局域网,并手动配置路由和防火 墙规则来提升安全性。虽然这样可以提升安全性,但费时又费力。因为这 个痛点的存在,当时的新功能都被设计成小型的Web服务,导致《英雄联 盟》生态系统的服务数量大肆膨胀。

除此之外,我们的开发团队对应用程序的测试环节缺乏信心,在进行 部署时经常出现一些配置或网络连接问题。因为应用程序与物理基础设施 的耦合太过紧密,以致于生产环境与测试环境、Staging环境和公测环境 难以保持一致。

我们的应用程序数量一直在增长,我们也在经历着手动配置服务器 和网络的艰难过程。与此同时,Docker开始在我们的开发团队中流行起 来,用于解决配置和开发环境一致性问题。我们开始意识到,我们可以用 Docker做更多的事情,它可以在基础设施方面扮演一个更重要的角色。

2016 全明星赛及其他

基础设施团队的目标是为游戏玩家、开发团队和2016全明星赛提供支 持。在2015年底,我们从手动部署转向了自动部署,比如海克斯工匠系统 8 InfoQ 中文站 就使用了自动部署。我们开发了rCluster——一个全新的系统,它使用了 Docker和微服务风格的SDN(Software Defined Networking)。rCluster解 决了不一致性问题和部署流程问题,让产品团队可以集中在他们的产品研 发上。

接下来我们将深入探讨rCluster是如何支持海克斯工匠系统的。

海克斯工匠系统在我们内部被称为“战利品(Loot)”,由三个核心 组件组成。

• 战利品服务——一个Java应用程序,通过基于HTTP/JSON的REST API处理战利品请求。

• 战利品缓存——基于Memcached的缓存集群,并使用了一个Go语 言开发的小型边车(sidecar)来监控、配置、启动和关闭缓存集 群。

• 战利品数据库——一个MySQL集群,包含了一个主数据库和多个 从数据库。

在进入工匠系统时,会发生以下一系列事件

1. 玩家在客户端打开工匠系统的屏幕。

2. 客户端向前端应用程序发起 RPC 调用,前端应用(也就是 “feapp”)就是玩家和后端服务之间的代理。

3. feapp向战利品服务器发起调用请求。 • feapp从“服务发现”(Service Discovery)中找到战利品服务 器的IP地址和端口。 • feapp向战利品服务器发起HTTP GET请求。 • 战利品服务器检查战利品缓存里是否保存着玩家的物品。 • 玩家物品不在缓存里,于是战利品服务向数据库发起请求,并 将返回的结果放进缓存。 • 战利品服务将结果返回给feapp。

4. feapp将RPC响应消息返回给客户端。 通过与战利品团队的合作,我们将服务器和缓存放进了Docker容器, 并使用JSON文件来定义它们的部署配置。 战利品服务器的JSON配置示例:

{
"name": "euw1.loot.lootserver",
"service": {
"appname": "loot.lootserver",
"location": "lolriot.ams1.euw1_loot"
},
"containers": [
{
"image": "compet/lootserver",
"version": "0.1.10-20160511-1746",
"ports": []
}
],
"env": [
"LOOT_SERVER_OPTIONS=-Dloot.regions=EUW1",
"LOG_FORWARDING=true"
],
"count": 12,
"cpu": 4,
"memory": 6144
}

战利品缓存的JSON配置示例:

{
"name": "euw1.loot.memcached",
"service": {
"appname": "loot.memcached",
"location": "lolriot.ams1.euw1_loot"
},
"containers": [
{
"name": "loot.memcached_sidecar",
"image": "rcluster/memcached-sidecar",
"version": "0.0.65",
"ports": [],
"env": [
"LOG_FORWARDING=true",
"RC_GROUP=loot",
"RC_APP=memcached"
]
},
{
"name": "loot.memcached",
"image": "rcluster/memcached",
"version": "0.0.65",
"ports": [],
"env": [
"LOG_FORWARDING=true"
]
}
],
"count": 12,
"cpu": 1,
"memory": 2048
}

不过要真正部署好它们,我们还需要创建一些集群,它们需要支持南 美、北美、欧洲和亚洲的Docker。我们因此需要解决一大堆问题:

• 容器调度

• Docker网络

• 持续交付

• 动态运行应用程序

后续的章节将会详细介绍这些组件,所以在这里先简要提及。

容器调度

我们自己编写了一款叫作Admiral的软件,并把它用在rCluster系统 里,进行容器调度。Admiral与一组物理机上的Docker后台进程进行通 信,以便了解它们的健康状态。运维人员通过HTTPS发送上述的JSON 请求,Admiral则用它们了解相关容器的状态。Admiral会持续地更新集 群的状态,并在必要的时候采取相应的行动。Admiral会根据实际情况向 Docker后台进程发起请求来启动或停止容器,从而达到预期的状态。 如果容器发生崩溃,Admiral会在另一台主机上启动一个新的容器。 这种灵活的机制让服务器的管理变得十分容易,我们可以无缝地“灭掉” 它们,做一些维护工作,然后再重启它们。 Admiral与开源工具Marathon有点像,我们目前也正打算使用Mesos、 Marathon和DC/OS的替代方案。如果这样可行,我们将会在后续的文章中 分享我们的经验。

Docker 网络

在容器可以运行了之后,我们还要为战利品应用程序和系统的其他 部分提供网络连接。我们使用OpenContrail为每个应用设置私有网络,然 后让开发团队使用托管在GitHub上的JSON文件来配置他们自己的网络策 略。 战利品服务器网络配置示例:

{
"inbound": [
{
"source": "loot.loadbalancer:lolriot.ams1.euw1_loot",
"ports": [
"main"
]
},
{
"source": "riot.offices:globalriot.earth.alloffices",
"ports": [
"main",
"jmx",
"jmx_rmi",
"bproxy"
]
},
{
"source": "hmp.metricsd:globalriot.ams1.ams1",
"ports": [
"main",
"logasaurous"
]
},
{
"source": "platform.gsm:lolriot.ams1.euw1",
"ports": [
"main"
]
},
{
"source": "platform.feapp:lolriot.ams1.euw1",
"ports": [
"main"
]
},
{
"source": "platform.beapp:lolriot.ams1.euw1",
"ports": [
"main"
]
},
{
"source": "store.purchase:lolriot.ams1.euw1",
"ports": [
"main"
]
},
{
"source": "pss.psstool:lolriot.ams1.euw1",
"ports": [
"main"
]
},
{
"source": "championmastery.server:lolriot.ams1.euw1",
"ports": [
"main"
]
},
{
"source": "rama.server:lolriot.ams1.euw1",
"ports": [
"main"
]
}
],
"ports": {
"bproxy": [
"1301"
],
"jmx": [
"23050"
],
"jmx_rmi": [
"23051"
],
"logasaurous": [
"1065"
],
"main": [
"22050"
]
}
}

战利品缓存网络配置示例:

{
"inbound": [
{
"source": "loot.lootserver:lolriot.ams1.euw1_loot",
"ports": [
"memcached"
]
},
{
"source": "riot.offices:globalriot.earth.alloffices",
"ports": [
"sidecar",
"memcached",
"bproxy"
]
},
{
"source": "hmp.metricsd:globalriot.ams1.ams1",
"ports": [
"sidecar"
]
},
{
"source": "riot.las1build:globalriot.las1.buildfarm",
"ports": [
"sidecar"
]
}
],
"ports": {
"sidecar": 8080,
"memcached": 11211,
"bproxy": 1301
}
}

一旦GitHub上的配置文件发生变更,就会启动一个传输作业,调用 Contrail的API来创建和更新应用程序的私有网络策略。 Contrail使用了一种叫作叠加网络(Overlay Network)的技术来实现私 有网络。在我们的系统里,Contrail在计算机主机之间启用了GRE通道, 并使用网关路由器来管理流经通道的流量。OpenContrail系统的灵感来自

于标准MPLS L3VPN,所以在概念上与之非常相似。

在实现这个系统时,我们必须解决一些关键性挑战:

• 集成Contrail和Docker;

• 允许rCluster之外的网络无缝地访问叠加网络;

• 允许不同集群之间的应用发生交互;

• 在AWS上运行叠加网络;

• 在叠加网络上构建高可用的面向边缘的应用。

持续集成

战利品应用程序的CI流程类似下面这样:

我们的主要目标是这样的:一旦主仓库发生变化,就会创建一个新的 应用容器,并将其部署到QA环境中。有了这个流程,我们的团队就可以 快速迭代他们的代码,并看到代码实际的运行情况。紧凑的反馈闭环加快 了改进用户体验的速度,这也正是Riot的关键目标——以玩家为中心,为 玩家提供最佳体验。

动态地运行应用程序

到目前为止,我们谈论了我们是如何构建和部署应用程序的,但如果 你曾经在这样的容器环境里工作过的话,你就会知道,我们要面临的挑战 远不止之前提到的那些。

在rCluster里,容器有动态的IP地址,而且一直在启动和关闭。这与之

前提到的静态服务器的部署方式是完全不一样的,所以我们需要新的工具 和流程。

一些关键问题:

• 如何监控容量和端点一直在变化的应用?

• 如果端点一直在变化,那么应用程序如何才能知道其他应用程序 的端点是什么?

• 如果不能通过ssh连接到容器上,而且容器日志在重启之后就会消 失,那么该如何进行问题诊断?

• 如果我们是在构建阶段预热(bake)容器,那么如何配置数据库 密码,或者如何为其他地区的容器配置不同的参数? 为了解决这些问题,我们开发了一个微服务平台,用于解决服务发 现、配置管理和监控问题,我们将在其他详述该平台的细节,以及它为我 们解决了哪些问题。

容器调度 • Docker网络 • 持续交付 • 动态运行应用程序 部署的多元化的更多相关文章

  1. 利用jenkins和docker实现持续交付

    利用jenkins和docker实现持续交付 一.什么是持续交付 让软件产品的产出过程在一个短周期内完成,以保证软件可以稳定.持续的保持在随时可以发布的状况.它的目标在于让软件的构建.测试与发布变得更 ...

  2. Docker学习总结(14)——从代码到上线, 云端Docker化持续交付实践

    2016云栖大会·北京峰会于8月9号在国家会议中心拉开帷幕,在云栖社区开发者技术专场中,来自阿里云技术专家罗晶(瑶靖)为在场的听众带来<从代码到上线,云端Docker化持续交付实践>精彩分 ...

  3. Docker学习总结(8)——利用Docker开启持续交付之路

    持续交付即Continuous Delivery,简称CD,随着DevOps的流行正越来越被传统企业所重视.持续交付讲求以短周期.小细粒度,自动化的方式频繁的交付软件,在这个过 程中要求开发.测试.用 ...

  4. BumbleBee: 如丝般顺滑构建、交付和运行 eBPF 程序

    本文地址:https://www.ebpf.top/post/bumblebee 1. 前言 不久前,Solo.io 公司在官网博客宣布了开源了一个名称为 BumbleBee 的新项目.该项目专注于简 ...

  5. Docker网络讲解 及实验redis集群部署

    理解docker0 准备工作:清空所有的容器,清空所有的镜像 docker rm -f $(docker ps -a -q) # 删除所有容器 docker rmi -f $(docker image ...

  6. Docker第一弹:下载运行hello-world程序

    1.需要安装好docker程序 没有安装的请看在centos 6.8下安装docker 2.从docker镜像仓库中拉去hello-world镜像 docker pull hello-world 3. ...

  7. 初识容器和Docker

    什么是Docker? Docker 是一个用于开发,交付和运行应用程序的开放平台.能够就应用程序和基础架构分开,从而可以快速的交付软件. 借助Docker可以和管理应用程序的方式来管理基础架构. 使用 ...

  8. Jenkins自动化部署-----持续交付【转】

    感谢之前带领过我的leader,让我能够知道什么是好的开发方法. 在很早之前就接触过敏捷开发.什么是敏捷开发,简单来说就是让软件可靠地,快速地发布出来的一种开发方法和技巧. 而敏捷开发中有许多的实践, ...

  9. Jenkins自动化部署——持续交付

    感谢之前带领过我的leader,让我能够知道什么是好的开发方法. 在很早之前就接触过敏捷开发.什么是敏捷开发,简单来说就是让软件可靠地,快速地发布出来的一种开发方法和技巧. 而敏捷开发中有许多的实践, ...

随机推荐

  1. 从零实现Linux一键自动化部署.netCore+Vue+Nginx项目到Docker中

    环境搭建 1.安装Linux,这里我用的阿里云服务器,CentOS7版本 2.进入Linux,安装Docker,执行以下命令 sudo yum update #更新一下yum包 sudo yum in ...

  2. git 清除本地git commit的内容

    由于我经常git add . , 然后再git commit -m "文字说明",这样有时候代码嵌套再另一个项目里面,就会把外面的项目一起提交了,导致提交的代码不是我想要的.小菜鸟 ...

  3. Tensorflow2.0-mnist手写数字识别示例

    Tensorflow2.0-mnist手写数字识别示例   读书不觉春已深,一寸光阴一寸金. 简介:通过CNN 卷积神经网络训练后识别出手写图片,测试图片mnist数据集中的0.1.2.4.     ...

  4. Double 值比较大小 Long值比较大小

    BigDecimal outValue = new BigDecimal(sapVerifyInventory.getQuantity()); BigDecimal inValue = new Big ...

  5. web项目报错 无法解析,丢失包 是缺少本地运行jre

    1.通过build path 添加add Library 2.添加jre

  6. Redis基础篇(六)数据同步:主从复制

    Redis具有高可靠性,体现在两方面: 一是数据尽量少丢失,通过前面介绍的持久化方式AOF和RDB,在宕机时可以恢复数据. 二是服务尽量少中断,通过副本冗余来实现. 今天我们学习的就是通过主从复制实现 ...

  7. 关于opcache中opcache.revalidate_freq参数设置测试报告

    1.测试目的: 测试出opcache中,opcache.revalidate_freq这个参数最适合的大小 说明:如果opcache.revalidate_freq参数越大,服务器单位时间能接收的请求 ...

  8. Daphile FAQ -- 官方文档译文 [原创]

    Daphile FAQ 英文原文:https://www.daphile.com/download/FAQ.txt 采集日期:2021-01-03 常见问题解答:(FAQ) Q1:没有声音.Daphi ...

  9. 2.1 关系型数据的收集--Sqoop

    Sqoop应用场景: 1.数据迁移,将关系型数据库中的数据导入Hadoop存储系统 2.可视化分析结果,将Hadoop处理之后产生的结果导入关系型数据库,以便进行可视化展示 3.数据增量导入:减少ha ...

  10. <input type="image">表单提交2次 重复插入数据问题

    写一个表单提交用到图片:两种代码. <input type="image" src="xxx.gif"onclick="return dosub ...