Presentation is loading. Please wait.

Presentation is loading. Please wait.

Mico的架构之旅 魏佳 Co-Founder & CTO @ Mico Inc..

Similar presentations


Presentation on theme: "Mico的架构之旅 魏佳 Co-Founder & CTO @ Mico Inc.."— Presentation transcript:

1 Mico的架构之旅 魏佳 Co-Founder & Mico Inc.

2 关于我 分布式消息中间件 虚拟化及多租户弹性运行时 大规模分布式系统服务质量 分别在美国和国内发表技术专利 2009 2012 2014
IBM 新浪微博 Mico创业 资深工程师 Co-Founder & CTO 平台架构部架构师 技术评审委员会成员

3 关于Mico 是什么? 定位 形态 类似产品 市场? 用户群体分布 为什么选择这样的市场

4 关于Mico 相关数据? 注册用户数 日活跃用户数、日在线用户数、月活跃用户数、 日消息量、日服务请求量、日通知推送量
UGC内容量、图片/语音/短视频等

5 关于Mico 技术团队 团队规模、职责划分 技术准则和文化

6 今天分享些什么 初起炉灶 高速发展 步入正轨

7 初起炉灶 业务驱动,简单分层,粗放、够用就好 暴露的问题 SCM和流程 环境 基本架构组成(带图,细讲) 这种情况下如何应对增长(扩展)?
功能简单,除了应用后台外,无其他周边系统 运维工具的缺失,全手工 环境的监控和告警 发布和上线过程 手工环境的错误不可控 * 业务驱动,简单分层,粗放、够用就好 Bitbucket作为scm Linode,东京机房,裸VM+自己搭建生产环境 单实例的biz backend(Java,Spring Boot),暴露REST API,为移动端提供业务功能。 缓存(Memcached、Redis),隔离业务功能和通信,无sharding,Redis以master-slave拓扑 存储(MySQL、MongoDB),MySQL一主一从(实例中按业务分库但无分表),MongoDB一主两从 GridFS用于文件存储,比如图片、短视频等,文件访问API(NodeJS),直接使用Nginx的local cache来做二进制资源的缓存。 单实例的socket backend,提供长连接通信,资源与biz backend共用。 单独的Web server(Nginx+NodeJS)用来server产品官网、外部内容分享以及所有应用内HTML5的页面。 这种情况下如何应对增长? 扩展接入层,直接扩展业务server和socket server,直接扩展文件存储的Nginx(local cache) 扩展缓存和存储的从实例来抗读 * App功能简单,除了应用后台,无其他周边系统 早期的推荐用户、推荐动态的功能都有人工标记,没有引入其他流处理和单独的推荐系统等等。 * 缺失运维工具,全手工 Linode提供VM级的系统监控,包括CPU、Mem、Disk、Load、Network等 没有应用级的监控/告警工具,依赖各组件内置的stat工具来手工查看 构建和发布系统也很弱(简单Jenkins job) * 各种暴露的问题 1. 对系统状况没有直观实时的了解 2. 人工参与的环节错误不可控

8 初起炉灶 * 业务驱动,简单分层,粗放、够用就好 Bitbucket作为scm Linode,东京机房,裸VM+自己搭建生产环境
细讲 * 业务驱动,简单分层,粗放、够用就好 Bitbucket作为scm Linode,东京机房,裸VM+自己搭建生产环境 单实例的biz backend(Java,Spring Boot),暴露REST API,为移动端提供业务功能。 缓存(Memcached、Redis),隔离业务功能和通信,无sharding,Redis以master-slave拓扑 存储(MySQL、MongoDB),MySQL一主一从(实例中按业务分库但无分表),MongoDB一主两从 GridFS用于文件存储,比如图片、短视频等,文件访问API(NodeJS),直接使用Nginx的local cache来做二进制资源的缓存。 单实例的socket backend,提供长连接通信,资源与biz backend共用。 单独的Web server(Nginx+NodeJS)用来server产品官网、外部内容分享以及所有应用内HTML5的页面。 这种情况下如何应对增长? 扩展接入层,直接扩展业务server和socket server,直接扩展文件存储的Nginx(local cache) 扩展缓存和存储的从实例来抗读 * App功能简单,除了应用后台,无其他周边系统 早期的推荐用户、推荐动态的功能都有人工标记,没有引入其他流处理和单独的推荐系统等等。 * 缺失运维工具,全手工 Linode提供VM级的系统监控,包括CPU、Mem、Disk、Load、Network等 没有应用级的监控/告警工具,依赖各组件内置的stat工具来手工查看 构建和发布系统也很弱(简单Jenkins job) * 各种暴露的问题 1. 对系统状况没有直观实时的了解 2. 人工参与的环节错误不可控

