简单介绍一下什么是SpringCloud?

SpringCloud

我觉着SpringCloud就是一个分布式微服务架构的一站式解决方案,它提供了很多组件用来解决了分布式架构所带来的一些问题。
我在之前工作里用过Eureka[优瑞卡]、Ribbon[瑞本]、Feign[菲恩]、Hystrix[黑丝锤科丝],Zuul[入欧]这么几个组件。其中
Eureka在整个微服务架构中充当注册中心的角色,服务提供者将自身信息注册到Eureka Server[涩沃]中,然后服务消费者就可以从Eureka Server中获取注册的服务提供者的信息,然后就可以向服务提供者发起调用了。
Ribbon实现了客户端的负载均衡,它提供了轮询、轮询权重、随机等一些常用的负载均衡策略。
Feign我理解的就是简化服务之间的调用,让我们调用远程接口就像在调用本地方法一样。
Hystrix的主要功能就是服务熔断、降级和资源隔离,用来保护我们的调用链路,避免发生服务雪崩问题。
Zuul在整个微服务架构中充当服务网关的角色,提供请求转发和过滤的功能,可以在服务网关中实现统一身份验证、统一跨域请求处理等功能。以上就是我对SpringCloud的一些简单理解。

Eureka简介?

我理解的Eureka它在整个微服务架构中充当注册中心的角色,方便咱们管理各种微服务。Eureka又分为Eureka Server(服务端)和 Eureka Client(客户端)。每个微服务中都有一个Eureka Client专门负责将这个服务的信息注册到Eureka Server中。说白了就是告诉Eureka Server自己在哪台机器上监听着哪个端口。而Eureka Server是一个注册中心,里面有一个注册表,保存了各服务所在的机器和端口号。服务之间进行调用的时候,消费者服务中的Eureka Client会把要调用的服务的IP地址、端口号等这些相关信息从Eureka Server的注册表中拉取到自己本地缓存起来。然后服务之间进行调用的时候,消费者服务中的Eureka Client会把要调用的服务的IP地址、端口号等这些相关信息从Eureka Server的注册表中拉取到自己本地缓存起来。紧接着就可以发送一个请求过去,调用相应服务的那个接口!
(2)Eureka心跳机制?
接下来我来说一下Eureka的心跳机制吧,就是Eureka Client每隔30秒会向Eureka Server发送一次心跳,就如同人还活着存在的信号一样,如果Eureka Server在90秒后还未收到发来的心跳时,那么它就会认定该服务已经死亡就会注销这个服务。但是这里注销并不是立即注销,而是会在60秒以后对在这个时间段内“死亡”的服务集中注销,如果立即注销,肯定会对Eureka造成极大的负担。另外刚才我说的这些时间参数都可以人为配置。
(3)Eureka自我保护机制?
Eureka还有自我保护机制,如果在15分钟内一直都是超过85%的节点都没有正常的心跳,那么Eureka Server就认为客户端与注册中心出现了网络故障,就会进入自我保护模式。进入自我保护模式之后Eureka Server就不会再接收心跳,也不会删除任何服务。当网络故障恢复后,Eureka Server会自动退出自我保护模式。这就是Eureka的自我保护机制。
(4)具体怎么使用Eureka搭建注册中心?
首先需要在pom文件中引入Eureka Server的依赖,之后在启动类中加入@EnableEurekaServer的注解证明该项目的作用是作为注册中心使用,并且在对应的application.properties中指明Eureka注册中心服务器的地址,方便服务提供者和消费者对其进行访问,为了保证注册中心的高可用,我们当时还搭建了Eureka集群,防止因为单台Eureka 导致的单点故障问题。
(5)服务怎么注册到Eureka Server中?
首先在需要注册到Eureka Server的服务pom中引入Eureka Client的依赖,然后在配置文件中配置服务名、Eureka Server的地址,最后在启动类上添加@EnableEurekaClient注解就行了。
(6)怎么搭建的Eureka Server集群?
其实就是对Eureka Server进行了集群部署,然后每台Eureka Server都要注册到另外两台Eureka Server中,它们之间会自动进行数据同步。服务在注册的时候要填写所有Eureka Server的地址,当然只写其中一个Eureka Server也行,但是这样做有风险,万一你写的这台Eureka Sever整好挂了那服务注册就失败了,所以为了稳妥起见,最好把所有Eureka Server的地址都写上。
(7)为什么要使用注册中心?
如果没有注册中心,消费者通过ip地址访问服务提供者,如果服务越来越多,调用也会越来越复杂,一旦服务提供者的ip地址发生变动,则所有用到的地方都需要进行改变,维护起来会特别麻烦;或者说服务提供者宕机了,所有访问的消费者也都会受到影响。通过注册中心可以让服务提供者注册到注册中心上去,并且可以进行负载均衡。这样就可以达到高可用以及提高并发的目的。消费者再调用服务提供者的时候,就可以通过注册中心获取地址列表,从地址列表中选一个地址进行调用,后续的维护各方面也会比较方便。

