张坤的个人博客

  • 首页
  • 分类
  • 标签
  • 日志

  • 搜索
Jenkins RabbitMQ Zookeeper IDEA Logstash Kibana ELK NIO Netty Spring Cloud Golang DataX Elasticsearch React Native Mysql H2 Socket Spring Boot Kafka Mybatis Sqlmap Vue Postgresql Docker Vert.x Flutter Flink Redis

Eureka服务搭建

发表于 2020-06-10 | 分类于 Spring Cloud | 0 | 阅读次数 37

简介

最初Eureka使用的是spring-cloud-starter-eureka这玩意,但是这个版本只有1.x,后来就没更新了,所以现在用的eureka通常是spring-cloud-starter-netflix-eureka-client这玩意

Eureka Server在Spring Cloud中被当做注册中心,Eureka Client往Eureka Server上注册自己信息,方便消费者调用服务提供者的服务。Eureka Client可以是服务提供者,也可以是服务消费者。

为什么不直接叫消费者调用服务呢?为什么要服务提供者和消费者都向Eureka Server注册自己的信息?
因为在服务很多的时候,消费者不知道服务端有多少个,以及服务是否正常,如果硬编码让某一个消费者调用服务端,这个服务端已经挂掉了,这个请求就一直卡在这里,直到网络超时为止。
还有让消费者固定的请求某一个服务端,服务端是会有性能瓶颈的,无法更好的水平扩容来提高吞吐量。那么就需要一个注册中心来管理这些服务端的ip端口等信息,如果有消费者要去请求这个服务,先去注册中心找到所有和你要获取的服务相同的地址,然后通过Ribbon负载均衡去请求其中一个服务,这样就会减少单个服务端的压力。

Eureka Client

上一篇讲了如何去搭建Eureka Server,这次把Eureka Client也搭起来,看看有啥区别

创建eureka-client子模块
eureka-client pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-learning</artifactId>
        <groupId>com.coddox</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eureka-client</artifactId>

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

</project>

上次eureka模块引入的是spring-cloud-starter-netflix-eureka-server,这次引入的是spring-cloud-starter-netflix-eureka-client
同样,需要个启动类,注解用的是@EnableEurekaClient

package com.coddox;

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

/**
 * @author zhangkun
 * @date 2020/6/10 9:47
 */
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication.class, args);
    }
}

eureka-client application.properties

# eureka server地址
eureka.client.service-url.defaultZone=http://localhost:8080/eureka
spring.application.name=eureka-client

# 端口注意不要冲突
server.port=8081

启动之后,发现eureka-client已经注册上来了
image.png

点击eureka-client服务的超链接,发现404了,看url可以发现这是个健康监控的接口
image.png
在eureka-client加上spring-boot-starter-actuator就行了

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

在次访问,发现不是404了,只不过返回了个空对象

如果把eureka-client断掉,eureka server检查到这个eureka client到期之后会出现这个报错,因为eureka server并不会马上移除它,而是会有一个保护机制,让它继续存在,我们可以在eureka-server通过配置来关闭eureka server的默认保护机制
image.png
eureka application.properties

eureka.server.enable-self-preservation=false

Eureka心跳机制

eureka client会每隔30s向eureka server发送一次心跳,可以通过修改eureka client的配置修改间隔

eureka.instance.lease-renewal-interval-in-seconds=30

eureka server在90s内没有收到eureka client的心跳,就把改eureka client的注册信息在注册表中删掉,其它eureka client就无法访问这个eureka client了,可在eureka client配置修改

eureka.instance.lease-expiration-duration-in-seconds=90

需要注意,在eureka server中,清理注册表是由一个定时任务去做的,每个60秒执行一次,如果客户端配置的eureka.instance.lease-expiration-duration-in-seconds小于60秒。那么虽然eureka client过期了但是注册表中还有这个eureka client的信息,会导致其它eureka client还认为这个已过期的eureka client还活着,并不断的请求它。
可以通过在服务端的配置修改注册表的清理间隔,时间是ms

eureka.server.eviction-interval-timer-in-ms=60000

还需要注意的是,如果服务端开启了自我保护,eureka client就不会被剔除,为了方便测试,最好在eureka server的配置中关闭自我保护

eureka client每隔30秒去eureka server中拉取注册表信息(可用的服务列表),并将服务列表缓存在本地,可以在eureka client端配置修改

eureka.client.registry-fetch-interval-seconds=30

服务提供者和消费者环境搭建

创建 eureka-provider-consumer 模块,里面有两个子模块,provider和consumer,provider是服务提供者,分别在8081,8083提供服务,consumer是服务消费者,运行在8084端口,通过ribbon来负载均衡请求8081和8083端口的服务
image.png
application.properties