9 高速发展 数据增长很快,开着飞机换引擎 这个阶段的架构变更(带图,细讲) 异步消息组件 拆分业务(细讲,缘由,做法等) 文件存储系统
请求接入 通信 跨长链消息 拆分业务(细讲,缘由,做法等) Api层 Server层 资源层 文件存储系统 实现 做法 问题 * 数据增长很快,一边继续产品迭代一边进行架构改造(开着飞机换引擎) 这个阶段的系统架构图 * 引入消息组件,这里面临技术选型的问题。目前开源并且广泛实用的mom非常多,不同的系统的设计侧重点也不同。(比如事务完备,确保投递,分布式的方式等等) 1. http上下行请求分离,上行请求全部异步,移动端假写,服务层直接写cache,具体业务逻辑在消息处理器中完成 2. 通信消息异步写库,上行直接写cache 3. 跨socket server通信写队列 * 按业务拆分,因为各业务的使用量和场景不同,这就决定了生产环境上资源的使用是不均等的,高峰期遇到的压力也不同。 1. 划分api pool,可以更细粒度的控制请求,可以根据需要单独扩展某业务,可以在故障或高峰时单独降级某业务 2. 划分service,为之后的微服务化铺路,将各业务作为内聚的最小服务单元,提供多种服务协议,如RPC、消息、HTTP等,这样也为之后的产品功能迭代提供更快速的业务支撑能力(搭积木) 3. 划分各类资源,比如cache、redis,根据各业务数据量的不同以及预计的增长量,可以更细粒度得控制这些组件的部署规模。 * 使用新的文件存储系统 1. Nginx(local cache)+ NodeJS(API)+ GridFS(storage)的方案带来的运维痛苦以及较大的性能问题 * scaleout时,部署一整套组件,同时新的的gridfs实例作为secondary需要从primary全量复制,时间长(standby状态写不能提供服务) * primary在持续的较大写入量下,secondary会追不上 2. 将数据全部迁移到S3,我们用Golang写了个工具用来迁移数据。但是全量数据中有大量缩略图(对于图片来说共3种尺寸的缩略图,对于视频来说共3种尺寸的首帧缩略图),连缩略图一起迁移太耗时,所以我们将原来文件系统API(NodeJS)中的生成缩略图的逻辑摘出来放到AWS的Lambda服务上(Lambda的名字非常形象,可以用于S3任意action的回调函数使用,其中一个典型用途就是图片上传到S3后异步生成缩略图),这样我们就很快将原始图片、短视频以及语音迁移到S3上了。搭配S3,AWS提供了Cloudfront,它是一个global的CDN服务,迁移过程中同步就将内容复制到各个region的节点上。迁移完成后,对于未升级的客户端(早期写死了IP地址),将原有的文件系统API的前置Nginx将请求转发到cloudfront来下载。

