本文来说下springcloud微服务框架是如何进行服务治理的

文章目录

  • 概述
  • 技术架构实现
    • 服务注册与发现:Eureka集群
      • 实践经验
    • 统一接入网关:Zuul
      • Zuul1 or Zuul2,同步or异步
      • 实践经验
    • 服务RPC调用:Feign
      • 自动降级熔断:Hystrix
      • 断路器机制
      • Fallback
      • 资源隔离
      • 实践经验
    • 接口调用链分析监控:Zipkin
      • 实践经验
    • 应用服务监控SpringBootAdmin
      • Metrics
      • Environment
      • Logging
      • JMX
      • Threads
      • Trace
      • Heapdump
  • 敏捷开发运维保障
    • 运维保障
    • 持续集成CI & 持续部署CD
  • 总结与展望
  • 本文参考

概述

关于微服务的介绍目前已经有很多文章做了介绍,本文不再对微服务的概念再做进一步阐述,重点将介绍微服务架构具体开发运维方面的经验总结,侧重于落地实践。

目前业界比较热门的微服务开发框架是SpringCloud和dubbo,由于前期一些项目已经使用了SpringBoot进行快速开发,自然就平滑地升级到SpringCloud进行微服务实践。另外,按照微服务不断演进的思路,我们首先对非核心业务和新业务进行了重构,不断积累微服务开发运维经验,待后续时机成熟,再对核心业务进行微服务重构治理。


技术架构实现


开箱即用的特性使得SpringCloud比较容易上手,需要哪个功能,就通过maven引入响应子系统组件,符合各个层次的使用者,也符合各类不同应用场景特点。微服务改造是一个渐变的过程,不必一开始就使用所有功能。按照目前自身的技术条件与保障能力,同时参照应用自身特点,我们使用了如下几类组件,下面分别进行详细说明。


服务注册与发现:Eureka集群

目前SpringCloud支持的服务注册有Consul和Eureka。Consul需要独立部署,脱离Spring框架;而Eureka天然集成在SpringCloud中,本身就是一个SpringBoot项目。这2者特点可以通过如下表展示。


可以看出,Consul在整体功能上比Eureka更加丰富和完备,但同时也增加了一定的复杂性;Eureka相对来说更加轻量,天然溶于SpringCloud体系,虽然缺失一部分功能,但是对于一般性的微服务集群来说已经足够。因此,我们采用了Eureka来作为服务发现与注册组件。下图为目前已经接入Eureka组件的所有拆分的微服务实例。目前来看,数量还不算太多,后期随着业务的发展,会不断增加微服务实例。如下图3所示:


实践经验

从业务量上来说,一个数据中心站点上,一般挂载2个实例做负载均衡即可满足一般业务需求,但在一些请求量较大的服务上,我们会增加微服务的实例数量。例如对于我们的一个行情增值微服务组件,由于早高峰tps接近6000,就挂载了6个实例。因此通过实际业务量的请求数据监控,我们可以动态调配微服务组件的挂载实例,从而满足业务需求,保障服务的HA,同时提高了系统资源的使用效率。

对于Eureka服务本身来说,也是挂载了2个实例,通过客户端的Failover协议同时配置2个实例,来实现服务注册的高可用。需要在每个注册到Eureka集群中微服务组件均增加此配置即可:eureka.client.serviceUrl.defaultZone=http://ip1:20001/eureka/,http://ip2:20001/eureka/。

如果超过2个Eureka实例,则通过继续以“,”分隔连上。这点来说,和ActiveMQ的连接使用异曲同工。

从我们实际运行来看,目前Eureka组件应用逻辑简单、稳定。当一台Eureka Server实例down机后,所有client实际均不受影响。当然从Eureka自身来说,也存在弱一致性的问题,特别是对于微服务节点在重启时候,可能会存在某服务在一个心跳周期不可用的情况,待心跳超时隔离以后,就恢复正常了。其实这也是为了最大程度保证可用性,可见确实只满足了AP。官方目前Eureka2.X版本将不再开源,基于此考虑,后续我们也会持续关注替代方案Consul,或者其他服务注册框架。


统一接入网关:Zuul

所谓“一夫当关,万夫莫开”,统一接入网关组件作为服务的统一入口,地位足够重要。Zuul网关主要实现了请求服务路由、负载均衡、统一校验等功能。在服务路由和负载均衡方面,和nginx相当类似。Zuul通过自身注册到Eureka,通过url匹配的serviceID配置,即可实现服务路由。