eureka.client.service-url.defaultZone=http://localhost:8080/eureka
spring.application.name=provider
# 启动第一个服务
#spring.profiles.active=provider-1
# 启动第二个服务
spring.profiles.active=provider-2

application-provider-1.properties

server.port=8081
provider.name=provider-1

application-provider-2.properties

server.port=8083
provider.name=provider-2

来看看controller,通过 provider.name 来判断请求的是哪个provider

@RestController
@RequestMapping("/user-search")
public class UserSearchController {

    @Value("${provider.name}")
    private String name;

    @RequestMapping("/list")
    public String list() {
        return name;
    }
}

先把eureka跑起来,启动provider两次,主要要修改application.properties中的spring.profiles.active来指定不同的服务配置,只要端口不同就行了。然后启动消费端,端口是8084
image.png
可以发现provider的两个服务application名称都是provider,消费者就可以通过这个provider进行负载均衡的消费了

访问8081端口的服务
image.png
访问8083端口的服务
image.png

Ribbon做负载均衡

在消费端引入ribbon依赖,注意也是netflix的,看来netflix这个公司来头不小,spring cloud一堆插件都是这个公司整出来的

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

在创建RestTemplate对象的时候加上@LoadBalanced注解,就可以从客户端支持负载均衡了

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

在消费端创建一个controller,这个controller自己本身不提供服务,就专门调用服务提供端的接口

@RestController
@RequestMapping("/user-search")
public class UserSearchController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/list")
    public String list() {
        // provider 是服务提供者配置的 spring.application.name 值
        return restTemplate.getForObject("http://provider/user-search/list", String.class);
    }
}

可以看到restTemplate.getForObject()调用接口不需要指定ip端口,直接写注册到eureka server上的application名称就行了
然后我们这次不直接调用provider服务,调用consumer的服务,可以发现,ribbon默认的负载均衡策略是轮询
image.png
image.png
在8081和8083的provider服务之间来回调用

服务实例健康自检

在搭建eureka client的时候我们有提到了可以用spring-boot-starter-actuator来让eureka client自己检查自己服务的健康状态。
那这种和让eureka server来判断eureka client是否可用有什么区别呢?
想想看,如果eureka client本身并没有挂掉,还是可以继续向eureka server发送心跳,eureka server也认为eureka client是正常的。但是eureka client其中的某一项服务挂掉了,影响了整个服务,比如数据库,那么这个eureka client实际上相当于已经不可用了,这时候就需要eureka client自己检查自己哪些必须服务是不能挂的,一旦挂了就立即通知eureka server,自己已经不能提供服务了,让其它消费端别再过来白忙活了

创建 health-actuator 模块,里面有provider(运行在8081端口)和consumer(运行在8082端口),provider实现了健康自检,如果provider不健康了,那么consumer就无法访问provider了
image.png
通过consumer访问provider,这里resttemplate一定要加上@LoadBalanced才能通过服务名访问
image.png
访问/db-status接口,将数据库健康状态设置成false
image.png
可以看到eureka server已经收到了provider发送的健康状态了,并将它标记为不可用
再次通过consumer访问provider提供的服务接口时,已经是404了
image.png
这里做测试的时候可能很多小伙伴发现就算provider为不可用了,但是在30秒内还是可以正常访问,之后就不行了。
因为provider要在30秒后才会向eureka server同步一次自己的状态信息,如果想更快的看到结果,可以在provider上修改配置

eureka.client.instance-info-replication-interval-seconds=30

Eureka集群

创建两个eureka server,分别是eureka1和eureka2,eureka1和eureka2互相发送心跳,同步状态
eureka1 application.properties

eureka.client.service-url.defaultZone=http://localhost:8081/eureka
spring.application.name=eureka1
server.port=8080

eureka2 application.properties

eureka.client.service-url.defaultZone=http://localhost:8080/eureka
spring.application.name=eureka2
server.port=8081

eureka client配置defaultZone的时候就需要将两个eureka server的地址都给配置上

eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/,http://localhost:8081/eureka/

源码:https://codox.coding.net/public/springcloud-learning/springcloud-learning/git/files

# Jenkins # RabbitMQ # Zookeeper # IDEA # Logstash # Kibana # ELK # NIO # Netty # Spring Cloud # Golang # DataX # Elasticsearch # React Native # Mysql # H2 # Socket # Spring Boot # Kafka # Mybatis # Sqlmap # Vue # Postgresql # Docker # Vert.x # Flutter # Flink # Redis
Spring Cloud环境搭建
Feign实现负载均衡
  • 文章目录
  • 站点概览
会Coding的猴子

会Coding的猴子

57 日志
19 分类
28 标签
RSS
Github
Creative Commons
© 2021 会Coding的猴子
由 Halo 强力驱动
|
主题 - NexT.Gemini v5.1.4

湘ICP备18011740号