您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

当时高并发项目差点让我丢了工作!看我如何配置优化

时间:2020-10-20 12:01:48  来源:  作者:

本文主要介绍的微服务是spring cloud,它一个服务治理框架和一系列框架的由序集合,其利用springboot的开发便利性巧妙的简化了分布式系统基础设施的开发,如服务发现注册、负载均衡、断路器、数据监控等,都可以用springboot的开发风格做到一键启动和部署。学习和了解微服务对快速熟悉和掌握不同项目的服务架构大有益处

分为以下几个部分进行介绍:

一、微服务应用的简单业务场景

二、Spring Cloud核心组件:Eureka

三、Spring Cloud核心组件:Feign

四、Spring Cloud核心组件:Ribbon

五、Spring Cloud核心组件:Hystrix

六、Spring Cloud核心组件:Zuul

七、高并发场景下配置优化

八、总结


一、业务场景介绍

先来给大家说一个都熟悉的支付订单的功能,大体的流程如下:

  • 用户创建一个订单并支付,需要将订单状态更新为“已支付”
  • 更新商品库存
  • 通知物流发货
  • 增加用户购物积分

上述业务场景的流程涉及到订单服务、库存服务、物流服务、用户积分服务。其调用关系如下图:

 

当时高并发项目差点让我丢了工作!看我如何配置优化

 

二、Spring Cloud核心组件:Eureka

考虑一个问题:订单服务想要调用库存服务、物流服务,或者是积分服务,怎么调用?

  • 传统方式:通过传统的ip:port的方式调用各种服务,如果订单服务依赖的其他服务地址更改了,就需要修改订单服务配置,然后重新部署。阿西吧!
  • eureka出场,eureka是微服务架构的注册中心,专门负责服务的注册和发现。Eureka有两个组件组成:Eureka server和Eureka client,一张图认识一下:
当时高并发项目差点让我丢了工作!看我如何配置优化

 

  • 上面的图描述了Eureka的基本架构,有3个角色组成
  1. Eureka Server:提供服务注册和发现
  2. Service Provider:服务提供方,将自身服务注册到Eureka Server,从而使消费方能够找到
  3. Service Consumer:服务消费方,定时从Eureka获取注册服务列表,消费服务
  • 再来看一下业务场景中,这些服务上都有Eureka Client组件,Service Provider启动时将自己注册到Eureka Server上,注册的意思就是告诉Eureka Server 自己在哪台服务器,端口号等,Eureka Server 的注册表会保存这些服务的元数据信息。这个时候如果订单服务调用库存服务,Service Consumer通过Eureka Client组件 向Eureka Server 问一下库存服务的ip是什么,端口是什么,然后调用库存服务。订单服务调用其他服务亦是如此。
当时高并发项目差点让我丢了工作!看我如何配置优化

 

 

  • 千万级访问量:eureka各个服务默认每隔30秒拉取注册表,每隔30s发起一次心跳,看看Eureka是如何实现千万级别访问量
  1. 假设现在有一个大型的分布式系统,一共100个服务,每个服务部署在20台机器上,机器是4核8G的标准配置。也就是说,相当于你一共部署了100 * 20 = 2000个服务实例,有2000台机器。每台机器上的服务实例内部都有一个Eureka Client组件,它会每隔30秒请求一次Eureka Server,拉取变化的注册表。此外,每个服务实例上的Eureka Client都会每隔30秒发送一次心跳请求给Eureka Server。

那么大家算算,Eureka Server作为一个微服务注册中心,每秒钟要被请求多少次?一天要被请求多少次?

按标准的算法,每个服务实例每分钟请求2次拉取注册表,每分钟请求2次发送心跳

  • 这样一个服务实例每分钟会请求4次,2000个服务实例每分钟请求8000次
  • 换算到每秒,则是8000 / 60 = 133次左右,我们就大概估算为Eureka Server每秒会被请求150次
  • 那一天的话,就是8000 * 60 * 24 = 1152万,也就是每天千万级访问量

深入原理:

  • Eureka server注册数据结构:
当时高并发项目差点让我丢了工作!看我如何配置优化

 

  • 如上图所示,图中的这个名字叫做registryCocurrentHashMap,就是注册表的核心结构。各个服务的注册、服务下线、服务故障,全部会在内存里维护和更新这个注册表。
  • 各个服务每隔30秒拉取注册表,每隔30s发起一次心跳,都在这Map数据结构中操作