10 高速发展 * 数据增长很快,一边继续产品迭代一边进行架构改造(开着飞机换引擎) 这个阶段的系统架构图
细讲 * 数据增长很快,一边继续产品迭代一边进行架构改造(开着飞机换引擎) 这个阶段的系统架构图 * 引入消息组件,这里面临技术选型的问题。目前开源并且广泛实用的mom非常多,不同的系统的设计侧重点也不同。(比如事务完备,确保投递,分布式的方式等等) 1. http上下行请求分离,上行请求全部异步,移动端假写,服务层直接写cache,具体业务逻辑在消息处理器中完成 2. 通信消息异步写库,上行直接写cache 3. 跨socket server通信写队列 * 按业务拆分,因为各业务的使用量和场景不同,这就决定了生产环境上资源的使用是不均等的,高峰期遇到的压力也不同。 1. 划分api pool,可以更细粒度的控制请求,可以根据需要单独扩展某业务,可以在故障或高峰时单独降级某业务 2. 划分service,为之后的微服务化铺路,将各业务作为内聚的最小服务单元,提供多种服务协议,如RPC、消息、HTTP等,这样也为之后的产品功能迭代提供更快速的业务支撑能力(搭积木) 3. 划分各类资源,比如cache、redis,根据各业务数据量的不同以及预计的增长量,可以更细粒度得控制这些组件的部署规模。 * 使用新的文件存储系统 1. Nginx(local cache)+ NodeJS(API)+ GridFS(storage)的方案带来的运维痛苦以及较大的性能问题 * scaleout时,部署一整套组件,同时新的的gridfs实例作为secondary需要从primary全量复制,时间长(standby状态写不能提供服务) * primary在持续的较大写入量下,secondary会追不上 2. 将数据全部迁移到S3,我们用Golang写了个工具用来迁移数据。但是全量数据中有大量缩略图(对于图片来说共3种尺寸的缩略图,对于视频来说共3种尺寸的首帧缩略图),连缩略图一起迁移太耗时,所以我们将原来文件系统API(NodeJS)中的生成缩略图的逻辑摘出来放到AWS的Lambda服务上(Lambda的名字非常形象,可以用于S3任意action的回调函数使用,其中一个典型用途就是图片上传到S3后异步生成缩略图),这样我们就很快将原始图片、短视频以及语音迁移到S3上了。搭配S3,AWS提供了Cloudfront,它是一个global的CDN服务,迁移过程中同步就将内容复制到各个region的节点上。迁移完成后,对于未升级的客户端(早期写死了IP地址),将原有的文件系统API的前置Nginx将请求转发到cloudfront来下载。

11 高速发展 补齐或完善运维系统,半手工扩容 云环境的迁移 封装环境vagrant Gitflow,完善构建发布过程 简单的监控系统
朴素的定时任务 用户管理系统和内容管理系统 手工扩容 云环境的迁移 为什么? 资源 定价 服务单一 * 一边补全运维工具,一边应对高峰期手工扩容 * 使用Vagrant构建最小化的dev环境,可以确保所有成员环境一致 * 合理使用Gitflow,Jekins每日构建dev branch,每日部署staging环境,同样使用Vagrant来封装staging环境 * munin搭建监控系统,覆盖所有的资源或组建。munin的plugin机制(Python/Perl)可以灵活扩展或定制监控项 * 定时任务+离线脚本去统计业务数据 * 用NodeJS+Angular搭建用户管理和内容管理后台(包括内容运营/发布,应用内官方帐号消息,应用内用户反馈,用户封禁/解封,内容审核,外部内容分享控制等) * 依赖监控系统的各类数据指标指导高峰期的扩容(需手工执行,是一套简易的python实现的工具箱,可以根据base image(AMI)快速创建实例,更新前端LB,更新资源配置等。) * 云环境的迁移 * 为什么放弃Linode? 1. 资源欠缺 Linode(tokyo地区)的机器资源实际是使用AWS的,在我们高速发展的阶段(频繁需要扩容)但是Linode经常提示没有实例可以提供。 2. 定价模式 Linode的机器都是按实例按规格按月结算,不论用多用少没有灵活的收费模式(主要还是因为我们穷) 3. 服务太单一 只提供VM,连IaaS都称不上,没有其他任何云服务。相比AWS,提供很多开箱即用的服务,能极大节省我们的精力和时间。 * AWS,使用了EC2、Loadbalancer、EIP、S3、CloudFront、Lambda。后期又陆续使用了ElasticCache、RDS、MailService等。

