【SpringCloud】一、微服务概述、注册中心与Ribbon负载均衡技术简介

SpringCloud

微服务技术栈

  • 微服务治理
  • 异步通信技术 —> mq
  • 缓存技术 —> Redis
  • 搜索技术 —> ES集群
  • Devops —> Jenkins…

微服务

微服务是一种将各个模块拆分开独立运行以提高系统整体效率的技术,其主要特征为:

  • 单一职责:每个服务对应唯一的业务能力、做到单一职责。
  • 面向服务:对外要暴露微服务的业务接口
  • 自治:团队独立、技术独立、数据独立、部署独立,可以根据业务进行不同的技术选型
  • 隔离型强:服务的调用要做好隔离、容错、降级,避免出现一个模块的错误影响到其他模块的问题

微服务框架

国内的知名微服务框架有SpringCloud和Dubbo(阿里巴巴)

用户访问服务网关,服务网关请求路由负载均衡(服务集群),服务集群在注册中心中拉取注册和服务信息,在配置中心中拉取配置信息。

Dubbo SpringCloud SpringCloudAlibaba
注册中心 zookeeper、Redis Eureka、Consul Nacos、Eureka
服务远程调用 Dubbo协议 Feign(http协议) Dubbo、Feign
配置中心 SpringCloudConfig SpringCloudConfig、Nacos
服务网关 SpringCloudGateway、zuul SpringCloudGateWay、zuul
服务监控和保护 dubbo-admin、功能弱 Hystrix Sentinel

SpringCloud

SpringCloud组件

  • 服务注册发现:

    Eureka、Nacos、Consul

  • 远程服务调用:

    OpenFeign、Dubbo

  • 服务链路监控:

    Zipkin、Sleuth

  • 统一配置管理:

    SpringCloudConfig、Nacos

  • 统一网关路由:

    SpringCloudGateWay、Zuul

  • 流控、降级、保护:

    Hystix、Sentinel

注意:SpringCloud与SpringBoot有较为严格的匹配关系、一定要注意兼容性

服务远程调用

由于业务有可能涉及到多个模块,但同时由于微服务的限制我们不能重复开发功能,所以有了服务远程调用的概念,在业务实现时,一个模块调用另外一个模块就成为服务远程调用

服务远程调用的流程

令模块发送Http请求

使用到RestTemplate,RestTemplate是Spring的一个功能,用来发送Http请求

  • 创建RestTemplate并注入Spring容器,在SpringBoot中,这件事只能在配置类中完成,这里在启动类中做这件事:

        /**
         * 创建RestTemplate对象用于发送Http请求
         * 并注入到Spring容器中
         * @return
         */
        @Bean
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
  • 在业务层(Service)注入restTemplate

        @Autowired
        private RestTemplate restTemplate;
    
  • 调用restTemplate的方法,注意什么样的请求调用什么样的方法:

            //设置请求地址
            String url = "http://localhost:8081/user/" + order.getUserId();
            //通过RestTemplate发送请求给url的这个地址,默认返回类型为json,也可以生命返回类型为一个对象,
    		//只需要在第二个参数里添加对象的反射类
    		//这里是get请求所以使用get方法
            User user = restTemplate.getForObject(url, User.class);
    

服务调用关系

调用其他模块的服务叫做消费者,被调用的模块叫做提供者

Eureka

注意在上面的原生服务远程调用中,只能将请求的链接写死,这十分不利于功能的拓展,另外,其也无法处理分布式的问题。

而Eureka可以解决这些问题。

服务提供者会将自己的端口号信息提供给eureka-server注册中心,而服务消费者会从eureka-server注册中心中拉取对应需要的模块的请求地址,如果有很多地址的话,会通过负载均衡技术选用一个地址并进行远程调用。另外,Eureka会与服务提供者保持一个心跳请求,Eureka每隔30秒回向服务提供者确认服务列表信息,心跳不正常的信息会被剔除。

Eureka负责保存服务提供者提供的信息,

实现流程:

搭建EurekaServer —> 将模块注册到eureka —> 在对应的模块中进行服务拉取,然后通过负载均衡技术进行服务选取与远程调用。

搭建Eureka

搭建Eureka服务器

  • 引入依赖

    
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
            dependency>
    
  • 在启动类中添加Eureka的启动注解:@EnableEurekaServer

    @EnableEurekaServer
    @SpringBootApplication
    public class EurekaApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaApplication.class, args);
        }
    }
    
  • 创建配置文件并添加如下配置:

    server:
      port: 10086   #服务端口
    spring:
      application:
        name: eurekaserver  # eureka的服务名称
    eureka:
      client:
        service-url:  # eureka的地址信息
          defaultZone: http://127.0.0.1:10086/eureka
    