一句话概括:维护注册表、拉取注册表、更新心跳时间,全部发生在内存里!

  • 这个ConcurrentHashMap的key就是服务名称,比如“订单服务的名字是:order-service,这里就是order-service”, value则代表了一个服务的多个服务实例。Lease的类,它的泛型是一个叫做InstanceInfo,代表服务实例的具体信息,比如机器的ip地址、hostname以及端口号。而这个Lease,里面则会维护每个服务最近一次发送心跳的时间
  • Eureka Server为了避免同时读写内存数据结构造成的并发冲突问题,采用了多级缓存机制ReadOnlyCacheMapReadWriteCacheMap)提升服务请求的响应速度。

在拉取注册表的时候:

  1. 首先从ReadOnlyCacheMap里查缓存的注册表。
  2. 若没有,就找ReadWriteCacheMap里缓存的注册表。
  3. 如果还没有,就从内存中获取实际的注册表数据。

在注册表发生变更的时候:

  1. 会在内存中更新变更的注册表数据,同时过期掉ReadWriteCacheMap
  2. 此过程不会影响ReadOnlyCacheMap提供人家查询注册表。
  3. 一段时间内(默认30秒),各服务拉取注册表会直接读ReadOnlyCacheMap
  4. 30秒过后,Eureka Server的后台线程发现ReadWriteCacheMap已经清空了,也会清空ReadOnlyCacheMap中的缓存
  5. 下次有服务拉取注册表,又会从内存中获取最新的数据了,同时填充各个缓存。

 

总结一下:

  • Eureka Client:负责将这个服务的信息注册到Eureka Server中
  • Eureka Server:注册中心,里面有一个注册表,保存了各个服务所在的机器和端口号

三、Spring Cloud核心组件:Feign

 

实现优雅的rpc调用:解决完服务在哪里之后,该如何去调用服务呢?难道订单服务要自己写一大堆代码,跟其他服务建立网络连接,然后构造一个复杂的请求,接着发送请求过去,最后对返回的响应结果再写一大堆代码来处理吗?想到这里是不是直想挠头,为了保住自己本来就不多的头发!来看看Feign是如何处理的吧!

当时高并发项目差点让我丢了工作!看我如何配置优化

 

看完上面的代码是不是感觉干净清爽!没有底层的建立连接、构造请求、解析响应的代码,直接就是用注解定义一个 FeignClient接口,然后调用那个接口就可以了,Feign都帮你做好了。

Feign实现这些的原理:一个关键机制就是使用了动态代理

  • 首先,如果你对某个接口定义了@FeignClient注解,Feign就会针对这个接口创建一个动态代理
  • 接着你要是调用那个接口,本质就是会调用 Feign创建的动态代理,这是核心中的核心
  • Feign的动态代理会根据你在接口上的@RequestMApping等注解,来动态构造出你要请求的服务的地址
  • 最后针对这个地址,发起请求、解析响应
当时高并发项目差点让我丢了工作!看我如何配置优化

 

四、Spring Cloud核心组件:Ribbon

服务集群部署:如果库存服务部署了3台怎么办,如下所示:

  • 192.168.10.10:7000
  • 192.168.10.11:7000
  • 192.168.10.13:7000

问题来了,Feign怎么知道该请求哪台机器呢?这时就轮到Ribbon出马了,其提供了解决微服务负载均衡的问题。Ribbon 是一个基于Http和TCP的客服端负载均衡工具,它是基于Netflix Ribbon实现的。它不像spring cloud服务注册中心、配置中心、API网关那样独立部署,但是它几乎存在于每个spring cloud 微服务中。包括feign提供的声明式服务调用也是基于该Ribbon实现的。

  • Ribbon的负载均衡默认使用的最经典的Round Robin轮询算法。如果订单服务对库存服务发起10次请求,那就先让你请求第1台机器、然后是第2台机器、第3台机器,接着再来—个循环,第1台机器、第2台机器。。。以此类推。其他常见的负载均衡策略还包括权重轮询WeightedResponseTimeRule,随机策略RandomRule,最少并发数策略BestAvailableRule等等

此外,Ribbon是和Feign以及Eureka紧密协作,完成工作的,具体如下:

  • 首先Ribbon会从 Eureka Client里获取到对应的服务注册表,也就知道了所有的服务都部署在了哪些机器上,在监听哪些端口号。
  • 然后Ribbon就可以使用默认的Round Robin算法,从中选择一台机器
  • Feign就会针对这台机器,构造并发起请求

对上述整个过程,再来一张图:

当时高并发项目差点让我丢了工作!看我如何配置优化

 

 

五、Spring Cloud核心组件:Hystrix

断路器,旨在通过熔断机制控制服务和其依赖服务之间的延迟和故障。比如:在一个大型的微服务架构里,一个服务可能要依赖很多服务,像本文的业务场景,订单服务依赖库存服务、物流服务、积分服务三个服务。假设订单服务最多只有100个线程可以处理请求,如果库存服务挂了,一般会抛出一个异常。如果系统处于高并发的场景下,大量请求涌过来的时候,订单服务的100个线程都会卡在请求库存服务这块,这导致订单服务没有一个线程可以处理请求,服务器完全不响应任何请求。

 

如上图,这么多服务互相调用,要是不做任何保护的话,某一个服务挂了,就会引起连锁反应,导致别的服务也挂。比如服务B挂了,会导致服务A的线程全部卡在请求服务B这里,没有一个线程可以工作。上面这个,就是微服务架构中恐怖的服务雪崩问题

 

当时高并发项目差点让我丢了工作!看我如何配置优化

 

  • 解决方式:

使用Hystrix。Hystrix是隔离、熔断以及降级的一个框架。Hystrix处理方式是提供很多个小小的线程池(其中一种解决方式),比如订单服务请求库存服务是一个线程池,请求物流服务是一个线程池,请求积分服务是一个线程池。每个线程池里的线程就仅仅用于请求那个服务。

  • 打个比方:现在很不幸,服务B挂了,会咋样?

当然会导致服务A的那个用来调用服务B的线程都卡死不能工作了啊!但是由于服务A调用服务C、服务D的这两个线程池都是正常工作的,所以这两个服务不会受到任何影响。但是如果服务B都挂了,服务A每次调用都要去卡住几秒钟干啥呢?有意义吗?当然没有!所以我们直接对服务B熔断不就得了,比如在5分钟内请求积分服务直接就返回了,不要去走网络请求卡住几秒钟,这个过程,就是所谓的熔断!如果服务A知道服务B已经熔断了,可以做一些特殊的处理,比如返回一些兜底的数据或者友好的提示,这个过程,就是所谓的降级。

为帮助大家更直观的理解,接下来用一张图,梳理一下Hystrix隔离、熔断和降级的全流程:

 

当时高并发项目差点让我丢了工作!看我如何配置优化

 

 

六、Spring Cloud核心组件:Zuul

前面的文章我们介绍了,Eureka用于服务的注册于发现,Feign和Ribbon支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散我们还是少考虑了一个问题,外部的应用如何来访问内部各种各样的微服务呢?在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个API网关根据请求的url,路由到相应的服务。当添加API网关后,在第三方调用端和服务提供方之间就创建了一面墙,这面墙直接与调用方通信进行权限控制,后将请求均衡分发给后台服务

为什么需要微服务网关?

在微服务架构模式下后端服务的实例数一般是动态的,动态改变的服务实例的访问地址信息很难被客户端发现。因此在基于微服务的项目中为了简化前端的调用逻辑,引入API Gateway作为轻量级网关,而且有一个网关之后,还有很多好处,比如可以做统一的降级、限流、认证授权、安全,等等。

 

当时高并发项目差点让我丢了工作!看我如何配置优化

 

七、高并发下配置优化

  • 合理的hystrix线程池大小:

假设你的服务A,每秒钟会接收30个请求,同时会向服务B发起30个请求,然后每个请求的响应时长经验值大概在200ms,那么你的hystrix线程池需要多少个线程呢?计算公式是:30(每秒请求数量) * 0.2(每个请求的处理秒数) + 4(给点缓冲buffer) = 10(线程数量)。

为什么10个线程可以轻松抗住每秒30个请求?

一个线程200毫秒可以执行完一个请求,那么一个线程1秒可以执行5个请求,理论上,只要6个线程,每秒就可以执行30个请求。也就是说,线程里的10个线程中,就6个线程足以抗住每秒30个请求了。剩下4个线程都在玩儿,空闲着。那为啥要多搞4个线程呢?很简单,因为你要留一点buffer空间。万一在系统高峰期,系统性能略有下降,此时不少请求都耗费了300多毫秒才执行完,那么一个线程每秒只能处理3个请求了,10个线程刚刚好勉强可以hold住每秒30个请求。所以你必须多考虑留几个线程。

  • 合理的超时时间设置