12 高速发展 * 一边补全运维工具,一边应对高峰期手工扩容 * 使用Vagrant构建最小化的dev环境,可以确保所有成员环境一致
细讲 * 一边补全运维工具,一边应对高峰期手工扩容 * 使用Vagrant构建最小化的dev环境,可以确保所有成员环境一致 * 合理使用Gitflow,Jekins每日构建dev branch,每日部署staging环境,同样使用Vagrant来封装staging环境 * munin搭建监控系统,覆盖所有的资源或组建。munin的plugin机制(Python/Perl)可以灵活扩展或定制监控项 * 定时任务+离线脚本去统计业务数据 * 用NodeJS+Angular搭建用户管理和内容管理后台(包括内容运营/发布,应用内官方帐号消息,应用内用户反馈,用户封禁/解封,内容审核,外部内容分享控制等) * 依赖监控系统的各类数据指标指导高峰期的扩容(需手工执行,是一套简易的python实现的工具箱,可以根据base image(AMI)快速创建实例,更新前端LB,更新资源配置等。) * 云环境的迁移 * 为什么放弃Linode? 1. 资源欠缺 Linode(tokyo地区)的机器资源实际是使用AWS的,在我们高速发展的阶段(频繁需要扩容)但是Linode经常提示没有实例可以提供。 2. 定价模式 Linode的机器都是按实例按规格按月结算,不论用多用少没有灵活的收费模式(主要还是因为我们穷) 3. 服务太单一 只提供VM,连IaaS都称不上,没有其他任何云服务。相比AWS,提供很多开箱即用的服务,能极大节省我们的精力和时间。 * AWS,使用了EC2、Loadbalancer、EIP、S3、CloudFront、Lambda。后期又陆续使用了ElasticCache、RDS、MailService等。

13 高速发展 IM系统的架构和改进(带图,细讲) 协议 传输 场景 * IM系统的架构和改进 * 协议 自己实现的轻量sync协议
inbox/outbox 单点消息推模式,群组消息拉模式,支持多端同步(app,web) 文本消息,图片消息(附带缩略图),语音消息(分片),短视频消息(附带首帧缩略图) 文本消息直接push,图片、语音通知后主动拉 支持消息状态,如『已达』『已读』 * 通信 Netty实现的TCP socket server,单机(AWS xlarge.m2配置)60万长链接,用于iOS/Android Netty实现的WebSocket endpoint,用于browser 二进制(Protobuf)和JSON均支持 跨server通信支持RPC式和异步队列,可手动切换;消息状态走异步队列,高峰期走异步队列; api server定期检查socket server的可用性并提供一个查询接口,移动端通过该接口来始终获取最新的可用endpoint 关于长链维系,调研了一些IM产品以及国内外不同运营商的网络品质,搞了套自适应心跳机制,做到了消息投递/通知时效性和power saver的平衡 和业务资源隔离,和相关业务有关系的资源通通异步更新。消息异步落地,投递时只写cache。 * 场景 * 其他

14 高速发展 * IM系统的架构和改进 * 协议 自己实现的轻量sync协议 inbox/outbox
细讲 * IM系统的架构和改进 * 协议 自己实现的轻量sync协议 inbox/outbox 单点消息推模式,群组消息拉模式,支持多端同步(app,web) 文本消息,图片消息(附带缩略图),语音消息(分片),短视频消息(附带首帧缩略图) 文本消息直接push,图片、语音通知后主动拉 支持消息状态,如『已达』『已读』 * 通信 Netty实现的TCP socket server,单机(AWS xlarge.m2配置)60万长链接,用于iOS/Android Netty实现的WebSocket endpoint,用于browser 二进制(Protobuf)和JSON均支持 跨server通信支持RPC式和异步队列,可手动切换;消息状态走异步队列,高峰期走异步队列; api server定期检查socket server的可用性并提供一个查询接口,移动端通过该接口来始终获取最新的可用endpoint 关于长链维系,调研了一些IM产品以及国内外不同运营商的网络品质,搞了套自适应心跳机制,做到了消息投递/通知时效性和power saver的平衡 和业务资源隔离,和相关业务有关系的资源通通异步更新。消息异步落地,投递时只写cache。 * 场景 * 其他