Feign的介绍?

Feign说白了就是一个用于简化服务间进行远程接口调用的工具,当然了不用Feign的话我们也可以进行远程接口调用,比如说我们可以使用HttpClient自己写代码去构造请求、发送请求和解析接口的响应结果,但是这样做太麻烦了,使用了Feign之后,我们调用远程接口就像在调用本地方法一样。那些构造请求、发送请求和解析接口响应结果的脏活累活Feign都帮我们做了,让我们可以更加专注于那些核心业务逻辑的编写。
(2)Feign的工作原理?
那在这里我就简单说一下我了解到的Feign的工作原理吧,首先在服务消费者微服务启动的时候,如果启动类上添加了@EnableFeignClients注解,那么Feign会进行包扫描,扫描那些添加了@FeignClient注解的接口,并按照注解的规则,创建接口的代理对象然后加入到IOC容器中。当接口中的方法被调用时,接口的代理对象会根据你在接口上的@RequestMapping、@PathVariable等注解,来动态构造出你要请求的服务的地址。最后针对这个地址,发起请求、解析响应结果。
(3)Feign具体怎么使用的?
首先我打个比方吧,比如说我现在有两个微服务一个是订单微服务一个是商品微服务,订单微服务在下订单的时候需要调用商品微服务的接口。那现在我的订单微服务就是消费者,商品微服务就是服务提供者。考虑到后续可能有更多的消费者都要调用商品微服务。我们应该给商品微服务新建一个对应的接口模块(项目),里面就放商品微服务对外暴露的东西。那此时如果说要使用Feign来进行订单微服务和商品微服务的远程接口调用的话,我们应该在商品微服务对应的接口模块下引入Feign的依赖,然后定义一个接口类,然后在接口上添加了@FeignClient注解并指定商品微服务的服务名,然后在这个接口类里面定义和商品微服务项目里面API接口对应的方法,而且方法要和对应API接口的请求方式、请求地址以及方法名、返回值、参数都要保持一致。这些做完了之后我们就可以在订单微服务中引入商品微服务接口模块的依赖,然后在启动类上添加@EnableFeignClients注解,然后在订单微服务的业务逻辑层注入前面定义好的FeignClient接口,然后调这个FeignClient接口里面的方法就可以实现对商品微服务API接口的调用了。

.Ribbon总结

Ribbon说白了就是一个客户端负载均衡的工具,当然我们在之前的项目里没有单独使用过Ribbon,因为我们使用的Feign已经内置了Ribbon。Ribbon内置了很多负载均衡策略,比如说轮询啊、随机啊、过滤掉不可用的服务啊、根据响应时间加权啊、轮询重试啊等,大概我就记得这些。Ribbon默认使用的负载均衡策略是轮询。当然如果说Ribbon自带的负载均衡策略满足不了你的需求的话,你也可以自定义Ribbon的轮询策略。其实就是新建一个类去继承Ribbon提供的一个什么Abstract…Rule什么的[故意说的不清楚],然后重写抽象方法,在里面实现你的负载均衡策略就可以了。
客户端负载均衡和服务端负载均衡的区别(被动)?
客户端负载均衡就是客户端自己来选择,服务端负载均衡就是服务端来选择。我打个现实生活中的例子吧,就是咱们去肯德基点餐,这个时候假设它有三个点餐窗口,每个点餐窗口都有一个服务员,现在每个点餐窗口都有排队的,这个时候如果是你自己选择点餐窗口那就是客户端负载均衡,如果是由服务员让你去指定的点餐窗口那就是服务端负载均衡。

Hystrix总结