一个接口,理论的最佳响应速度应该在200ms以内,或者慢点的接口就几百毫秒。如果一个接口响应时间达到1秒+,建议考虑用缓存、索引、NoSQL等各种你能想到的技术手段,优化一下性能。否则你要是胡乱设置超时时间是几秒,甚至几十秒,万一下游服务偶然出了点问题响应时间长了点呢?那你这个线程池里的线程立马全部卡死!合理的超时时间设置为多少?答案应该不超过300毫秒(这个需要根据实际压测数据做些优化)。为啥呢?如果你的超时时间设置成了500毫秒,想想可能会有什么后果?考虑极端情况,如果服务B响应变慢,要500毫秒才响应,你一个线程每秒最多只能处理2个请求了,10个线程只能处理20个请求。大量的线程会全部卡死,来不及处理那么多请求,最后用户会刷不出来页面。如果你的线程池大小和超时时间没有配合着设置好,很可能会导致服务B短暂的性能波动,瞬间导致服务A的线程池卡死,里面的线程要卡顿一段时间才能继续执行下一个请求。哪怕一段时间后,服务B的接口性能恢复到200毫秒以内了,服务A的线程池里卡死的状况也要好一会儿才能恢复过来。你的超时时间设置的越不合理,比如设置的越长,设置到了1秒、2秒,那么这种卡死的情况就需要越长的时间来恢复。所以说,此时你的超时时间得设置成300毫秒,保证一个请求300毫秒内执行不完,立马超时返回。这样线程池里的线程不会长时间卡死,可以有条不紊的处理多出来的请求,大不了就是300毫秒内处理不完立即超时返回,但是线程始终保持可以运行的状态。这样当服务B的接口性能恢复到200毫秒以内后,服务A的线程池里的线程很快就可以恢复。

八、总结:

总结一下,上述几个Spring Cloud核心组件,在微服务架构中,分别扮演的角色:

  • Eureka:各个服务在启动时,Eureka Client组件会将本服务注册到Eureka Server,集群以应用名做区分,并且Eureka Client还可以反过来从Eureka Server拉取注册表,从而知道其他服务在哪里
  • Ribbon:微服务之间发起请求的时候,基于Ribbon做负载均衡,从服务集群中选择一台
  • Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求
  • Hystrix:发起请求是通过Hystrix的线程池来走的,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题
  • Zuul:微服务路由

当然spring cloud家族还有Spring Cloud Config、Spring Cloud Bus、Spring Cloud for Cloud Foundry、Spring Cloud Cluster、Spring Cloud Consul、Spring Cloud Security、Spring Cloud Sleuth、Spring Cloud Data Flow、Spring Cloud Stream、Spring Cloud Task、Spring Cloud Zookeeper、Spring Cloud Connectors、Spring Cloud Starters、Spring Cloud CLI等等,具体信息请查看:

中文文档:https://springcloud.cc/

英文文档:http://spring.io/projects/spring-cloud

来源:网易工程师-周延旭



