工做上项目的后台进行微服务改造后已经平稳运行将近1年了,起初项目为若干个单体web应用组成,以后因为上线App,需求的多样性和对于需求的响应速度有了更高的要求,所以为了快速响应需求变化,将后台进行微服务化改造。总的来讲,改造初期因为既有系统我都很是熟悉,所以改造和迁移都比较顺利。在微服务架构的帮助下,新接入业务能够更专一于服务的实现,同时各个服务的功能也能够进行快速整合。目前平台的研发告一段落,后期工做可能调整,所以趁有时间把最近一年的改造设计、研发、部署、迁移、运维等各个部分的经验大体整理一下,不说虚的,不列名词,具体代码尽可能不说(网上一堆),只说经验与想法。nginx
因为是生产中正在运行的系统,所以有以下几个要求必须知足:git
对于既有后台的若干服务的功能和模块进行整理,首先应该梳理出公共功能部分,能够做为独立的服务模块对外提供服务,其次对于其它功能梳理出关键功能(必须切换、必须保证过分、历史数据不能丢失……),对于非关键功能,在时间紧张的时候能够先维持既有系统运行,在微服务平台切换后期再进行研发,并转入新的后台中。web
以我如今的项目为例,redis
1)公共服务包括:算法
2)关键服务包括:spring
3)非关键服务包括:sql
综上,咱们根据梳理的服务类型,优先实现公共服务和关键服务,在合适的时候进行总体迁移。在主体服务迁移完毕,平稳运行后便可进行后续功能的迁移与改造。数据库
系统研发过程当中,应充分考虑既有系统的兼容性,并准备好关键数据的转移方案。对于有大量修改的系统和数据,考虑经过兼容接入服务处理旧的应用请求,而新的业务请求直接根据新的数据和逻辑开发。api
在平台改造时,应该充分考虑能力冗余。数据库、缓存、消息队列、分布式文件系统、目录服务、负载均衡、ElasticSearch集群等服务平台的基础组件应该进行资源的合理划分。好比:缓存
用户设备端经过互联网最终到达内部应用服务须要通过多道关卡,经过合理的层级划分,能够对各层功能进行划分,也有助于整理平台结构。
从外到内的层级以下:
互联网-> CDN -> 防火墙 -> 负载均衡 -> Api网关 -> 接入层服务 -> 内部服务
1) CDN
在这里配置外部CDN数据、资源缓存,能够有效减轻源站压力。
2) 防火墙
在这里配置安全防御设施,风控平台等组件。用于拦击恶意访问行为。
3) 负载均衡
在外部通道、端口有限的状况下,经过负载均衡进行端口转发,将不一样应用请求分配到不一样的应用实例上,同时也起到在高可用部署下将请求有效分配至有效节点的做用。
4) Api网关
在这里咱们使用的是Spring Cloud全家桶,所以网关选用Zuul。 在咱们的场景下,网关的做用包括:
5) 接入层服务
直接对接用户设备或者第三方服务器,不直接访问数据库等基础设施,而是经过访问内部微服务整合数据,最终对外提供服务。同时在新老系统过渡期间也能够起到兼容适配的做用。在这里须要应用必要的安全防御措施,对于接口类型的服务,若在网关以后则无需另外配置,如果独立的Web应用,则应该搭配Spring Security等组件进行使用。
6) 内部服务
外部网络没法直接访问内部服务的接口。内部服务仅能被接入层服务、内部其它服务调用。
eureka, config-server, zipkin, hystrix-dashboard,spring-admin(这个咱们没有采用,可是装了无妨) 都是有必要部署的。
其中有些须要注意的地方,配置不合理可能影响平台内的应用性能。
1) zipkin
2) config-server
3) eureka
4) hystrix
1) 数据库
基本须要作到读写分离、按期增量备份、按期全量备份便可,暂时没有遇到极端性能要求的场景。可是最好隔离应用,并把关键应用的数据库独立部署。
2) redis
作好cluster和高可用配置,同时在应用层面作好redis失效时候正常提供服务的准备。
3) 消息队列
个人场景下安装了RabbitMq和Kafka,各个业务应用根据实际需求使用不一样的队列便可。在个人场景下,对于应用之间的结偶和缓冲我使用的RabbitMq。Kafka仅做为ELK中的队列部分。
4) 日志采集
采用ELK方案: ElasticSearch + Logstash + Kibana的方案,同时logstash的Producer和Consumer间采用kafka队列。这里 FireBeat应该是更好的选择。
服务平台涉及多个应用服务,须要基本的Maven配置,将各个类型的服务应用进行划分,以减小各个应用开发时候的配置工做量,同时也避免了没必要要的组件应用。
咱们的场景中分为: parent, common, aop, front-end, service, api, util等项目类型。
参看阿里巴巴的规范文档便可,在多人协做开发的状况下是十分必要的。
人员配置容许的状况下,像3.1中的api项目最好由有经验的开发人员统一设计,对各个业务服务的对外接口进行抽象和整合,同时严格遵照接口的版本定义规范,以最大限度的达到服务在接口层面的稳定。不然api若频繁变更,连带的调用服务都得跟着升级,很是不利于系统稳定,同时也很容易出现因为人员疏忽形成的服务间api版本不统一而出现服务异常。
不论何种类型的部署,最好在接入层之上配置好nginx,这样实现基本的流量切换、灰度测试等功能,实现平滑过渡。
对于新增业务能够直接在测试环境/生产环境部署,不会影响到既有应用的运行。
在nginx之下的服务(好比网关)能够直接重启,若要保险一点,则应该先把nginx的upstream中须要升级的服务踢掉再重启。
在微服务体系内的其它服务因为是客户端的负载均衡,所以不能直接重启,这样会致使其它应用调用时候至少出现一次调用异常。正确的方法应该是发送Shutdown命令至服务,这样服务能够在关闭的同时删除eureka中自身的信息,其他的应用就不会再调用这个实例。
因为老系统接口数据结构不一样,能够在接入层进行数据转换适配后提供服务。