雷锋网按:技术圈流传这样一句话“人工智能背后的架构和工程问题是武当少林,属于内功。而算法则是招式,讲究一时之快。”
再强的算法均需强大的架构和工程作支撑,两者缺一不可。
那么 AI 公司该如何设计承载产品背后庞大复杂的算法、工程核心架构?本期雷锋网 AI 科技评论特邀极限元 CTO 康利强为大家讲述《AI 公司该如何设计基于微服务的 AI SaaS 架构》。
康利强,极限元 CTO,亲自主导搭建了支撑极限元现有语音识别、计算机视觉、人机交互解决方案的构架;20 年软件研发、架构设计以及项目管理经验,前亿赞普集团核心架构设计专家;美国 Borland 软件公司中国机构分布式存储架构师及项目负责人。
如想获取本期公开课的 PPT 资源,关注雷锋网 (公众号:雷锋网) 人工智能垂直微信公众号“ AI 科技评论”,在后台回复关键词“架构”,即可收到本期公开课 32 页的 PPT 下载链接。
以下为分享正文:
今天我给大家分享的内容是,基于微服务的 AI Saas 架构设计。
既然要设计 SaaS 架构,先要了解何为 Saas?SaaS 是云计算的一种服务形式,关于云计算,我先简要做个介绍:
什么是云计算?
云计算的分类(分层)
云计算新的服务方式
云计算是一种计算资源,按量付费,也就是你用多少就支付多少费用,可以便捷的访问,通过网络进入可配置的资源池,(资源包括网络,服务器,存储,应用软件,服务),这些资源能够被快速提供,我们只需投入很少的管理工作,或与服务供应商进行很少的交互。
2006 年 8 月 ,Google 提出云计算的概念,到今天经过了 10 年的发展,云计算越来越为大家所接受,很多人也在使用云计算提供的服务,比如云主机、云存储、网盘、云分发、云笔记等等;今天的直播也会用到其中的几项服务,比如云存储、云分发,由于用到云分发,所以大家在看直播的时候会有一个比较低的延时。
接下来介绍 SaaS,除了SaaS 外,云计算也包含其他几种类型:
主要有以下几种类型:
IaaS(Infrastructure-as-a- Service):基础设施即服务。消费者通过 Internet 可以从完善的计算机基础设施获得服务。也就是云主机,比如亚马逊云,微软云,阿里云等。
PaaS(Platform-as-a-Service):平台即服务。PaaS 实际上是指将软件研发的平台作为一种服务,以 SaaS 的模式提交给用户。因此,PaaS 也是 SaaS 模式的一种应用。PaaS 的出现可以加快 SaaS 的发展,尤其是加快 SaaS 应用的开发速度。需要用户有一定的开发能力,比如谷歌的 GAE。
SaaS(Software-as-a-Service):软件即服务。它是一种通过 Internet 提供软件的模式,用户无需购买软件。例如:各种云存储,网盘、云笔记。
近些年随着 Docker 的发展,出现了一种新的服务形式:CaaS。
CaaS (Containers-as-a-Service): 容器即服务这是随着近几年docker的火热而出现的一种新的服务形式, 使应用的打包与部署自动化,创建轻量、私有的 PAAS 环境,使持续集成/部署、测试自动化,部署可伸缩的 web app、数据库和后台服务。
因为 docker 基于 Linux Container(Namespace,cgroup,chroot等),抽象出 Libcontainer 的接口,docker 运行于 Libcontainer 接口之上而不关心底层实现,所以这种服务就叫做 CaaS。
这是一个简化版的云计算分类,通过这个图可以一目了然看到它们之间的关系。
既然讲架构设计,所以要了解一下架构模式,题目是基于微服务的架构设计有微服务,那么是不是有宏大的服务呢,答案是肯定的。
一般来说,有以下两种架构模式:
单体式架构(Monolithic Architecture)
微服务架构(Microservices Architecture)
下面我们来看一下单体式架构:
单体式架构就是所有功能打包运行在一个进程,比如一个war包,从这个架构图我们也可以看到,这是一个叫车应用,中间部分是一个整体,包含很多功能,有乘客管理,通知,支付,司机管理 ,路线规划等功能。
优点是开发,部署,测试,水平扩展比较容易,可以放到一个工程,打一个包,扩展的时候只把这一个包复制到新的位置即可。缺点就是随着功能增多,代码变多, 维护成本高,交付周期长。
与此同时,不同模块发生资源冲突时,扩展将会非常困难。造成资源的浪费,有的要大内存,有的高带宽,有的要大的存储空间等。为了同时满足这些条件,这样就造成了资源的浪费。
还有一个问题是,技术选项成本高,必须谨慎选择,因为一旦选定很难更改,如果要更改的话,肯能要全部推到重来。另外可靠性也存在问题,一个模块故障会影响整个服务。
在了解微服务之前,首先了解什么是微服务,其次需要了解微服务架构的设计要点,最后需知道微服务的优缺点。先看一下什么是微服务?
微服务没有一个公认的确切定义,但是有一些共性,微服务是是面向服务架构的一种特例,有以下特性:
容易替换(升级)。
服务轻量级,可独立部署,构建发布自动化。
与其他服务通过网络协作完成任务。
根据功能来划分服务,比如用户前端,推荐,物流,账单等。
可以用不同的语言、数据库、软硬件实现。
所以微服务本身天然就具有模块化特性,适合于持续交付的开发部署,业务改变只需要重新发布部署少量的服务。了解微服务以后,进入今天的主题:为微服务架构设计。
我们知道,人工智能的核心是机器学习,因为机器不会自己学习,所以要明确指明一些特征来让机器知道符合这个条件的是什么,符合那个条件的是什么,这就需要编写复杂的程序来让机器来学习,在某些场合,随着需要的特征约来越多,编写程序越来越困难,我们无法用足够实用并且可靠的方式明确指定所要优化的特征。
以让机器识别一只猫为例,假设这只猫是白色的,先不考虑其他特征,只说颜色特征。其它特征+白色这两个特征让计算机知道这是一只猫,那么来一只黑色猫就不认识了,或者来一只加菲猫计算机就有可能就会把它识别成色情图片了。
这就导致所需的特征越来越多,这时候发现程序没法写了。于是深度学习顺势而生,大量数据通过深度神经网络的训练,让计算机学习,机器会自己提取特征并跟测试集来比较,然后自己调整进行下一轮的训练,直到训练出合适的结果。所以说目前的 AI 更多是数据的比拼。
首先我们要了解 AI 能做什么,AI 可以做一些色情检测、广告检测、涉爆涉恐言论以及电信诈骗检测,这些都是 AI 可以做的事情。用 AI 来做的话可以节省大量的人力,但是,不是所有公司都有能量构建 AI 系统,从上图中可以看出,构建 AI 系统需要大量数据,需要大量计算资源,需要专业技术人员。
所以随着社会分工越来越细,专注于自己的业务,专业的事情交给专业的公司来做就好,避免自己精力过于分散。以直播平台为例,其需要检测上面所述的一些违规内容,也可以用 AI 来检测。但是不一定要自己做 AI 系统,你可以把更多的精力放在直播的流畅度、延时、互动性等提升上。
由于 AI SaaS 需要提供多种服务,不同的服务需要不同的计算资源,AI 算法需要 GPU 资源,所以微服务的架构更适合 AI SaaS。
传统的架构设计一般从这 5 个方面来设计,所谓的五视图:逻辑架构,开发架构,运行架构,部署架构,数据架构。
逻辑架构主要是考虑需求,并根据职责划分逻辑层,子系统、子模块儿,同时考虑模块儿的接口。
开发架构:源文件管理,工程组织方式,依赖的库、框架,以及构建系统。
运行架构:子系统需要几个进程,进程之间怎么通信,以及怎么启停。
部署架构:系统的物理架构,需要那些服务器,服务器之间的网络拓扑结构,以及系统运行到那些服务器上。同时还需要考虑冗余,因为系统出问题是必然的。
逻辑架构是根据需求划分的几个逻辑层,主要分为接入层,业务层,存储层,管理层,这几层分别有不同的服务。
上面讲到逻辑架构要根据需求划分子系统,子模块,以及定义模块的接口。对应的微服务架构的话就是怎么根据需求分解成微服务,以及怎么定义服务间的通讯接口。与单体应用不同的是还需要确定服务的位置,所以需要服务定位。此外,由于微服务通过网络来访问,所以需要有对应的故障处理机制。
所以下面就从服务的划分,接口设计,服务定位(注册与发现),故障处理来讲解一下逻辑架构。
第一,服务的划分,服务划分的原则跟面向对象设计原则基本一致,单一职责,高内聚,低耦合。我们知道对于需求来说分为功能性需求跟非功能性需求,那么微服务也按这种方式来划分。
API Server api 的接入,认证,负载均衡。
Service Registry服务注册与发现。
AI 网关:AI 服务的流量控制与负载均衡。
AI 服务:提供 AI 服务,比如图像识别,语音识别等。
计费服务 计费的管理
文件服务 存储文件
缓存服务:提高性能
监控服务:监控系统及应用的情况
日志服务:应用日志收集分析
接口设计分为:对外接口,内部接口。为了方便多语言的开发,所以对外提供 http 协议接口,不一定完全按照 REST ful 去设计,根据业务确定。每个请求需要确定访问者的身份,而 http 无状态,故可以用 JSON Web Token(JWT) 来做认证。
内部调用分为两种:同步调用,异步调用。
同步调用可以这几种方式去做:REST API ,RPC框架,比如 thrift,gRPC 等,或者可以基于 PB 自定义通讯,当然也可以完全用完全自定义的协议,根据公司开发资源灵活选择。
异步调用主要是通过消息队列去做 (RabbitMQ,RocketMQ,kafka,NSQ)等。
既然有这么多服务,这些服务有会同时存在好多实例,那么怎么去定位这些服务也是一个要解决的问题。
这就是服务定位,也就是服务注册与发现。
为什么需要定位呢,一是服务位置的变化,另一个就是数量的变化。服务位置可能会变化由于某些原因要迁移到不同的 ip 地址,数量会变化,比如增加一台服务器,需要对外提供服务,就要告诉网关,如果用固定配置文件方式就会比较麻烦,所以需要动态的去获取服务的位置。
现在常用的几个开源服务包括 ZooKeeper、Etcd、Consul 等,服务启动注册到注册表服务,当一个请求到来时,网关去注册表查询。服务位置,然后把请求转发到其中某一个服务,服务与注册表服务之间会定时检测,如果一个服务挂了,那么就会从注册表删除,同时通知网关,这样就可以避免访问到失败的服务。而如果有新加入的服务,它会注册到注册表,网关也会收到通知,这样请求就可以转发到新服务,不需要手工做任何的配置。
刚才提到服务挂了注册表会检测到,但是并不是实时的,所以这个时候的调用就会失败,那怎么处理这些调用失败呢?通过故障处理这节我们有以下这些处理方式。我们可以看到有超时机制、限流、熔断机制、负载均衡、降级(本地缓存)。在解释这些处理机制之前我,我们先通过这个图看一下如果出现故障,不管是服务挂了也好,网络断了也好,还是访问量太大处理不过来,会发生什么情况,会造成服务不可用,没法处理新的请求。
这种情况的第一个处理方式就是超时机制,就是每个调用都要有个超时时间,防止资源被无限制的占用,这样避免影响后面的调用。如果流量太大处理不过来,就可以通过限流来处理,比如用请求队列大小来限制访问量,避免访问量过大造成服务不可用,就像早期的 12306,想必刷过票的都有体会。
断路器模式:就是先跟踪成功、失败调用的次数,当比率达到设定的阈值,打开断路器,后续的调用就会立即失败,这时候断路器会启动一个定时器,来给服务器恢复服务,计时器时间到了就会去允许一定数量的请求操作,而不是立即返回失败,如果全部调用成功就关闭断路器开始正常服务,否则继续启动定时器,进入下一个循环。
负载均衡方式:后面对应多个服务实例,一个服务失败会自动切换到另一个,这也是一种故障处理方案。某些业务情况直接返回错误可能不太友好,所以可以返回缓存的数据,或者返回默认的数据,比如别人发了朋友圈,你刷新的时候还给你返回旧的数据,也不会影响你的体验,过一会儿再一刷,他就出来了。逻辑架构这部分就结束了,上面所说的这些功能都是需要开发来实现的,所以下面我们看一下开发架构。
开发架构主要是一些软件资源以及人员的问题。随着开源软件的发展,它们可以减少我们大量的工作,我们有许多服务,这些服务之间需要通讯,所以可以选择一些通讯框架,比如 netty,libevent 等,这样可以减少很多工作量,提高效率。还有一些开源应用可以直接使用,如 nginx,redis,mysql,prometheus,grafana 等。
nginx 可以用作反向代理,redis 用于缓存,mysql 作为数据库,Prometheus,Grafana 用于监控。
源码版本控制可以直接用 gitlab 社区版,当然也可以用 GitLab 收费版。如果完全开源,那么也可以直接用 GitLab 的免费服务。
Bug 管理选择 redmine,当然也可以用 jira,那就需要不少的费用。
人员方面根据团队擅长的语言,比如 Java,可以做网关,计费系统等,而 AI Server 通常用 C++ 去做,当然有些应用也可以用 Go 语言做,如 prometheus 就是用 Go 写的。
主要有一下几个进程,如图所示,请求的流程如图所示。
确定了运行的服务,那么接下来我们来看看怎么部署这些服务,也就是服务的部署架构。
首先看下怎么部署:
每个主机一个 Service 实例,这些主机可以是真实主机、虚拟机、容器、Docker。部署的时候要考虑灾备,可以同一个服务部署多个实例。对于微服务来说,由于服务数量比较多,手工部署比较繁琐,也容易出错,所以需要一些自动化的部署工具。比如 puppet,saltstack,chef,ansible,k8s(kubernetes) 是 Docker 的编排工具。CoreOS 提供 docker 的运行环境,精简版的 Linux,很快的可以部署出一个系统出来,包括一些 Marathon/Mesos。
API Gateway 对外提供服务,所以需要高带宽,AI 服务部署到 GPU 计算资源的主机。文件服务部署存储空间大的主机,缓存服务需要内存大的主机。所有应用都部署在云上,方便扩容。
雷锋网原创文章,未经授权禁止转载。详情见 转载须知 。