Tags:高并发   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃。不应该大于255,默认值是5,对应于180秒左右时间。。(对于大负载而物理通信良好的网络而言,这个值偏高,可修改为2.这个值仅仅是针对对外的连接,对进来的连接,...【详细内容】
2021-12-08  Tags: 高并发  点击:(23)  评论:(0)  加入收藏
一、幂等性概念在数学里,幂等有两种主要的定义。1、在某二元运算下,幂等元素是指被自己重复运算(或对于函数是为复合)的结果等于它自己的元素。例如,乘法下唯一两个幂等实数为0和...【详细内容】
2021-10-09  Tags: 高并发  点击:(43)  评论:(0)  加入收藏
原文链接: https://mp.weixin.qq.com/s/MTw7z6n_wk4y4CTmGkoRoA一切要从CPU说起你可能会有疑问,讲多线程为什么要从CPU说起呢?原因很简单,在这里没有那些时髦的概念,你可以更加清...【详细内容】
2021-08-13  Tags: 高并发  点击:(96)  评论:(0)  加入收藏
题目:高并发情况下,数据库该如何设计?Java高级面试题:为什么要分库分表( 设计高并发系统的时候 , 数据库层面该如何设计 ) ? 用过哪些分库分表中间件 ? 不同的分库分表中间件都有什么...【详细内容】
2021-06-18  Tags: 高并发  点击:(119)  评论:(0)  加入收藏
1. 目的撰写本文的目的是解决微服务架构,对静态数据资源没有规整,所有微服务都是从数据库直接读取,导致性能较差,用户体验不好。通常在高可用的分布式架构中,一般都会采用将这部...【详细内容】
2021-03-17  Tags: 高并发  点击:(157)  评论:(0)  加入收藏
元旦期间 订单业务线 告知 推送系统 无法正常收发消息,作为推送系统维护者的我正外面潇洒,无法第一时间回去,直接让 ops 帮忙重启服务,一切好了起来,重启果然是个大杀器。由于推...【详细内容】
2021-01-07  Tags: 高并发  点击:(146)  评论:(0)  加入收藏
本文主要介绍的微服务是spring cloud,它一个服务治理框架和一系列框架的由序集合,其利用springboot的开发便利性巧妙的简化了分布式系统基础设施的开发,如服务发现注册、负载...【详细内容】
2020-10-20  Tags: 高并发  点击:(105)  评论:(0)  加入收藏
一、什么是分布式?分布式更多的是一个概念,是为了解决单个物理服务器容量和性能瓶颈问题而采用的优化手段,该领域需要解决的问题极多,在不同的技术层面上,又包括:分布式文件系统...【详细内容】
2020-10-14  Tags: 高并发  点击:(91)  评论:(0)  加入收藏
作为热点频出的电商系统,经常遇到高并发,热点秒杀的场景。我们在开发设计高并发海量业务请求的系统时,通常利用三板斧:缓存、降级和限流来保障系统稳定性。...【详细内容】
2020-09-27  Tags: 高并发  点击:(68)  评论:(0)  加入收藏
前言一台服务器并发TCP连接数可以有多少?如何支持从硬件和操作系统上支持单台服务器支持上万并发,支持百万千万,甚至上亿的并发著名的C10K并发连接问题是什么?C10M并发问题又是...【详细内容】
2020-09-01  Tags: 高并发  点击:(102)  评论:(0)  加入收藏
▌简易百科推荐
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Python阿杰    Tags:FastAPI   点击:(6)  评论:(0)  加入收藏
文章目录1、Quartz1.1 引入依赖<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>...【详细内容】
2021-12-22  java老人头    Tags:框架   点击:(11)  评论:(0)  加入收藏
今天来梳理下 Spring 的整体脉络啦,为后面的文章做个铺垫~后面几篇文章应该会讲讲这些内容啦 Spring AOP 插件 (了好久都忘了 ) 分享下 4ye 在项目中利用 AOP + MybatisPlus 对...【详细内容】
2021-12-07  Java4ye    Tags:Spring   点击:(14)  评论:(0)  加入收藏
&emsp;前面通过入门案例介绍,我们发现在SpringSecurity中如果我们没有使用自定义的登录界面,那么SpringSecurity会给我们提供一个系统登录界面。但真实项目中我们一般都会使用...【详细内容】
2021-12-06  波哥带你学Java    Tags:SpringSecurity   点击:(18)  评论:(0)  加入收藏
React 简介 React 基本使用<div id="test"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js...【详细内容】
2021-11-30  清闲的帆船先生    Tags:框架   点击:(19)  评论:(0)  加入收藏
流水线(Pipeline)是把一个重复的过程分解为若干个子过程,使每个子过程与其他子过程并行进行的技术。本文主要介绍了诞生于云原生时代的流水线框架 Argo。 什么是流水线?在计算机...【详细内容】
2021-11-30  叼着猫的鱼    Tags:框架   点击:(21)  评论:(0)  加入收藏
TKinterThinter 是标准的python包,你可以在linx,macos,windows上使用它,你不需要安装它,因为它是python自带的扩展包。 它采用TCL的控制接口,你可以非常方便地写出图形界面,如...【详细内容】
2021-11-30    梦回故里归来  Tags:框架   点击:(26)  评论:(0)  加入收藏
前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等。配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文...【详细内容】
2021-11-17  充满元气的java爱好者  博客园  Tags:SpringBoot   点击:(25)  评论:(0)  加入收藏
一、搭建环境1、创建数据库表和表结构create table account(id INT identity(1,1) primary key,name varchar(20),[money] DECIMAL2、创建maven的工程SSM,在pom.xml文件引入...【详细内容】
2021-11-11  AT小白在线中  搜狐号  Tags:开发框架   点击:(29)  评论:(0)  加入收藏
SpringBoot开发的物联网通信平台系统项目功能模块 功能 说明 MQTT 1.SSL支持 2.集群化部署时暂不支持retain&will类型消 UDP ...【详细内容】
2021-11-05  小程序建站    Tags:SpringBoot   点击:(55)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条