目前我们在Zuul网关中实现了校验token功能,通过ZuulFilter,可以轻松做到所有外部请求的token统一校验。目前还没有把其他校验类逻辑放到Zuul中,一些请求流量统计的功能,我们在nginx层面做了拦截实现。


Zuul1 or Zuul2,同步or异步

Zuul2版本已经与今年5月份发布,相比于Zuul1,其强大的事件驱动和异步非阻塞调用特性,将支持超高并发接入并转发。其核心是引入了高性能netty框架,从请求接入到调用外部组件,全部采用netty事件驱动模式来实现。而Zuul1则采用传统servlet同步请求的方式进行处理,每个连接分配一个线程,所有的线程均从线程池中获取,一旦外部连接并发量很大的话,线程数将急剧上升,一旦处理线程阻塞,则最终将耗尽容器中的线程池内的线程,造成容器无法继续接受新的请求,因此才有了Hystrix熔断组件来解决服务耗尽资源的解决方案。

虽然Zuul1的同步阻塞带来了吞吐量的瓶颈,但是整个处理模块比较简单,从请求接入到处理,再到响应,整个流程都在一个线程中处理,方便了开发和调试跟踪。而Zuul2则将接入请求全部放入netty的事件队列中,并分别由不同的线程进行接入、处理、响应,从维护和跟踪上面来看,更加复杂和难维护。

其实对于一般的应用场景来说,并发量不会太大,其实用Zuul1就能够满足要求,而且开发维护更简单;但是如果面对高并发的应用场景,例如QPS>1000时,则建议采用Zuul2,其异步非阻塞特性,将轻松接入高并发连接,并配合其EventLoop和pipeline机制,可以保证所有的连接都能被接收和处理,基本不存在连接被拒绝访问的情况。

从Netflix给出的性能结论来看,Zuul2的性能比Zuul1大致提升了20%,可见从吞吐量上面来说,提升能力有限;但是比较明确的是,Zuul2的连接数管理方面要明显好于Zuul1,可以支持超大规模的并发连接处理。从这点上面来说,其性能应该接近于Nginx。可参考如下Zuul演进图4.


实践经验

目前实际项目中,生产系统还是以Zuul1来作为API网关使用。因为目前我们只是对于内部系统API、外部一些核心低频API调用走Zuul,并发量不太大,还能扛住;对于外部应用的一些高并发API调用,例如行情相关的接口QPS>6000,还是从Nginx接入,直接转发到SpringBoot微服务组件。

从未来趋势来看,为了实现微服务的全覆盖和完整性,后期将把nginx的接入请求全部转到Zuul上来,到时将必须升级到Zuul2上来,没的说。


服务RPC调用:Feign

Feign是一种http方式的声明式调用,目前SpringCloud默认使用java原生的HttpURLConnection进行http调用,同时通过jar包引入还可以支持Apache的httpclient、OKhttp等。Feign底层依靠Ribbon实现了调用各个实例的负载均衡,从效率上面来说,不占太大优势,但是从简单易用上面来看绝对是一个重要的亮点;而且和自动熔断降级组件Hystrix天热融合,优势明显。使用Feign非常简单,只需要创建一个调用服务的接口方法,标记@FeignClient即可像本地方法一样调用。


自动降级熔断:Hystrix

在微服务集群中通常会有很多个服务之间的调用,例如通过Feign调用。各个服务之间的调用最终形成了网状模型。如果某一些基础服务不可用,而上游服务持续不断调用此基础服务,可能导致整个系统故障,也就是“雪崩效应”。下图5展示了常见的场景。


断路器机制

断路器很好理解,当Hystrix Command请求后端服务失败数量超过一定比例(默认50%),断路器会切换到开路状态(OPEN)。这时所有请求会直接失败而不会发送到后端服务。断路器保持在开路状态一段时间后(默认5秒),自动切换到半开路状态(HALF-OPEN)。这时会判断下一次请求的返回情况,如果请求成功, 断路器切回闭路状态(CLOSED),否则重新切换到开路状态(OPEN)。Hystrix的断路器就像我们家庭电路中的保险丝,一旦后端服务不可用,断路器会直接切断请求链,避免发送大量无效请求影响系统吞吐量,并且断路器有自我检测并恢复的能力。


