2021-04-25-SpringCloud学习总结(二)

搭建服务注册中心 --Eureka

Eureka 简介

  • Eureka 是 Netflix 出品的用于实现服务注册和发现的工具。 Spring Cloud 集成了 Eureka,并提供了开箱即用的支持。其中, Eureka 又可细分为 Eureka Server 和 Eureka Client。
    在这里插入图片描述
    上图是基于集群配置的eureka;
    处于不同节点的eureka通过Replicate进行数据同步
    Application Service为服务提供者
    Application Client为服务消费者
    Make Remote Call完成一次服务调用

Eureka原理

  • 服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。
  • 当服务注册中心Eureka Server检测到服务提供者因为宕机、网络原因不可用时,则在服务注册中心将服务置为DOWN状态,并把当前服务提供者状态向订阅者发布,订阅过的服务消费者更新本地缓存。
  • 服务提供者在启动后,周期性(默认30秒)向Eureka Server发送心跳,以证明当前服务是可用状态。Eureka Server在一定的时间(默认90秒)未收到客户端的心跳,则认为服务宕机,注销该实例

搭建一个父工程继承SpringBoot父工程和SpringCloud父工程

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.1.7.RELEASE</version>
   <relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.qf.test</groupId>
<artifactId>springcloud_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud_demo</name>
<description>Demo project for Spring Boot</description>

<properties>
   <java.version>1.8</java.version>
  <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
</properties>

<dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-dependencies</artifactId>
         <version>${spring-cloud.version}</version>
         <type>pom</type>
         <scope>import</scope>
      </dependency>
   </dependencies>
</dependencyManagement>

创建一个SpringBoot Web项目继承父工程

  • POM
<parent>
   <groupId>com.qf.test</groupId>
   <artifactId>springcloud_demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.qf.test</groupId>
<artifactId>springcloud_eureka_server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud_eureka_server</name>
<description>Demo project for Spring Boot</description>

<properties>
   <java.version>1.8</java.version>
</properties>

<dependencies>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
   </dependency>

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

   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
   </dependency>
</dependencies>

  • 主启动类
@SpringBootApplication
@EnableEurekaServer
public class SpringcloudEurekaServerApplication {
   public static void main(String[] args) {
      SpringApplication.run(SpringcloudEurekaServerApplication.class, args);
   }
}

  • 配置

#配置eureka

#关闭eureka自动注册服务,默认为true,如果不设置会把当前应用注册上去
eureka.client.register-with-eureka=false
#禁止当前微服务调用其他微服务
eureka.client.fetch-registry=false
#eureka注册中心地址,这个地址不要驼峰
eureka.client.service-url.defaultZone=http://localhost:8080/eureka

#配置应用程序的名称,不要使用下划线命名
spring.application.name=eureka-server

  • 访问
    http://localhost:8080

搭建微服务-提供者

  • 创建一个SpringBooWeb项目继承父工程
    在这里插入图片描述
  • 自定义一个Controller
@RequestMapping(value = "/hello")
public class HelloController {

    @RequestMapping(value = "/test1/{id}")
    @ResponseBody
    public String test1(@PathVariable  Integer id){
        System.out.println("HelloController.test1 id:"+id);
        return "id:"+id;
    }
}

因为SpringCloud是通过HTTP调用服务,所以这里要写一个Controller

  • 配置
server.port=8081

#eureka服务中心地址
eureka.client.service-url.defaultZone=http://localhost:8080/eureka

# 微服务提供者名称
spring.application.name=eureka-provide

  • 主启动类
@EnableEurekaServer
@SpringBootApplication(scanBasePackages = "com.qf")
public class EurekaProviderApplication {

   public static void main(String[] args) {
      SpringApplication.run(EurekaProviderApplication.class, args);
   }
}

  • 测试
  • 在eureka注册中心可以看到该微服务
  • 可以直接在浏览器中调用微服务提供者的Controller

