15. springcloud(详细讲解)

微服务架构技术

微服务架构: 是使用一套小服务来开发单个应用的方式或途径。
微服务结构图:
在这里插入图片描述API Gateway网关是一个服务器,是系统的唯一入口。为每个客户端提供一个定制的API。API网关核心是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。如它还可以具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。通常,网关提供RESTful/HTTP的方式访问服务。而服务端通过服务注册中心进行服务注册和管理。

微服务架构的特点

单一职责:微服务中每一个服务都对应唯一的业务能力,做到单一职责
微(服务粒度小):微服务的服务拆分粒度很小,例如一个用户管理就可以作为一个服务。每个服务虽小,但“五脏俱全”。 、
面向服务(对外暴露rest风格 api):面向服务是说每个服务都要对外暴露Rest风格服务接口API。并不关心服务的技术实现,做到与平台 和语言无关,也不限定用什么技术实现,只要提供Rest的接口即可。
自治(服务之间相互独立):自治是说服务间互相独立,互不干扰
团队独立:每个服务都是一个独立的开发团队,人数不能过多。
技术独立:因为是面向服务,提供Rest接口,使用什么技术没有别人干涉
前后端分离:采用前后端分离开发,提供统一Rest接口,后端不用再为PC、移动端开发不同接口
数据库分离:每个服务都使用自己的数据源
部署独立,服务间虽然有调用,但要做到服务重启不影响其它服务。有利于持续集成和持续交付。每个服 务都是独立的组件,可复用,可替换,降低耦合,易维护

与使用ESB的SOA架构的区别:

微服务架构没有使用ESB, 有服务治理注册中心;业务粒度小.
在这里插入图片描述

服务调用方式:

常见的远程调用方式有以下2种:

RPC:

Remote Produce Call远程过程调用,RPC基于Socket,工作在会话层。自定义数据格式,速度快,效率高。早期的webservice,现在热门的dubbo(阿里),都是RPC的典型代表

Http:

http其实是一种网络传输协议,基于TCP,工作在应用层,规定了数据传输的格式。现在客户端浏览器与服务端通信基本都是采用Http协议,也可以用来进行远程服务调用。缺点是消息封装臃肿,优势是对服务的提供和调用方没有任何技术限定,自由灵活,更符合微服务理念。

区别:

RPC的机制是根据语言的API(language API)来定义的,而不是根据基于网络的应用来定义的。 如果你们公司全部采用Java技术栈,那么使用Dubbo作为微服务架构是一个不错的选择。 相反,如果公司的技术栈多样化,而且你更青睐Spring家族,那么Spring Cloud搭建微服务是不二之选。在我们的项 目中,会选择Spring Cloud套件,因此会使用Http方式来实现服务间调用。

小结:

RPC:基于socket,速度快,效率高;webservice、dubbo(阿里)

HTTP:基于TCP,封装比较臃肿;对服务和调用方没有任何技术、语言的限定,自由灵活;RESTful,Spring Cloud

Http客户端工具

一般情况下有如下三种http客户端工具类包都可以方便的进行http服务调用:

HttpClient

OKHttp

JDK原生URLConnection

spring 提供了RestTemplate的工具类对上述的3种http客户端工具类进行了封装,可在spring项目中使用RestTemplate进行服务调用

Spring Cloud

微服务的实现方式很多,但是最火的莫过于Spring Cloud了。为什么?

  1. 后台硬:作为Spring家族的一员,有整个Spring全家桶靠山,背景十分强大。
  2. 技术强:Spring作为Java领域的前辈,可以说是功力深厚。有强力的技术团队支撑,一般人还真比不了
  3. 群众基础好:可以说大多数程序员的成长都伴随着Spring框架,试问:现在有几家公司开发不用Spring? Spring Cloud与Spring的各个框架无缝整合,对大家来说一切都是熟悉的配方,熟悉的味道。
  4. 使用方便:相信大家都体会到了SpringBoot给我们开发带来的便利,而Spring Cloud完全支持Spring Boot的开 发,用很少的配置就能完成微服务框架的搭建
    Spring最擅长的就是集成,把世界上最好的框架拿过来,集成到自己的项目中。
    Spring Cloud也是一样,它将现在非常流行的一些技术整合到一起,实现了诸如:配置管理,服务发现,智能路由, 负载均衡,熔断器,控制总线,集群状态等功能;协调分布式环境中各个系统,为各类服务提供模板性配置。其主要 涉及的组件包括:

Eureka:注册中心

Zuul、Gateway:服务网关

Ribbon:负载均衡

Feign:服务调用

Hystrix或Resilience4j:熔断器