Fallback

Fallback相当于是降级操作。对于查询操作,我们可以实现一个fallback方法,当请求后端服务出现异常的时候,可以使用fallback方法返回的值。 fallback方法的返回值一般是设置的默认值或者来自缓存。例如在一个热门推荐股票榜单功能中,如果Feign调用失败,则自动在Fallback中返回本地缓存中的默认榜单即可,成功实现了推荐榜单服务的降级。


资源隔离

在Hystrix中,主要通过线程池来实现资源隔离。通常在使用的时候我们会根据调用的远程服务划分出多个线程池。例如调用产品服务的Command放入A线程池,调用账户服务的Command放入B线程池。这样做的主要优点是运行环境被隔离开了。就算调用服务的代码存在bug或者由于其他原因导致自己所在线程池被耗尽时,不会对系统的其他服务造成影响。但是带来的代价就是维护多个线程池会对系统带来额外的性能开销。如果是对性能有严格要求而且确信自己调用服务的客户端代码不会出问题的话,可以使用Hystrix的信号量(Semaphores)来隔离资源。

例如,在我们实际生产系统中,如果服务调用不太频繁时,减少线程数量,节约系统资源,可以在配置文件中显示设置隔离线程池的线程规模=2:hystrix.threadpool.default.coreSize=2。


实践经验

由于Feign组件集成了Ribbon和Hystrix,其服务降级和熔断的参数配置较为复杂,如果不看完源码,则只能靠系统测试来一一验证了。例如服务调用超时这类场景,其默认的服务超时设置为1秒,这对一些外部较复杂的服务调用来说是不太合适的,因此需要在配置文件中显式声明hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000,将其扩大到5秒超时。另外对于服务的重试次数,也需要进行谨慎设置,一旦被调用方服务没有做好幂等性防护,可能会带来意想不到的破坏。


接口调用链分析监控:Zipkin

Zipkin 是一个开放源代码分布式的跟踪系统,由Twitter公司开源,它致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。每个服务向zipkin报告计时数据,zipkin会根据调用关系通过Zipkin UI生成依赖关系图,显示了多少跟踪请求通过每个服务,该系统让开发者可通过一个 Web 前端轻松的收集和分析数据,例如用户每次请求服务的处理时间等,可方便的监测系统中存在的瓶颈。

Zipkin提供了可插拔数据存储方式:In-Memory、MySql、Cassandra以及Elasticsearch。下图6为我们实际场景中的一个接口的调用链分析。


上方的图形展示了3个微服务之间的调用关系;下方的甘特图则展示了调用链的各个服务耗时分布。对于分析调用链层次多的复杂接口具有很好的分析作用。


实践经验

在我们实际系统中,对于接口的采样率有个配置:spring.sleuth.sampler.percentage=0.2,表示只采样20%的接口入库存储可展示,对于接口请求量巨大的应用来说,避免接口量太大消耗太多内存。


应用服务监控SpringBootAdmin

SpringBootAdmin提供了开箱即用的监控工具箱,可以看各个注册在Eureka下个微服务实例的运行全貌,如下图7所示。首先在面板上面展示了所有能监控到的应用实例,具体到IP和端口。Status包括UP和DOWN,分别表示正常启动和未启动。


点击detail可以进入应用的详细监控页面。在详情页面概览中包含了应用的全貌信息,包括JVM占用的内存情况、类加载、GC、DataSource数据库连接占用情况快照,如下图8所示。还提供有实时刷新功能,每隔一秒动态展示系统的快照,比JavaVisualVM和jConsole更加方便和直观。我们用的较多的是DataSource连接数占用情况分析,如果Active连接数长期占用率较高,就必须考虑应用对数据库的优化了。



在监控详情页面中,还可以看到Metrics、Environment、Logging、JMX、Threads、Trace、Heapdump几个栏目。


Metrics

Metrics主要展示了接口调用次数和耗时统计(Counter和Gauges),便于查看微服务内部接口的运行情况。如下图9所示。


Environment

主要提供该服务的所有配置项。包括系统层级和应用的配置列表。


Logging

提供动态改变应用log打印级别的功能。在系统出现异常而没有查到有效日志的情况下,可以动态调整logging的日志级别,例如调整为debug级别,可以让应用立即以debug级别进行日志打印,方便查看系统详细异常情况。其实底层还是使用了JMX实现,需要在logback配置中增加jmx支持配置,如下图10所示。


