服务治理

  • RPC近程过程调用协定的外围设计思维: 在于注册核心, 因为注册核心:治理每个服务与服务之间的一个依赖关系
  • 服务治理: 在传统的RPC近程过程调用协定中,治理每个服务与服务之间的依赖关系非常复杂.能够应用服务治理技术,治理每个服务与服务之间的一个依赖关系.能够实现本地负载平衡,服务发现与注册,容错等

    服务注册与发现

    注册核心

  • 在RPC近程过程调用协定中,有一个注册核心

    • SpringCloud反对三种组册核心:

      • Consul(go语言)
      • Eureka
      • Zookeeper
    • Dubbo反对两种注册核心:

      • Zookeeper
      • Redis
  • 注册核心概念: 寄存服务地址相干信息(接口地址),通过别名注册获取
  • 原理:

    • 首先启动注册核心
    • 服务提供者(Provider)服务在启动时,把以后服务信息以别名的形式注册到注册核心
    • 服务消费者(Consumer)在调用接口的时候,应用服务别名从注册核心获取RPC近程调用地址
    • 服务消费者(Consumer)获取RPC近程调用地址后,应用本地HttpClient技术实现调用
  • 配置文件:

    server.port=8761    # 服务端口号eureka.instance.hostname=127.0.0.1    # 注册核心IP地址eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/    # 注册url地址eureka.client.register-with-eureka=false    # 是否将本人注册到注册核心(集群时须要注册)eureka.client.fetch-registry=false    # 是否须要到注册核心检索服务信息
  • 注册核心我的项目:

    1.在主类上标注@EnableEurekaServer注解开启EurekaServer服务,开启注册核心

    服务注册

  • 将服务信息注册到注册核心上
  • 配置文件:

    server.port=8001    # 服务提供者(Provider)服务端口号spring.application.name=Ticket-Service    # 服务别名,注册到注册核心的名称:serviceIdeureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/    # 服务提供者(Provider)注册到eureka注册核心的url地址eureka.client.register-with-eureka=true    # 是否将本人注册到注册核心eureka.client.fetch-registry=true    # 是否须要到注册核心检索服务信息
  • 服务提供者(Provider)我的项目:

    1.在主类上标注@EnableEurekaClient注解将服务提供者(Provider)服务注册到注册核心

    服务发现

  • 从注册核心获取服务信息
  • 配置文件:

    server.port=8200    # 服务消费者(Consumer)服务端口号spring.application.name=Ticket-User    # 服务别名,注册到注册核心的名称:serviceIdeureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/    # 服务提供者(Provider)调用服务eureka注册核心的url地址eureka.client.register-with-eureka=true    # 是否将本人注册到注册核心eureka.client.fetch-registry=true    # 是否须要到注册核心检索服务信息
  • 服务消费者(Consumer)我的项目:

    1.在SpringCloud有两种形式调用服务:Rest    Fegin(SpringCloud)
  • 应用RestTemplate,是SpringBoot的web组件,默认整合Ribbon负载均衡器.底层就是采纳的HttpClient技术
  • 创立RestTemplate并标注@Bean增加办法创立Http服务进行通信
  • RestTemplate调用有两种形式:采纳服务别名调用 间接url调用
    restTemplate.getForObject("providerName(代替IP地址)/providerUrl",String.class)
    2.在主类上标注@EnableEurekaClient(@EnableDiscoveryClient)注解开启服务消费者(Consumer)从注册核心发现服务性能
    3.应用Rest形式以别名形式调用须要依赖Ribbon负载均衡器,在RestTemplate办法上标注
    @LoadBalanced,让RestTemplate在申请时领有客户端的负载平衡的能力

  • Ribbon负载平衡:

    • 在集群操作中:

      • 首先启动注册核心
      • 多个服务提供者(Provider)服务在启动时,把以后服务信息以别名的形式注册到注册核心
      • 多个服务消费者(Consumer)在调用接口的时候,应用服务别名从注册核心获取RPC近程调用地址
      • 服务消费者(Consumer)获取RPC近程调用地址后,先应用Ribbon负载均衡器实现负载平衡再应用本地HttpClient技术实现调用
    • 负载平衡根本策略: 轮询机制(默认)

      集群

  • 微服务RPC近程过程调用协定的外围:服务治理:注册核心
  • 搭建注册核心集群: 能够解决注册核心故障导致整个微服务环境不可用的问题
  • Eureka高可用原理:

    • 默认状况下,Eureka是让服务注册的服务注册核心,不注册本人
    • Eureka高可用就是将本人作为服务向其它注册核心注册本人, 造成一组互相注册的服务注册核心,实现服务清单的相互同步, 达到高可用成果
  • 注册核心集群:

    • 在注册服务过程中,只会保障有一台注册核心有对应的服务信息数据即可,只有注册核心宕机后,才启动同步数据到其它注册核心
    • 配置文件:

      server.port=9000    # 服务端口号spring.application.name=euraka    # 注册核心集群上服务器的名称要保持一致eureka.instance.hostname=127.0.0.1    # 注册核心IP地址eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8761/eureka/    # ,注册到其它注册核心的url地址eureka.client.register-with-eureka=true    # 是否将本人注册到注册核心(集群时须要注册)eureka.client.fetch-registry=true    # 是否须要到注册核心检索服务信息

      Eureka自我爱护机制

  • Eureka自我爱护机制: 为了避免EurekaClient能够失常运行时,与EurekaServer在网络无奈通信的状况下,EurekaServer误将EurekaClient服务剔除

    1.默认状况下,EurekaClient端定时向EurekaServer端发送心跳包2.如果EurekaServer端在<肯定工夫>内没有收到EurekaClient端发送的心跳包,便会间接从服务注册列表中剔除该服务3.在<短时间>内如果失落了大量的服务实例心跳包,EurekaServer端会开启自我爱护机制,不会剔除EurekaClient端
  • 在本地开发环境中,测试时倡议敞开EurekaServer端自我爱护机制,保障不可用服务及时被剔除:

    配置文件:EurekaServer端:eureka.server.enable-self-preservation=false         # 是否开启自我爱护机制(默认开启true) eureka.server.eviction-interval-timer-in-ms=2000    # 剔除距离2秒EurekaClient端-服务提供者(Provider):# 心跳检测和续约工夫,在测试程序时,将值设置小些,保障服务敞开后,注册核心及时剔除服务eureka.instance.lease-renewal-interval-in-seconds=1    # EurekaClient端向EurekaServer端发送心跳的工夫距离秒eureka.instance.lease-expiration-duration-in-seconds=2    #     EurekaServer端在收到最初一次心跳之后等待时间下限秒,超过就剔除服务

    Zookeeper

  • Eureka闭源,应用Zookeeper代替Eureka作为注册核心
  • Zookeeper是分布式协调工具,能够实现注册核心的性能,采纳Zookeeper的长期节点类型
  • 长期节点和生命周期是相关联的,如果服务断开连接之后,长期节点就会被主动删除

    配置文件:ZookeeperClient-服务提供者(Provider):server.port=8090    # 服务端口号spring.application.name=zk-ticket    # 服务别名,注册到注册核心的名称spring.cloud.zookeeper.connect-string=127.0.0.1:2181    #注册到zookeeper注册核心的url地址 ZookeeperClient-服务消费者(Consumer):server.port=8020    # 服务端口号spring.application.name=zk-user    # 服务别名,注册到注册核心的名称spring.cloud.zookeeper.connect-string=127.0.0.1:2181    #调用服务的zookeeper注册核心的url地址1.ZookeeperClient-服务提供者(Provider)在主类上标注@EnableDiscoveryClient注解向注册核心注册服务2.ZookeeperClient-服务消费者(Consumer)在主类上标注@EnableDiscoveryClient注解从注册核心调用服务3..在调用服务的办法上标注@LoadBalanced开启Ribbon的负载平衡性能进行服务的调用

    Consul

  • Consul是开源的分布式服务发现与配置管理系统,由HashiCorp公司用Go语言开发
  • 特点:

    • 基于raft协定,比拟简洁
    • 反对健康检查
    • 反对Http和DNS协定
    • 反对跨数据中心的WAN集群
    • 提供图形界面
    • 跨平台
  • Consul环境搭建:

    • 下载Consul
    • 设置环境变量:增加Consul所在目录
    • cmd启动:consul agent -dev -ui -node=cy(-dev:开发服务器模式启动 -node:节点名 -ui界面拜访反对,默认开启)
    • 拜访Consul: http://localhost:8500

      配置文件:ConsulClient-服务提供者(Provider):server.port=8780    # 服务端口号spring.application.name=consul-ticket    # 服务别名,注册到注册核心的名称spring.cloud.consul.host=127.0.0.1        # Consul服务url地址spring.cloud.consul.port=8500            # Consul服务端口号spring.cloud.consul.discovery.hostname=192.168.66.128    # 服务在注册核心显示的IP地址(默认状况下,服务注册到注册核心,地址随机生成)ConsulClient-服务消费者(Consumer):server.port=8099    # 服务端口号spring.application.name=consul-user    # 服务别名,注册到注册核心的名称spring.cloud.zookeeper.connect-string=127.0.0.1:2181    #服务调用服务Consul注册核心的url地址1.ZookeeperClient-服务提供者(Provider)在主类上标注@EnableDiscoveryClient注解向注册核心注册服务2.ZookeeperClient-服务消费者(Consumer)在主类上标注@EnableDiscoveryClient注解从注册核心调用服务3..在调用服务的办法上标注@LoadBalanced开启Ribbon的负载平衡性能进行服务的调用

      DiscoveryClient

  • 获取注册核心的服务信息
  • 用于实现本地负载平衡

    @Autowired        // 主动拆卸private DiscoveryClient discoveryClient;    // Discovery接口,用于获取注册核心的服务信息@RequestMapping("/discoveryClientMember")public List<ServiceInstance> discoveryClientMember(){  List<ServiceInstance> instances=discoveryClient.getInstance("consul-ticket");  for(ServiceInstance serviceInstance:instances){          System.out.println("URI:"+serviceInstance.getUri());  }  return instance;}