在这里插入图片描述

Eureka注册中心

Eureka是服务注册中心,只做服务注册;自身并不提供服务也不消费服务。可以搭建web工程使用Eureka,可以使用Spring Boot方式搭建。

原理图

在这里插入图片描述
Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址
提供者:启动后向Eureka注册自己信息(地址,提供什么服务)
消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新
心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态

Eureka架构中的三个核心角色:
服务注册中心

Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的eureka-server

服务提供者

提供服务的应用,可以是SpringBoot应用,也可以是其它任意技术实现,只要对外提供的是Rest风格服务即可。本例中就是我们实现的user-service

服务消费者

消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。本例中就是我们实 现的consumer-demo

搭建步骤:
  1. 创建工程;
  2. 添加启动器依赖;
  3. 编写启动引导类(添加Eureka的服务注解)和配置文件;
  4. 修改配置文件(端口,应用名称…);
  5. 启动测试
Eureka 服务注册中心(eureka server)

服务提供者要向EurekaServer(eureka 服务注册中心)注册服务,并且完成服务续约等工作。

服务注册

服务提供者在启动时,会检测配置属性中的:

  1. eureka.client.register-with-erueka=true 参数是否正确,事实上 默认就是true。如果值确实为true,则会向EurekaServer发起一个Rest请求,并携带自己的元数据信息,Eureka Server会把这些信息保存到一个双层Map结构中。 第一层Map的Key就是服务id,一般是配置中的 spring.application.name 属性
    第二层Map的key是服务的实例id。一般host+ serviceId + port,例如: localhost:user-service:8081
    值则是服务的实例对象,也就是说一个服务,可以同时启动多个不同实例,形成集群。
    默认注册时使用的是主机名或者localhost,如果想用ip进行注册,可以在 user-service 中添加配置如下:
eureka:
  server:
    # 服务失效剔除时间间隔,默认60秒
    eviction-interval-timer-in-ms: 60000
    # 关闭自我保护模式(默认是打开的)
    enable-self-preservation: false
失效剔除和自我保护

如下的配置都是在Eureka Server服务端进行:

服务下线

当服务进行正常关闭操作时,它会触发一个服务下线的REST请求给Eureka Server,告诉服务注册中心:“我要下线 了”。服务中心接受到请求之后,将该服务置为下线状态。

失效剔除