JMX

JMX栏目将显示应用所有JMX对象,如果有一些自定义的JMX MBean,可以通过此处操作动态执行操作,实现应用配置的动态热变更,如下图11所示。


Threads

主要提供当前线程堆栈的快照信息。通过查看线程全貌快照,可以看到当前所有线程的运行状态,如果发现某类线程组全部都属于running,可能需要扩容线程池。如果发现大部分线程高峰期一直都是waiting状态,可能需要缩减线程池规模。如果发现大部分线程都在等待某一类资源对象锁,则表示该类资源存在瓶颈,需要进行优化调整。合理的调整各类线程池规模,可以让系统运行的更高效,提高系统资源利用率,如下图12所示。


Trace

主要提供对外接口的实时运行快照。在此不做详细说明。


Heapdump

主要提供了实时获取内存堆栈快照的下载功能。如果发现应用占用内存一直很高,GC释放效率低,则可以通过查看内存堆栈快照,作进一步分析,哪些大对象没有及时释放。


敏捷开发运维保障

运维保障

微服务的正常运转离不开配套的监控体系和敏捷DevOps,大量的微服务实例需要自动化的监控和运维的支持。如下图13为最终微服务系统的部署图。


对于部署的微服务来说,实现了中间件和数据库的完全独立,大部分微服务组件都拥有独立的数据库和缓存资源。当然有些缓存可能存在公用的情况,这个具体场景具体分析。目前部署的环境还是VM,后续为了提高部署速度和资源动态升缩能力,会尝试用docker来进行替代。

目前对于服务器资源的监控时zabbix,对于微服务应用的监控是SpringBootAdmin,另外对于接口API的监控我们还自研了一套接口可用性监控系统,基本上覆盖了监控的大部分需求。从架构演进角度来看,后续监控会引入Prometheus+Grafana结合使用。


持续集成CI & 持续部署CD

微服务的快速部署和迭代,需要持续集成CI与持续部署CD的支持。目前在测试环境已经实现了CI与CD的全流程自动化运行,由于公司网络的监管要求,目前生产系统网段无法直接连通代码仓库,因此目前CI与CD其实是分离的,当前仍然需要人工去做部署包的上传,如下图14所示。


目前已经在jekins上实现了大部分的微服务实例的持续部署,大大提升了部署的效率和准确性。而且通过Jenkins上面的部署历史,也实现了投产的审计和可追溯,提升投产管理水平,如下图15所示。


总结与展望

从目前微服务的搭建和治理来看,整体还处于一个入门级水准,但考虑到我们实际的技术水平和保障能力,也无法一步做到很完善的规模。微服务治理是不断演进的一个过程,正如任何系统架构一样,永远没有最完美的,只有最合适的。

目前整套系统只是使用了SpringCloud中的很小一部分组件,后续可能会增加统一配置中心ConfigServer,但其前提是生产系统网络需要开通到Git库访问,仍需要和机房部门沟通。考虑到目前我们的服务器还是实体机+VM组合,后续仍然需要引入docker容器技术,为以后迁移到云平台做好准备。

本文主要从实际开发运维的角度阐述了基于SpringCloud的微服务体系,希望可以为各位同行快速搭建微服务系统提供一些参考和帮助。


本文参考

  • Open Sourcing Zuul 2 https://medium.com/netflix-techblog/open-sourcing-zuul-2-82ea476cb2b3
  • Hystrix https://github.com/netflix/hystrix
  • Zuul2:Netflix’s Journey to Asynchronous,Non-blocking Systems https://medium.com/netflix-techblog/zuul-2-the-netflix-journey-to-asynchronous-non-blocking-systems-45947377fb5c
  • http://www.ityouknow.com/spring-cloud.html
  • https://thepracticaldeveloper.com/2018/03/18/spring-boot-service-discovery-eureka/
  • https://www.sohu.com/a/240241734_355140