15 步入正轨 功能迭代非常快,数据增长非常快,需要周边系统支撑 这个阶段的架构变更(带图,细讲) 我们的日志分析 * 我们的日志分析
解决什么问题 怎么演进的 架构图(细讲) 场景 * 我们的日志分析 * 更细粒度日志的分类和梳理(业务日志,行为/访问/统计日志(包括HTTP、Service/RPC、Cache/DB等不同层次),一些BI用途的日志等) * 最早期crontab+rsync+grep/awk大法,简单够用;然后过渡到fluentd写mongodb(capped collection),web console提供展现和查询; * 最后过渡为ELK+kafka/redis的方案 * 架构图(再典型不过) * 根据使用场景不同和目的不同。其中部分由logstash收集写redis queue(这里引入redis queue中转的目的是提供日志内容的容错性,如es下线或维护时日志信息暂存。之后也有kafka替换了),之后由logstash再送入es做索引,展示到kibana上,这种大部分是无计算或少计算(聚合)的指标数据。es大家都很熟悉,它是基于lucene的,对于日志的所有字段都可以索引,并且其倒排索引的数据结构非常紧凑,搜索效率非常的高。反映到前端Kibana上,用户可以随意组合条件过滤日志,随意伸统计时间窗,秒级获取聚合计算结果。 * 需要做计算、统计类的日志数据(由logstash收集)写kafka,再由storm来消费。storm流式得做业务数据的聚合计算,主要是各种社交应用会遇到的数据统计场景,比如各种xx率,xx趋势,a/b test效果等等。数据驱动 * es目前数据节点和查询节点并没有分离(规模不到),目前还在使用http protocol模式 * 一些坑:开启doc_values;recovery和relocation的参数配置;默认的sharding策略shard总数均衡,不考虑IO。而做日志的时候,只有最近的索引的分片才有 IO 压力。所以如果你今天新上一个节点,然后隔天新建索引,一看,所有新分片全给分配到这台上,直接 IO 压垮。这个是有一个配置,针对索引级别的,可以对每个索引指定在单个节点上,最多分配几个分片。 * spark做业务数据方面的准实时计算, * kibana

16 步入正轨 细讲 * 我们的日志分析 * 更细粒度日志的分类和梳理(业务日志,行为/访问/统计日志(包括HTTP、Service/RPC、Cache/DB等不同层次),一些BI用途的日志等) * 最早期crontab+rsync+grep/awk大法,简单够用;然后过渡到fluentd写mongodb(capped collection),web console提供展现和查询; * 最后过渡为ELK+kafka/redis的方案 * 架构图(再典型不过) * 根据使用场景不同和目的不同。其中部分由logstash收集写redis queue(这里引入redis queue中转的目的是提供日志内容的容错性,如es下线或维护时日志信息暂存。之后也有kafka替换了),之后由logstash再送入es做索引,展示到kibana上,这种大部分是无计算或少计算(聚合)的指标数据。es大家都很熟悉,它是基于lucene的,对于日志的所有字段都可以索引,并且其倒排索引的数据结构非常紧凑,搜索效率非常的高。反映到前端Kibana上,用户可以随意组合条件过滤日志,随意伸统计时间窗,秒级获取聚合计算结果。 * 需要做计算、统计类的日志数据(由logstash收集)写kafka,再由storm来消费。storm流式得做业务数据的聚合计算,主要是各种社交应用会遇到的数据统计场景,比如各种xx率,xx趋势,a/b test效果等等。数据驱动 * es目前数据节点和查询节点并没有分离(规模不到),目前还在使用http protocol模式 * 一些坑:开启doc_values;recovery和relocation的参数配置;默认的sharding策略shard总数均衡,不考虑IO。而做日志的时候,只有最近的索引的分片才有 IO 压力。所以如果你今天新上一个节点,然后隔天新建索引,一看,所有新分片全给分配到这台上,直接 IO 压垮。这个是有一个配置,针对索引级别的,可以对每个索引指定在单个节点上,最多分配几个分片。 * spark做业务数据方面的准实时计算, * kibana