Eureka自我保护机制

  • eureka.server.enable-self-preservation=false(默认是true)
    打开自我保护机制:注册中心不会自动移除不可用的微服务,Eureka会保护起来。
    关闭自我保护机制: 注册中心会自动移除不可用的微服务

  • Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期,但是在保护期内如果服务刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,此时会调用失败,对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。

  • Eureka 的自我保护模式是有意义的,该模式被激活后,它不会从注册列表中剔除因长时间没收到心跳导致租期过期的服务,而是等待修复,直到心跳恢复正常之后,它自动退出自我保护模式。

  • 这种模式旨在避免因网络分区故障导致服务不可用的问题。例如,两个客户端实例 C1 和 C2 的连通性是良好的,但是由于网络故障,C2 未能及时向 Eureka 发送心跳续约,这时候 Eureka 不能简单的将 C2 从注册表中剔除。因为如果剔除了,C1 就无法从 Eureka 服务器中获取 C2 注册的服务,但是这时候 C2 服务是可用的。

  • 自我保护机制的触发条件
    Renews threshold:期望每分钟收到客户端心跳数
    Renews (last min):最后1分钟收到客户端实心跳数

    当Renews <Renews threshold * 0.85 就会触发自我保护机制

服务消费者–Ribbon

  • 创建一个SpringBootWeb工程
    在这里插入图片描述
  • pom
<parent>
   <groupId>com.qf.test</groupId>
   <artifactId>springcloud_demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.qf.test</groupId>
<artifactId>eureka_consumer_ribbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka_consumer_ribbon</name>
<description>Demo project for Spring Boot</description>

<properties>
   <java.version>1.8</java.version>
   <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
</properties>

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

   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
   </dependency>
</dependencies>


  • 主启动类
@EnableEurekaClient
@SpringBootApplication(scanBasePackages = "com.qf")
public class EurekaConsumerRibbonApplication {

   public static void main(String[] args) {
      SpringApplication.run(EurekaConsumerRibbonApplication.class, args);
   }

   @Bean
   @LoadBalanced // 负载均衡
   public RestTemplate restTemplate(){
      return new RestTemplate();
   }

@Bean // 随机的负载均衡方式
public IRule getRule(){
   return new RandomRule();
}

}

  • 配置
server.port=8082

eureka.client.service-url.defaultZone=http://localhost:8080/eureka

spring.application.name=eureka-consumer-ribbon

  • Controller
@Controller
@RequestMapping(value = "/consumer")
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/hello")
    @ResponseBody
    public String test(){
        System.out.println("RibbonTest.test");

        // 这种写法耦合了IP和端口,如果IP发生变化需要在这里修改代码
//        String reuslt = restTemplate.getForObject("http://localhost:8081/provider/test/11", String.class);

        // 这里是写的微服务的名称,需要RestTemplate上添加@LoadBalanced注解
        String reuslt = restTemplate.getForObject("http://EUREKA-PROVIDER/provider/test/11", String.class);
        return "[ribbon result ] "+reuslt;
    }

}

  • 负载均衡原理
    在这里插入图片描述

服务消费者–Feign

  • 面向对象的方式调用微服务,类似于Dubbo中的方式。
  • 创建一个SpringBootWeb工程
    在这里插入图片描述
  • pom
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

  • 主启动类
@EnableEurekaClient
@EnableFeignClients("com.qf.service")
@SpringBootApplication(scanBasePackages = "com.qf")
public class EurekaConsumerFeginApplication {
   public static void main(String[] args) {
      SpringApplication.run(EurekaConsumerFeginApplication.class, args);
   }
}

  • 配置
server.port=8084
eureka.client.service-url.defaultZone=http://localhost:8080/eureka
spring.application.name=enreka-consumer-fegin


  • Service
@FeignClient(name = "EUREKA-PROVIDE") // 调用服务的名称
@RequestMapping(value = "/provider") // 要和服务提供者保持一致
public interface HelloService {

    @RequestMapping(value = "/test1/{id}")// 要和服务提供者保持一致
    String test1(@PathVariable("id") Integer id);
}

@PathVariable中需要加属性名称

  • Controller
@Controller
@RequestMapping(value = "consumerFegin")
public class HelloController {

    @Autowired
    private HelloService helloService;

    @RequestMapping(value = "/test1")
    @ResponseBody
    public String test1(){
        System.out.println();
        return helloService.test1(10);
    }
}

服务消费Ribbon和Feign区别

  • Ribbon
    Ribbon 是一个基于 HTTP 客户端的负载均衡器,从 Eureka 注册中心获取服务端列表。
  • Feign
    Feign 是在 Ribbon的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。采用接口的方式, 只需要创建一个接口,然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方法即可,不需要自己构建http请求。
  • 总结起来就是:发布到注册中心的服务方接口是 HTTP的,也可以不用 Ribbon 或者 Feign,直接浏览器一样能够访问。只不过 Ribbon 或者 Feign 调用起来要方便一些,最重要的是:它俩都支持软负载均衡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值