springcloud是如何进行服务治理的相关推荐

  1. springboot springcloud区别_SpringCloud微服务全家桶-第一篇!为什么要用微服务

    从今天开始,学习SpringCloud微服务全家桶. 一.引导 1.什么是微服务? 2.微服务之间是如何独立通讯的 3.springCloud和Dubbo有哪些区别? 4.什么是服务熔断?什么是服务降 ...

  2. Spring Cloud之服务治理(注册发现)

    服务治理SpringCloud Eureka 什么是服务治理 在传统rpc远程调用中,服务与服务依赖关系,管理比较复杂,所以需要使用服务治理,管理服务与服务之间依赖关系,可以实现服务调用.负载均衡.容 ...

  3. 企业微服务治理的解决思路

    背景 随着业务需求的日渐复杂以及产品迭代节奏的不断加快,业务开发部门面临着前所未有的压力.为了抢占先机,用最快的速度准确把握用户需求的变化,优化开发出来的业务产品,微服务(MicroServices) ...

  4. SpringCloud微服务架构,Spring Cloud 服务治理(Eureka,Consul,Nacos),Ribbon 客户端负载均衡,RestTemplate与OpenFeign实现远程调用

    什么是SpringCloud 微服务架构 • "微服务"一词源于 Martin Fowler的名为 Microservices的博文,可以在他的官方博客上找到 http://mar ...

  5. SpringCloud服务治理Eureka(理论)

    Eureka:是Netflix公司开源的一个服务注册与发现的组件 Eureka和其他Netflix公司的服务组件(例如负载均衡,熔断器,网关)一起被SpringCloud社区整合为Spring-Clo ...

  6. SpringCloud微服务架构实战:微服务治理

    微服务治理 Spring Cloud 工具套件为微服务治理提供了全面的技术支持.这些治理工具主要包括服务的注册与发现.负载均衡管理.动态路由.服务降级和故障转移.链路跟踪.服务监控等.微服务治理的主要 ...

  7. SpringCloud微服务治理技术入门

    1.集群.分布式.微服务 首先先理解三个感念 什么是集群?: 同一个业务,部署在多个服务器上,目的是实现高可用,保证节点可用! 什么是分布式?: 一个业务分拆成多个子业务,部署在不同的服务器上,每个子 ...

  8. 基于Springcloud的服务治理落地实践

    前言 在微服务盛行的今天,提起服务治理,相信大家都已经不再陌生,许多公司都有自己内部的一套定制化的实现方案, Access也不例外, 接下来, 我来为大家介绍一下我们的一套基于Springcloud的 ...

  9. SpringCloud Eureka服务治理

    Spring Cloud Eureka 是 Spring Cloud Netflix 微服务套件中的一部分, 它基于 Netflix Eureka 做了二次封装, 主要负责完成微服务架构中的服务治理功 ...

最新文章

  1. Android 换肤
  2. 以太网的MAC帧(二)
  3. python模块手册_python模块说明
  4. 网络编程BIO,NIO一
  5. cleanmymac定时清理与垃圾监测
  6. stm32 堆和栈(stm32 Heap Stack)【worldsing笔记】
  7. android 3d渲染动画效果吗,Android如何实现3D效果
  8. Hibernate基础学习(二)—Hibernate相关API介绍
  9. jdk内置线程实例_EA问题的JDK14实例
  10. numpy基础知识点
  11. apache2 wordpress目录权限_小白指南:WordPress中的用户角色和权限
  12. s905各种型号的区别_预行式增压缸和直压增压缸有什么区别?
  13. 猫哥教你写爬虫 004--数据类型转换-小练习
  14. 蓝桥杯 基础练习 阶乘计算
  15. 怎么使用Diff和Meld工具发现两个目录间的不同之处
  16. 360linux如何卸载,卸载360安全卫士方法
  17. 尔雅课堂 美学原理课后练习题库
  18. Android拦截陌生号码,安卓手机应该如何设置拦截陌生号码
  19. 计算机 电脑 整机 加密,如何加密文件夹
  20. 网络系统管理Debian模块||初始化环境、网络地址规划

热门文章

  1. 学习.NET是因为热爱 or 兴趣 or 挣钱?
  2. 在Windows下快速搭建SVN服务器 VisualSVN
  3. CKEditor的使用方法
  4. 【开源】QuickPager ASP.NET2.0分页控件V2.0.0.1——支持多种数据库。让分页更加简单。...
  5. 为什么统计学家应该关注数据挖掘
  6. 一种避免 iOS 内存碎片的方法
  7. Codeforces 527C Glass Carving
  8. 记录C++ Builder 6.0开发过程中的一个linker error
  9. saltstack(三)state
  10. 微软发布Surface平板电脑 再度挑战苹果