17 步入正轨 功能迭代非常快,数据增长非常快,需要周边系统支撑 这个阶段的架构变更(带图,细讲) 我们的监控/告警 我们的搜索 * 我们的搜索
解决什么问题 怎么演进的 架构图(细讲) 场景 我们的搜索 架构(细讲) 局限性 * 我们的搜索 * elasticsearch * zone) * 架构图 * 我们的监控/告警 * 最早期是依赖各组建或系统的stat功能,直接在terminal中输出,之后改为基于munin的监控,munin提供各类plugin(python/perl/shell)同时也非常方便自己扩展, * 最终到了zabbix(下一步准备迁到openfalcon)? * OS层面,cpu、load、mem、io等的监控和告警都有云基础设施完成,AWS上的cloudwatch+mailservice * 基础设施层面,memcache、redis、mongo、MySQL等 * 应用层面,容器,jvm状况,其他jmx扩展(如socket server中队列堆积,kafka中jmx数据项)等 * kibana

18 步入正轨 * 我们的搜索 * elasticsearch * spatial@mongo+redis(geohash zone) * 架构图
细讲 * 我们的搜索 * elasticsearch * zone) * 架构图 * 我们的监控/告警 * 最早期是依赖各组建或系统的stat功能,直接在terminal中输出,之后改为基于munin的监控,munin提供各类plugin(python/perl/shell)同时也非常方便自己扩展, * 最终到了zabbix(下一步准备迁到openfalcon)? * OS层面,cpu、load、mem、io等的监控和告警都有云基础设施完成,AWS上的cloudwatch+mailservice * 基础设施层面,memcache、redis、mongo、MySQL等 * 应用层面,容器,jvm状况,其他jmx扩展(如socket server中队列堆积,kafka中jmx数据项)等 * kibana

19 步入正轨 功能迭代非常快,数据增长非常快,需要周边系统支撑 这个阶段的架构变更(带图,细讲) 我们的服务框架(RPC)和配套设施
场景 架构图(细讲) 目前数据 我们的异步/定时任务框架 架构(细讲) 局限性 * 我们的RPC框架和配套设施 * 改造thrift,在thrift的骨架之上做了failover、loadbalance策略,降级开关,请求统计和性能采用,服务注册和发现(zk/curator-receipe) * rpc服务的注册和发现使用zookeeper+curator * 架构图 * 我们的异步/定时任务框架 * 早期crontab,后来使用Quartz封装了一套简单的任务框架 * 支持任务手工触发,任务结果通知,任务结果验证等 * 主要任务都是和产品运营相关的,类似于离线任务,大量的读和内存计算

20 步入正轨 细讲 * 我们的RPC框架和配套设施 * 改造thrift,在thrift的骨架之上做了failover、loadbalance策略,降级开关,请求统计和性能采用,服务注册和发现(zk/curator-receipe) * rpc服务的注册和发现使用zookeeper+curator * 架构图 * 我们的异步/定时任务框架 * 早期crontab,后来使用Quartz封装了一套简单的任务框架 * 支持任务手工触发,任务结果通知,任务结果验证等 * 主要任务都是和产品运营相关的,类似于离线任务,大量的读和内存计算

21 下一步的方向 基于公有云环境的容器化架构 跨机房高可用 通信协议的改进 业界怎么做的 我们的架构愿景
依赖AWS的跨区域avaiable zone 虚拟网络 通信协议的改进 多端同步 周边

22


Download ppt "Mico的架构之旅 魏佳 Co-Founder & CTO @ Mico Inc.."

Similar presentations


Ads by Google