有时我们的服务可能由于内存溢出或网络故障等原因使得服务不能正常的工作,而服务注册中心并未收到“服务下 线”的请求。相对于服务提供者的“服务续约”操作,服务注册中心在启动时会创建一个定时任务,默认每隔一段时间 (默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务剔除,这个操作被称为失效剔除。 可以通过 eureka.server.eviction-interval-timer-in-ms 参数对其进行修改,单位是毫秒。

自我保护

我们关停一个服务,很可能会在Eureka面板看到一条警告:
在这里插入图片描述
这是触发了Eureka的自我保护机制。当服务未按时进行心跳续约时,Eureka会统计服务实例最近15分钟心跳续约的 比例是否低于了85%。在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务 剔除列表并不妥当,因为服务可能没有宕机。Eureka在这段时间内不会剔除任何服务实例,直到网络恢复正常。生 产环境下这很有效,保证了大多数服务依然可用,不过也有可能获取到失败的服务实例,因此服务调用者必须做好服 务的失败容错。 可以通过下面的配置来关停自我保护:

eureka: 
server:
enable-self-preservation: false # 关闭自我保护模式(缺省为打开)
服务续约(eureka 服务提供)

在注册服务完成以后,服务提供者会维持一个心跳(定时向EurekaServer发起Rest请求),告诉EurekaServer:“我还活着”。这个我们称为服务的续约(renew); 有两个重要参数可以修改服务续约的行为;可以在 user-service 中添加如下配置项:

eureka: 
instance: 
lease-expiration-duration-in-seconds:90 lease-renewal-interval-in-seconds: 30

lease-renewal-interval-in-seconds:服务续约(renew)的间隔,默认为30秒 lease-expiration-duration-in-seconds:服务失效时间,默认值90秒
也就是说,默认情况下每隔30秒服务会向注册中心发送一次心跳,证明自己还活着。如果超过90秒没有发送心跳, EurekaServer就会认为该服务宕机,会定时(eureka.server.eviction-interval-timer-in-ms设定的时间)从服务列表 中移除,这两个值在生产环境不要修改,默认即可。

获取服务列表

当服务消费者启动时,会检测 eureka.client.fetch-registry=true 参数的值,如果为true,则会从Eureka Server服务的列表拉取只读备份,然后缓存在本地。并且 每隔30秒 会重新拉取并更新数据。可以在 consumer-demo 项目中通过下面的参数来修改:

高可用配置:

将Eureka Server作为一个服务注册到其它Eureka Server(eureka 注册中心),这样多个Eureka Server之间就能够互相发现对方,同步服务,实现Eureka Server集群。

负载均衡Ribbon简介

目标:描述负载均衡和ribbon的作用
什么是Ribbon:
在这里插入图片描述

分析:

负载均衡是一个算法,可以通过该算法实现从地址列表中获取一个地址进行服务调用。
在Spring Cloud中提供了负载均衡器:Ribbon

小结:

Ribbon提供了轮询、随机两种负载均衡算法(默认是轮询)可以实现从地址列表中使用负载均衡算法获取地址进行服务调用。

开启负载均衡

因为Eureka中已经集成了Ribbon,所以我们无需引入新的依赖。 直接修改 consumer-demo\src\main\java\com\cgq\consumer\ConsumerApplication.java 在RestTemplate的配置方法上添加 @LoadBalanced 注解:

@Bean 
@LoadBalanced 
public RestTemplate restTemplate() {
   
 return new RestTemplate(); 
}

修改consumer-demo\src\main\java\com\cgq\consumer\controller\ConsumerController.java 调用方 式,不再手动获取ip和端口,而是直接通过服务名称调用;

@GetMapping("{id}") 
public User queryById(@PathVariable("id") Long id){
   
 String url = "http://user-service/user/" + id; 
User user = restTemplate.getForObject(url, User.class); 
return user; 
}
了解:Ribbon默认的负载均衡策略是轮询。SpringBoot也帮提供了修改负载均衡规则的配置入口在consumerdemo的配置文件中添加如下,就变成随机的了:
user-service: 
ribbon: 
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

格式是: {服务名称}.ribbon.NFLoadBalancerRuleClassName
为什么只输入了service名称就可以访问了呢?之前还要获取ip和端口。
显然是有组件根据service名称,获取到了服务实例的ip和端口。因为 consumer-demo 使用的是RestTemplate, spring的负载均衡自动配置类 LoadBalancerAutoConfiguration.LoadBalancerInterceptorConfig 会自动配置 负载均衡拦截器(在spring-cloud-commons-**.jar包中的spring.factories中定义的自动配置类), 它就是 LoadBalancerInterceptor ,这个类会在对RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列 表,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。

Feign

Feign也叫伪装
Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样。你不用再自己拼接url,拼接参数等等 操作,一切都交给Feign去做。

Feign 的使用
  1. 导入依赖
    在 consumer-demo 项目的 pom.xml 文件中添加如下依赖
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  1. Feign 的客户端
    在 consumer-demo 中编写如下Feign客户端接口类:
//声明当前类是一个Feign客户端,指定服务名为user-service
@FeignClient(value = "user-service", fallback = UserClientFallback.class,
configuration = FeignConfig.class)
public interface UserClient {
   

    //http://user-service/user/123
    @GetMapping("/user/{id}")
    User queryById(@PathVariable Long id);
}

首先这是一个接口,Feign会通过动态代理,帮我们生成实现类。这点跟mybatis的mapper很像 @FeignClient ,声明这是一个Feign客户端,同时通过 value 属性指定服务名称 接口中的定义方法,完全采用SpringMVC的注解,Feign会根据注解帮我们生成URL,并访问获取结果 @GetMapping中的/user,请不要忘记;因为Feign需要拼接可访问的地址 编写新的控制器类 ConsumerFeignController ,使用UserClient访问:
编写新的控制器类 ConsumerFeignController ,使用UserClient访问:

@RestController
@RequestMapping("/cf")
public class ConsumerFeignController {
   
    @Autowired
    private UserClient userClient;
    @GetMapping("/{id}")
    public User queryById(@PathVariable Long id){
   
        return userClient.queryById(id);
    }
}

  1. 编写feign 客户端
    在 ConsumerApplication 启动类上,添加注解,开启Feign功能
/*@SpringBootApplication
@EnableDiscoveryClient //开启Eureka客户端发现功能
@EnableCircuitBreaker //开启熔断*/
@SpringCloudApplication
@EnableFeignClients //开启Feign功能
public class ConsumerApplication {
   
    public static void main(String[] args) {
   
        SpringApplication.run(ConsumerApplication.class, args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
   
        return new RestTemplate();
    }
}

Feign中已经自动集成了Ribbon负载均衡,因此不需要自己定义RestTemplate进行负载均衡的配置

测试
Feign负载均衡及熔断

Feign中本身已经集成了Ribbon依赖和自动配置:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值