SpringCloud微服务(二)——Eureka、Ribbon

二、Eureka注册中心

1、初始Eureka

在这里插入图片描述

  • Eureka:服务注册中心(可以是一个集群),对外暴露自己的地址。
  • Provider:启动之后向Eureka注册中心注册自己的相关信息(地址以及提供什么服务)
  • Consumer:从Eureka获取注册服务列表,从而能够消费服务。
  • 心跳:提供者定期通过http方式向Eureka刷新自己的状态
2、搭建环境

在之前的父工程下创建一个maven工程,成为注册中心
添加如下依赖:

	<dependencies>
        <!--eureka-server服务端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
            <version>1.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>

在resources中的application.yml中配置Eureka

server:
  port: 7001
eureka:
  instance:
  hostname: localhost #eureka服务端的实例名称
  client:
    register-with-eureka: false       # 表示不向注册中心注册自己
    fetch-registry: false             # 表示自己就是注册中心,职责就是维护服务实例,不需要去检索服务
    service-url:
    defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  #设置Eureka Server交互的地址查询和注册服务都要依赖这个地址

只需要编写一个启动类即可

package springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer     //注册中心
public class EurekaServer7001_App {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer7001_App.class, args);
    }
}
3、调试
<1>、修改EurekaServer

运行,来到7001端口
我们发现注册Eureka的地址名称是unknown,是因为我们没有设置访问Eureka的Application Name,就是微服务的名称,所以我们这里来到配置文件中手动进行修改:

spring:
  application:
    name: miscroservicecloud-dept 
eureka:
  client:   # 客户端注册进eureka服务列表内
    service-url:
      defaultZone: http://localhost:7001/eureka

重新运行,发现我们的微服务名称不再是unknown了,而是我们自己写的名称。

<2>、修改生产者

消费者就是要在Eureka上注册自己的相关信息,因此要对消费者做一些配置上的修改,让其能够成功注册。
首先添加如下依赖

	<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

和之前一样,配置了Eureka就要开启这项集群服务来到启动类,进行启动Eureka
,加上一个注解@EnableDiscoveryClient即可,之后和以上相同,如果我们这个时候重新运行了miscroservicecloudproviderdept8001是无法被检测到注册了的,所以还需要稍微修改一下配置

server:
  port: 8001

mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml  # mybatis配置文件所在路径
  type-aliases-package: springcloud.entities           # 所有Entity别名类所在包 
  mapper-locations:                                   # mapper映射文件 
  - classpath:mybatis/mapper/**/*.xml                     
    
spring:
  application:
    name: miscroservicecloud-dept 
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource  # 当前数据源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver    # mysql驱动包
    url: jdbc:mysql://localhost:3306/cloudDB01    # 数据库名称
    username: root
    password: 123456
    dbcp2:
      min-idle: 5                                 # 数据库连接池的最小维持连接数
      initial-size: 5                             # 初始化连接数
      max-total: 5                                # 最大连接数
      max-wait-millis: 200                        # 等待连接获取的最大超时时间                              
 
eureka:
  client:   # 客户端注册进eureka服务列表内
    service-url:
      defaultZone: http://localhost:7001/eureka

重新运行之后,显示成功。

<3>、修改消费者

首先添加依赖

	<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

在application.yml中进行相关配置

server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
    defaultZone: http://localhost:7001/eureka

使用Eureka的目的就是动态获取到地址,所以要对url的获取方式进行修改

package springcloud.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import springcloud.entities.Dept;

import java.util.List;

@RestController
public class DeptController_Consumer {

    //misroservicecloud-dept
//    private static final String REST_URL_PREFIX = "http://localhost:8081";
    private static final String REST_URL_PREFIX = "http://MISROSERVICECLOUD-DEPT";

    /**
     * 使用RestTemplate访问restful接口
     * (url,requestMap,ResponseBean.class)
     * REST请求地址、请求参数、HTTP响应转换被转换成的对象类型
     */

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping(value = "/consumer/dept/add")
    public boolean add(Dept dept){
        return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add", dept, boolean.class);
    }

    @RequestMapping(value = "/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id")Long id){
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get"+id, Dept.class);
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/consumer/dept/list")
    public List<Dept> list(){
        return  restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
    }

    //测试@EnableDiscoveryClient,消费端可以调用服务发现
    @RequestMapping(value = "/consumer/dept/discovery")
    public Object discovery(){
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery", Object.class);
    }
}
4、Eureka HA
<1>、基本架构

Eureka中三大核心角色:
Eureka Server:
Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的Eureka-Server
Service Provider:
提供服务的应用,可以是SpringBoot应用,也可以是其它任意技术实现,只要对外提供的是Rest风格的服务即可。本例中就是我们实现的miscroservicecloudproviderdept8001
Service Consumer:
消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。就是在本例中实现的miscroservicecloudconsumerdept80

<2>、Eureka Server HA