(1)什么是服务雪崩?
在咱们的微服务系统中有可能发生服务雪崩的问题,比如说系统里面A服务需要调用B服务,B服务需要调用C服务,如果C服务出现问题,就会影响到B服务导致B服务出现问题,同样B服务出现问题,也会导致A服务也出问题,最后就会导致所有的微服务都不可用。就像咱们现实生活中,一个路口堵车,就会导致整条街慢慢拥堵,再后来影响的范围就会越来越大。为了避免出现服务雪崩问题,可以用SpringCloud中的Hystrix来解决这个问题。
(2)Hystrix是什么?
咱们都知道Hystrix可以进行熔断,降级和资源隔离。
(3)Hystrix的熔断机制?
熔断就是如果某个目标服务调用慢或者有大量超时,此时就熔断该服务的调用,对于后续的调用请求,不再继续调用目标服务,而是直接返回,快速释放资源。如果目标服务情况好转则恢复调用。
具体的原理是这样的,默认情况下在10s内,每当20个清求中,有50%失败时,就会触发熔断,导致hystrix熔断器从闭合状态切换到打开状态,这样就不需要每次都去调用远程微服务而是直接走调用者本地的降级方法。5秒后hystrix会进入到半打开状态,这时如果有新的请求过来hystrix就会放行1个请求尝试再次进行远程微服务调用,如果调用成功熔断器就会进入到闭合状态,如果不成功就会再次进入到打开状态,继续进行熔断。然后再过5秒再次进入半开状态。这个就是hystrix的自动检测并修复的能力。
(4)Hystrix的降级机制?
降级说白了就是进行熔断后需要执行本地的方法。也是为了保证微服务的高可用。
(5)Hystrix的隔离机制?
在Hystrix中,有两种资源隔离方式,信号量隔离和线程池隔离,我们主要用的是线程池隔离,通常在使用的时候我们会根据调用的远程服务划分出多个线程池,比如调用产品服务的线程放入一个线程池,调用会员服务的线程放入另一个线程池,这样就可以将运行环境隔离开。就算调用服务的代码存在BUG或者由于其他原因导致自己所在线程池被耗尽,也不会对系统的其他服务造成影响。
(6)Feign如何和Hystrix配合使用?
我们在项目中是用Feigin进行微服务之间的调用的,又因为Feign集成了Hystrix,所以我们当时通过在配置文件中开启Feign对Hystrix的支持,并且在具体使用Feign的接口上通过@FeignClient注解中的Fallback属性指定降级时候需要执行的类即可,这样在目标服务调用失败时或者熔断后就会自动调用Fallback类中对应的降级方法,在降级方法中可以记录下错误日志并且返回null这样使用Feign的客户端在调用远程微服务的方法后,判断返回值是否为null,如果是null,则证明走了降级方法,进行特殊处理就行。
Feign 还拥有负载均衡的特性,说白了它是靠Ribbon进行的负权均衡,在@FeignCilent的注解上指明要调用的微服务的名字,这样就可以通过该服务名从注册中心Eureka中获取对应的地址列表,方便进行负载均衡的调用。
还有一个需要注意的地方就是我们编写的FeignClient接口中的方法要和我们服务提供者项目中接口的请求方式,请求地址以及方法名,返回值,参数都要保持一致。

Zuul简介

Zuul在整个微服务系统中充当网关的角色,实现路由转发和过滤的功能能,是客户端与服务器之间的中间层。因为外部客户端的请求都是通过ZUUL网关路由到具体的微服务,所以为了保证微服务的安全,我们就在Zuul中自定义了过滤器,对所有微服务的安全进行统一的处理,还有,因为涉及到前后端分离,前端项目访问后端微服务涉及到跨域问题,所以我们在Zuul中也自定义了关于跨域的过滤器,进行统一处理。
(2)如何自定义跨域过滤器?
具体是这么做的,首先你得先定义一个继承于ZuulFiter的类,重写里面的filterType()方法filterOrder()方法,shouldFite()方法, 还有一个最核心的用来写具体业务逻辑的run()方法。其中filterType方法的作用是用来返回一个字符串,指明该过滤器的类型,经常用到的有pre类型,说白了就是在请求被发送到微服务之前调用:我们的微服务安全认证以及跨域这块都是用的pre类型的过滤器,这样对非法请求,就可以在发送到具体的微服务之前拒绝它;还有post类型,说白了就是微服务执行完后再执行该过滤器,filterOrder方法返回一个int类型的值,用来指明该过滤器的执行顺序,数宇越小表示优先级越高越先执行,shouldFilter()方法返回一个boolean值,用来指明该过滤器是否执行,true 表示执行,false表示不执行。
run方法中就是之前说的, 用来放具体的处理逻辑。
在run 方法中,首先获取一个RequestContext对象,之后就可以通过调用它的getRequest()方法来获取request对象;这样就可以获取头信息,按照基于token的方式进行接口的安全验证。
过程中特别需要注意的就是当验证不通过的时候,需要通过fastjson将要响应的数据转换为json格式的字符串,之后设置响应的内容类型为application/json并且指定utf-8的编码方式,用来处理中文乱码问题:通过setResponseBody将Json格式的字符串置为响应的内容,最后通过setSendZuulResponse为false,禁止路由转发。如果想要将zuul过滤器中的数据传递给后端微服务中使用,则需要通过addZuulRequestHeader方法来进行, 而后端微服务中就可以通过 request.getHeader来获取值。这里面需要特别注意的就是:如果传递的数据中含有中文则需要通过URLEncoder进行utf-8的编码, 同样在获取数据后也需要通过 URLDecoder进行解码。
最后想要使自定义的过滤器生效,得进行相关的配置。我通过创建一个配置类,并且在类上通过@Configuration 和方法上的@Bean结合起来,完成自定义filter的配置。
(3)Zuul集群的搭建?
Zuul的高可用非常关键,因为外部请求到后端微服务的流量都会经过Zuul。所以我们就对Zuul进行了集群部署,避免了单台Zuul会带来的单点故障问题,并且我们使用了Nginx对Zuul集群进行负载均衡。其实就是在Nginx配置文件里,把Zuul集群中每一台Zuul服务器的地址配上,然后由Nginx进行转发就行了。

你可能感兴趣的:(springcloud,java,spring)