Eureka客户端搭建

  • 在客户端中加载Eureka客户端依赖

    
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
            dependency>
    
  • 添加配置:

    # 添加服务名称,使erueka-server能够找到你的服务 
    spring:
     application:
      name: xxxservice
    
    # eureka配置,使其能够找到eureka-server注册中心
    eureka:
      client:
        service-url:  # eureka的地址信息
          defaulZone: http://127.0.0.1:10086/eureka
    

    在左下角可以将服务进行复制从而得到多个注册信息,要注意修改端口号

使用服务名获取服务列表(负载均衡)

在restTemplate调用方法的url处将链接的地址和端口号部分更改为服务名:

	//设置请求地址
    String url = "http://userservice/user/" + order.getUserId();

使用之后在配置类中为这个服务添加负载均衡注解@LoadBalanced

    /**
     * 创建RestTemplate对象用于发送Http请求
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

这样注册之后,在模块之间进行服务远程调用时就会根据负载均衡自动调用对应的端口进行服务调用

Ribbon

SpringCloud中的负载均衡是由Ribbon实现的,restTemplate发送http://userservice/user/这样的请求之后,Ribbon对这个请求进行拦截并解析userservice,其在Eureka-Server中查找对应服务名的端口号,在找到之后返回其真实的请求地址,例如:http://localhost:8080/user/若Eureka中存在多个地址的话,会对其进行负载均衡的判断来选择一个合适的地址

常见的负载均衡算法有:

  • 随机负载均衡
  • 轮询负载均衡等

负载均衡原理:

  1. 请求在发送后会被LoadBalanceInterceptor负载均衡拦截器所拦截,在拦截器中会进行以下行为:
  2. RibbonLoadBalancerClient获取请求中的服务名称(userservice)并将其传给DynamicServerListLoadBalancer
  3. DynamicServerListLoadBalancer会从Eureka中拉取服务列表并进行负载均衡的选取,在这之中,负载均衡技术存储在IRule中
  4. 选择最终的端口,并将请求补充为真实请求并发送。

Ribbon中的负载均衡算法

  • RoundRobinRule:轮询负载均衡

  • AvailablityFilteringRule:

    • 对服务器进行选择:若对某个服务器进行三次连接失败,则将这台服务器设置为“短路”状态。短路状态将持续30s,但若再次连接失败,则会将短路状态的持续时间以几何倍的添加。
    • 同时对于并发数过高的服务器,该算法也会将其标记并忽略(这个并发数可以自定义)。
  • WeightedResponseTimeRule:

    ​ 为每个服务器赋一个权重值,服务器相应时间越长,这个权重就越小,这个规则会随机的选择服务器,而赋予的权重会影响随机的 结果

  • ZoneAvoidanceRule:(默认)

    ​ 以区域可用性进行服务器选择,并在配置的区域中进行轮询选择,若不进行区域配置,则可认为其就是普通的轮询负载均衡技术, 就像是离哪里近,就选择哪里的服务器。

  • BestAvliableRule:

    ​ 忽略短路服务器并选择并发数较低的服务器

  • RandomRule:

    ​ 随机负载均衡

  • RetryRule:

    ​ 重试机制的选择逻辑

负载均衡算法的修改

在要服务消费者中进行定义,在主类(配置类)中进行如下定义:

注意这样做是全局配置,无论最终选择哪个服务进行调用都会遵循下面的规则,若想要根据不同的服务进行调用则需要使用yml配置文件进行:

    @Bean
    public IRule randomRule() {
        return new RandomRule();
    }

在配置文件中进行负载均衡算法的选取:

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #定义针对于userservice的负载均衡规则

Ribbon的加载策略

Ribbon的加载策略默认为懒加载,即只有在服务拉取时才创建RibbonLoadBalancerClient对象与DynamicServerListLoadBalancer对象,这样做会使第一次进行服务获取的时间速度变得很慢。

我们可以对加载策略进行修改,修改加载策略为饥饿加载:

在yml中这样定义:

ribbon:
  eager-load:
    enable: true # 开启饥饿加载
    clients:
     - userservice

你可能感兴趣的:(SpringCloud,spring,cloud,微服务,ribbon)