Eureka Server:服务注册中心,刚才我们只创建了一个Eureka Server,事实上Eureka Server也可以是一个集群,从而形成高可用的注册中心。
服务同步:
多个Eureka Server之间也会互相注册为服务,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会把服务的信息同步给集群中的每个节点,从而实现数据同步。因此,无论客户端访问到Eureka Server集群中的任意一个节点,都可以获取到完整的服务列表信息。
在这里插入图片描述

(1)、搭建环境
server:
  port: 7001
eureka:
  instance:
#    hostname: localhost #eureka服务端的实例名称
    hostname: eureka7001.com
  client:
    register-with-eureka: false       # 表示不向注册中心注册自己
    fetch-registry: false             # 表示自己就是注册中心,职责就是维护服务实例,不需要去检索服务
    service-url:
#      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  #设置Eureka Server交互的地址查询和注册服务都要依赖这个地址
      defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

将defaultZone的地址改变成为其他相邻的地址,做到相互连通。
然后将EurekaServer进行复制,让复制出来的也指向Eureka这项服务
创建第二个注册中心,修改相关的配置

server:
  port: 7002
eureka:
  instance:
#    hostname: localhost #eureka服务端的实例名称
    hostname: eureka7002.com
  client:
    register-with-eureka: false       # 表示不向注册中心注册自己
    fetch-registry: false             # 表示自己就是注册中心,职责就是维护服务实例,不需要去检索服务
    service-url:
#      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  #设置Eureka Server交互的地址查询和注册服务都要依赖这个地址
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/

同理创建第三个注册中心,记得修改defaultZone让其指向其相邻的地址。
由于我们对于Eureka进行了高可用的注册,所以也必须要对miscroservicecloudproviderdept8001和miscroservicecloudconsumerdept80进行两个Eureka的注册,而不只是7001端口的了,只需要在yml文件中给defaultZone加上域名即可
加了此注册信息主要就是防止其中一个节点挂了,另外的节点还可以继续工作。

(2)、调试

运行之后,发现我们现在的微服务是有三个Eureka Server。

5、Eureka Server的Register
<1>、Register

平时启动Eureka的时候还是先会报错,然后才能正常启动,现在我们的Eureka一启动首先就会注册自己,但是并不是所有情况下一开始就会注册自己,然后先报错的,这取决于一个设置register-with-eureka: false只要设置为false就不注册了,默认都是注册的。
平时注册的时候,都是以Map形式注册的,Key就是微服务的名字,Value就是InstanceID。

<2>、续约

心跳续约的默认时间是30s,每隔30s进行一次心跳的续约,但是时间也是可以配置的,超出时间范围就会被默认为宕机了。
默认配置是这样的:

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

每隔三十秒发送一次心跳,一共90秒也就是三次,如果都没有发送心跳相应,就是宕机了。
但是也不能心跳发送的太快,Eureka也会宕机的,设置默认就好,一般情况下是不会更改这个值的。

<3>、拉取列表

服务的提供方会注册自己,而消费方则会拉取服务列表,拉取也是有一定周期的:

eureka:
  client:
    registry-fetch-interval-seconds: 30
<4>、失效剔除和自我保护

一般情况下,当我们关闭某一项服务时,会触发一个服务下线的REST的请求给EurekaServer,告诉服务中心下线的请求,然后服务中心接收到请求之后就会下线。

  • 失效剔除:
    有时我们的服务提供方并不一定会正常下线,可能因为内存溢出、网络故障等原因导致服务无法正常工作。Eureka Server需要将这样的服务剔除出服务列表。因此它会开启一个定时任务,每隔60秒对所有失效的服务(超过90秒未响应)进行剔除。
eureka:
  server:
    eviction-interval-timer-in-ms: 30000
  • 自我保护:
    在这里插入图片描述
    触发了Eureka的自我保护机制。当一个服务未按时进行心跳续约时,Eureka会统计最近15分钟心跳失败的服务实例的比例是否超过了85%。在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因为服务可能没有宕机。Eureka就会把当前实例的注册信息保护起来,不予剔除。生产环境下这很有效,保证了大多数服务依然可用。
    我们可以手动关闭掉自我保护:
eureka:
  server:
    enable-self-preservation: false # 关闭自我保护模式(缺省为打开)
    eviction-interval-timer-in-ms: 1000 # 扫描失效服务的间隔时间(缺省为60*1000ms)

三、Ribbon负载均衡

1、概述

Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。所以,对Spring Cloud Ribbon的理解和使用,对于我们使用Spring Cloud来构建微服务非常重要。

简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。

2、环境搭建

首先导入maven的相关依赖

	<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
3、开启负载均衡

修改miscroservicecloudconsumerdept80的cfgbeans包里面的配置类

package springcloud.cfgbeans;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ConfigBean {

    @Bean
    @LoadBalanced   //spring cloud ribbon基于netfix实现的一套客户端 负载均衡的工具
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

总结:Ribbon默认是使用轮询来达到负载均衡,但是我们也可以去手动修改负载均衡机制,比如说随机
只需要在配置类里面写上

@Bean
    public IRule myRule(){
        return new RandomRule();    //目的:用重新选择的随机算法替代默认的轮询
    }

即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值