Spring Cloud(Finchley版本)系列教程(一) 服务注册与发现(eureka)

Spring Cloud(Finchley版本)系列教程(一) 服务注册与发现(eureka)

为了更好的浏览体验,欢迎光顾勤奋的凯尔森同学个人博客http://www.huerpu.cc:7000

如有错误恳请大家批评指正,与大家共同学习、一起成长,万分感谢。

一、构建环境

Spring Cloud的构建工具可以使用MavenGradle,但Maven任然是主流。本文档所使用的开发环境如下:

环境参数版本
JDK8
Maven3.9.4
Spring CloudFinchley
IDEidea2023.1.1 U
OSWindows11专业版

Spring Cloud相关模块

模块说明
Eureka服务注册中心,用于服务管理
Ribbon基于客户端的负载均衡组件
Hystrix容错框架,能够防止服务的雪崩效应
FeignWeb服务客户端,能够简化HTTP接口的调用
ZuulAPI网关,提供路由转发、请求过滤等功能
Config分布式配置管理
Sleuth服务跟踪
Stream构建消息驱动的微服务应用程序的框架
Bus消息代理的集群消息总线

Spring Cloud主要有5大组件,分别为服务发现组件EurekaFeignRibbonZuulHystrix。但很多都弃用了,比如Ribbon等。

注:SpringCloud版本说明

英文中文boot大版本boot代表
Angel安吉尔1.2.X1.2.8
Brixton布里克斯顿1.3.X1.3.8
Camden卡梅登1.4.X1.4.2
Dalston达斯顿1.5.X1.5.0
Edgware艾奇韦尔1.5.X1.5.19
Finchley芬奇利2.0.X2.0.8
Greenwich格林威治2.1.X2.1.2
Hoxton霍克斯顿2.2.X2.2.6
2020.0.6-aka Ilford埃福的2.5.72.5.7
2021.0.6 Jubilee朱比利2.6.x2.6.1
2022.0.0 Kilburn基尔伯恩3.0.x3.0.5

二、微服务注册与发现

Spring Cloud提供了很多服务发现组件,比如:EurekaConsulZooKeeper等。而EurekaNetflix开源的服务发现组件,它包含Server和Client两部分。Eureka Server提供服务发现的能力,每个微服务启动时,都会向Eureka Server注册自己的信息(IP、端口、微服务名称等),Eureka Server存储记录每个微服务的这些信息。Eureka Client是用于简化与Eureka Server交互的Java客户端。微服务启动后,会周期性地(默认30s)向Eureka Server发送心跳以续约自己的可用时间。如果Eureka Server在规定的时间内没有接收到微服务实例的心跳,Eureka Server则会将该实例注销(默认90s)。

常见的注册中心

组件名语言CAP一致性算法服务健康检查对外暴露接口
EurekaJavaAP可配支持HTTP
ConsulGoCPRaft支持HTTP/DNS
ZookeeperJavaCPPaxos支持客户端
NacosJavaAPRaft支持HTTP
2.1 创建EurekaServer

在idea中,创建一个名称为eurekaServerMaven工程。

image-20230906120456178

image-20230906121408500

image-20230906131449947

image-20230906121903248

pom.xml文件增加Eureka依赖,修改SpringCloud版本为Finchley.SR2,修改SpringBoot版本为2.0.6.RELEASE

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cc.huerpu</groupId>
    <artifactId>eurekaServer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eurekaServer</name>
    <description>eurekaServer</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
    </properties>
    <dependencies>
        <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>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

修改EurekaServerApplication启动类,增加@EnableEurekaServer注解。

package cc.huerpu.eurekaserver;

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

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

}

创建application.yml文件

server:
  port: 8761 # 端口号

spring:
  application:
    name: eurekaServer # Eureka名称

eureka:
  instance:
    prefer-ip-address: false
    hostname: eurekaServer
  client:
    fetch-registry: false # 表示是否从EurekaServer获取注册信息,默认为true。因为本应用是一个单点的EurekaServer,不需要同步其他的EurekaServer节点的数据,因此设为false。
    register-with-eureka: false # 是否将自己注册到EurekaServer,默认为true。由于当前应用就是EurekaServer,因此设为false。
    service-url:
      defaultZone: http://eurekaServer:8761/eureka/

修改系统的hostsWindows11hosts文件路径为:C:\Windows\System32\drivers\etc\hostsLinuxmacOS的文件路径为/etc/hosts。增加一行:127.0.0.1 eurekaServer

启动项目,并测试访问

点击idea的项目启动按钮,并访问http://eurekaserver:8761/查看Eureka首页。

image-20230906134611417

2.2 创建EurekaClient,并让它注册到EurekaServer上。

复制eurekaServer项目,修改artifactIdEurekaClient。修改application.yml文件,端口号为8000,应用名称为eurekaClient

server:
  port: 8000 # 端口号

spring:
  application:
    name: eurekaClient # Eureka名称

management:
  info:
    env:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "*"
    enabled-by-default: true

eureka:
  instance:
    prefer-ip-address: false
    hostname: eurekaClient
  client:
    healthcheck:
      enabled: true
    fetch-registry: true 
    register-with-eureka: true 
    service-url:
      defaultZone: http://eurekaServer:8761/eureka/

修改启动类,增加@EnableDiscoveryClient注解。

package cc.huerpu.eurekaclient;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientApplication {

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

}

编写一个测试接口,最简单的那种就好。

@RestController
public class UserController {

    @RequestMapping("/getUserById")
    public String getUserById(){

        return "{id:1,name:jason,age:23}";
    }

}

修改pom.xml文件,把几处地方改为eurekaClient,另外增加了一个actuator包。

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cc.huerpu</groupId>
    <artifactId>eurekaClient</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eurekaClient</name>
    <description>eurekaClient</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
    </properties>
    <dependencies>
        <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-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

启动项目,刷新http://eurekaClient:8761/会看到EurekaClient注册上来了。

image-20230906140215041

2.3 添加EurekaServer用户认证

在实际应用中,资源的访问都是需要认证的,接下来我们把EurekaServer 改造为需要认证的服务。

EurekaServer 添加security依赖:

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

修改EurekaServerapplication.yml文件,增加security认证,增加spring.security.user.namespring.security.user.password。并修改defaultZonehttp://eurekaha:eurekapwd@eurekaServer:8761/eureka/

server:
  port: 8761 # 端口号

spring:
  security:
    user:
      name: eureka
      password: eurekapwd
  application:
    name: eurekaServer # Eureka名称

eureka:
  instance:
    prefer-ip-address: false
    hostname: eurekaServer
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka:eurekapwd@eurekaServer:8761/eureka/

EurekaServercc.huerpu.eurekaserver.security包路径下创建WebSecurityConfig类,关闭csrf,并开启httpBasic认证。

package cc.huerpu.eurekaserver.security;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
            .httpBasic();
    }
}

重新启动项目,访问时需要认证登录。

image-20230906144643762

输入配置文件里的账号/密码:eureka/eurekapwd进行登录。

image-20230906144720577

如果你的没有注册上来,耐心等一分钟就可以了。

对于创建Eureka的注册中心集群,请参考文章:http://www.huerpu.cc:7000/?p=607。这里就不做过多的介绍了。

三、创建一个eurekaClientConsumer调用eurekaClient服务

复制eurekaClient项目,修改artifactIdeurekaClientConsumer。修改application.yml文件,端口号为8001,应用名称为eurekaClientConsumer(本机host中也增加这一个)。

127.0.0.1   localhost
127.0.0.1   eurekaServer
127.0.0.1   eurekaClient
127.0.0.1   eurekaclientconsumer
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cc.huerpu</groupId>
    <artifactId>eurekaClientConsumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eurekaClientConsumer</name>
    <description>eurekaClientConsumer</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
    </properties>
    <dependencies>
        <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-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

server:
  port: 8001 # 端口号

spring:
  application:
    name: eurekaClientConsumer # Eureka名称


management:
  info:
    env:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "*"
    enabled-by-default: true

eureka:
  instance:
    prefer-ip-address: false
    hostname: eurekaClientConsumer
  client:
    healthcheck:
      enabled: true
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka:eurekapwd@eurekaServer:8761/eureka/

修改启动类名称为EurekaClientConsumerApplication,并增加注入一个restTemplate

package cc.huerpu.eurekaclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaClientConsumerApplication.class, args);
    }
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

controller包下创建一个ConsumerController类,注入restTemplateeurekaClientdiscoveryClient

package cc.huerpu.eurekaclient.controller;

import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;

@RestController
public class ConsumerController {
    @Autowired
    private RestTemplate  restTemplate;
    @Autowired
    private EurekaClient eurekaClient;

    @Autowired
    private DiscoveryClient discoveryClient;

    //获得eurekaClient的url
    @RequestMapping("/eurekaClientServiceUrl")
    private String eurekaClientServiceUrl() {
        InstanceInfo instance = eurekaClient.getNextServerFromEureka("eurekaClient", false);
        return instance.getHomePageUrl();
    }

    @RequestMapping("/consumerEurekaClient")
    public String consumerEurekaClient(){
        String eurekaClientURL = eurekaClientServiceUrl();
        String res = restTemplate.getForObject(eurekaClientURL + "/getUserById",String.class);
        return "consumerEurekaClient:" + res;
    }

    @RequestMapping("/eurekaClient-instance")
    public List<ServiceInstance> showInfo() {
        return this.discoveryClient.getInstances("eurekaClient");
    }
}

在没有服务注册中心的时候,eurekaClientConsumer服务调用eurekaClient服务,需要在eurekaClientConsumer服务代码里显式通过硬编码IP地址和端口号进行调用,也可以通过@Value注入配置的方式进行配置,但被调用方方的IP和端口号变化之后,调用方就必须进行修改,针对千千万万的接口来说,维护这些信息简直是场噩梦。

@RestController
public class ConsumerController {

    @RequestMapping("/consumerEurekaClient")
    public String consumerEurekaClient(){
        String res = restTemplate.getForObject("http://localhost:8000/getUserById", String.class);
        return "consumerEurekaClient:" + res;
    }
  
}
@RestController
public class ConsumerController {
		//通过配置文件中的hep.eurekaclient.userservice.url值进行配置
    @Value("${hep.eurekaclient.userservice.url}")
    private String eurekaClient;
    @RequestMapping("/consumerEurekaClient")
    public String consumerEurekaClient(){
        String res = restTemplate.getForObject("http://localhost:8000/getUserById", String.class);
        return "consumerEurekaClient:" + res;
    }
}

但现在我们通过eureka就没有这个烦恼啦,只需要eurekaClient.getNextServerFromEureka("eurekaClient", false),就可以获得服务的调用地址,其中"eurekaClient"是由spring.application.name指定的,即使被调用方的IP和端口号变化,对我们来说都是无感的,调用方这边完全不用做任何修改,是不是很开心?

访问http://eurekaclientconsumer:8001/consumerEurekaClient,就可以得到consumerEurekaClient:{id:1,name:jason,age:23},证明我们的消费方consumerEurekaClient调用被消费方eurekaClient成功了。

image-20230420150333493

四、Eureka 的元数据

Eureka 的元数据有两种,标准元数据和自定义元数据。标准元数据有主机名、IP地址、端口号、状态页和健康检查等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。自定义元数据可以使用eureka.instance.metadata-map配置。

可以通过http://eurekaserver:8761/eureka/apps来查看eureka中有哪些应用。

<applications>
	<versions__delta>1</versions__delta>
	<apps__hashcode>UP_3_</apps__hashcode>
	<application>
		<name>EUREKASERVER</name>
		<instance>
			<instanceId>localhost:eurekaServer:8761</instanceId>
			<hostName>eurekaServer</hostName>
			<app>EUREKASERVER</app>
			<ipAddr>192.168.75.1</ipAddr>
			<status>UP</status>
			<overriddenstatus>UNKNOWN</overriddenstatus>
			<port enabled="true">8761</port>
			<securePort enabled="false">443</securePort>
			<countryId>1</countryId>
			<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
				<name>MyOwn</name>
			</dataCenterInfo>
			<leaseInfo>
				<renewalIntervalInSecs>30</renewalIntervalInSecs>
				<durationInSecs>90</durationInSecs>
				<registrationTimestamp>1693982763311</registrationTimestamp>
				<lastRenewalTimestamp>1693984895889</lastRenewalTimestamp>
				<evictionTimestamp>0</evictionTimestamp>
				<serviceUpTimestamp>1693982734094</serviceUpTimestamp>
			</leaseInfo>
			<metadata>
				<management.port>8761</management.port>
			</metadata>
			<homePageUrl>http://eurekaServer:8761/</homePageUrl>
			<statusPageUrl>http://eurekaServer:8761/actuator/info</statusPageUrl>
			<healthCheckUrl>http://eurekaServer:8761/actuator/health</healthCheckUrl>
			<vipAddress>eurekaServer</vipAddress>
			<secureVipAddress>eurekaServer</secureVipAddress>
			<isCoordinatingDiscoveryServer>true</isCoordinatingDiscoveryServer>
			<lastUpdatedTimestamp>1693982763311</lastUpdatedTimestamp>
			<lastDirtyTimestamp>1693982733236</lastDirtyTimestamp>
			<actionType>ADDED</actionType>
		</instance>
	</application>
	<application>
		<name>EUREKACLIENT</name>
		<instance>
			<instanceId>localhost:eurekaClient:8000</instanceId>
			<hostName>eurekaClient</hostName>
			<app>EUREKACLIENT</app>
			<ipAddr>192.168.75.1</ipAddr>
			<status>UP</status>
			<overriddenstatus>UNKNOWN</overriddenstatus>
			<port enabled="true">8000</port>
			<securePort enabled="false">443</securePort>
			<countryId>1</countryId>
			<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
				<name>MyOwn</name>
			</dataCenterInfo>
			<leaseInfo>
				<renewalIntervalInSecs>30</renewalIntervalInSecs>
				<durationInSecs>90</durationInSecs>
				<registrationTimestamp>1693982763312</registrationTimestamp>
				<lastRenewalTimestamp>1693984884241</lastRenewalTimestamp>
				<evictionTimestamp>0</evictionTimestamp>
				<serviceUpTimestamp>1693982751862</serviceUpTimestamp>
			</leaseInfo>
			<metadata>
				<management.port>8000</management.port>
			</metadata>
			<homePageUrl>http://eurekaClient:8000/</homePageUrl>
			<statusPageUrl>http://eurekaClient:8000/actuator/info</statusPageUrl>
			<healthCheckUrl>http://eurekaClient:8000/actuator/health</healthCheckUrl>
			<vipAddress>eurekaClient</vipAddress>
			<secureVipAddress>eurekaClient</secureVipAddress>
			<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
			<lastUpdatedTimestamp>1693982763312</lastUpdatedTimestamp>
			<lastDirtyTimestamp>1693982751816</lastDirtyTimestamp>
			<actionType>ADDED</actionType>
		</instance>
	</application>
	<application>
		<name>EUREKACLIENTCONSUMER</name>
		<instance>
			<instanceId>localhost:eurekaClientConsumer:8001</instanceId>
			<hostName>eurekaClientConsumer</hostName>
			<app>EUREKACLIENTCONSUMER</app>
			<ipAddr>192.168.75.1</ipAddr>
			<status>UP</status>
			<overriddenstatus>UNKNOWN</overriddenstatus>
			<port enabled="true">8001</port>
			<securePort enabled="false">443</securePort>
			<countryId>1</countryId>
			<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
				<name>MyOwn</name>
			</dataCenterInfo>
			<leaseInfo>
				<renewalIntervalInSecs>30</renewalIntervalInSecs>
				<durationInSecs>90</durationInSecs>
				<registrationTimestamp>1693984674119</registrationTimestamp>
				<lastRenewalTimestamp>1693984884145</lastRenewalTimestamp>
				<evictionTimestamp>0</evictionTimestamp>
				<serviceUpTimestamp>1693984674119</serviceUpTimestamp>
			</leaseInfo>
			<metadata>
				<management.port>8001</management.port>
			</metadata>
			<homePageUrl>http://eurekaClientConsumer:8001/</homePageUrl>
			<statusPageUrl>http://eurekaClientConsumer:8001/actuator/info</statusPageUrl>
			<healthCheckUrl>http://eurekaClientConsumer:8001/actuator/health</healthCheckUrl>
			<vipAddress>eurekaClientConsumer</vipAddress>
			<secureVipAddress>eurekaClientConsumer</secureVipAddress>
			<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
			<lastUpdatedTimestamp>1693984674119</lastUpdatedTimestamp>
			<lastDirtyTimestamp>1693984674059</lastDirtyTimestamp>
			<actionType>ADDED</actionType>
		</instance>
	</application>
</applications>

我们在上面也有写了一个接口,用来获得eurekaClient服务的相关实例。

@Autowired
private DiscoveryClient discoveryClient;

@RequestMapping("/eurekaClient-instance")
public List<ServiceInstance> showInfo() {
    return this.discoveryClient.getInstances("eurekaClient");
}
<List>
	<item>
		<host>eurekaClient</host>
		<port>8000</port>
		<metadata>
			<management.port>8000</management.port>
		</metadata>
		<secure>false</secure>
		<uri>http://eurekaClient:8000</uri>
		<serviceId>EUREKACLIENT</serviceId>
		<instanceInfo>
			<instanceId>localhost:eurekaClient:8000</instanceId>
			<app>EUREKACLIENT</app>
			<appGroupName />
			<ipAddr>192.168.75.1</ipAddr>
			<sid>na</sid>
			<homePageUrl>http://eurekaClient:8000/</homePageUrl>
			<statusPageUrl>http://eurekaClient:8000/actuator/info</statusPageUrl>
			<healthCheckUrl>http://eurekaClient:8000/actuator/health</healthCheckUrl>
			<secureHealthCheckUrl />
			<vipAddress>eurekaClient</vipAddress>
			<secureVipAddress>eurekaClient</secureVipAddress>
			<countryId>1</countryId>
			<dataCenterInfo _class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
				<name>MyOwn</name>
			</dataCenterInfo>
			<hostName>eurekaClient</hostName>
			<status>UP</status>
			<overriddenStatus>UNKNOWN</overriddenStatus>
			<leaseInfo>
				<renewalIntervalInSecs>30</renewalIntervalInSecs>
				<durationInSecs>90</durationInSecs>
				<registrationTimestamp>1693982763312</registrationTimestamp>
				<lastRenewalTimestamp>1693984674011</lastRenewalTimestamp>
				<evictionTimestamp>0</evictionTimestamp>
				<serviceUpTimestamp>1693982751862</serviceUpTimestamp>
			</leaseInfo>
			<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
			<metadata>
				<management.port>8000</management.port>
			</metadata>
			<lastUpdatedTimestamp>1693982763312</lastUpdatedTimestamp>
			<lastDirtyTimestamp>1693982751816</lastDirtyTimestamp>
			<actionType>ADDED</actionType>
			<asgName />
		</instanceInfo>
		<scheme />
	</item>
</List>

五、Eureka的健康检查

在pom文件中引入Spring Boot Actuator,它提供了/health端点,该端点可展示应用程序的健康信息。

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

引入Actuator后,在Eureka中开启健康检查。

eureka:
  client:
    healthcheck:
      enabled: true 	 #开启健康检查(依赖spring-boot-actuator)

访问http://localhost:8761/actuator/health可以查看Eureka的状态。

若出现下面红色警告,其实是Eureka进入自我保护模式。如果最近一分钟实际接收到的心跳值Renews除以期望的心跳阈值 Renews threshold小于等于0.85,即 Renews/Renews threshold≤0.85

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE

可以把renewal-percent-threshold调的小一些

eureka:
  server:
    renewal-percent-threshold: 0.49

或者暴力一点关闭自我保护模式

# 默认值是true
eureka:
  server:
  	enable-self-preservation: false

默认情况下,服务注册到Eureka Server的过程较慢。在开发或测试时,常常希望能够加速这一过程,从而提升工作效率。

##默认是30,单位秒。设成一个更小的值,该配置用于设置Eureka Client向Eureka Server发送心跳的时间间隔
eureka:
  instance:
    lease-renewal-interval-in-seconds: 5

本文参考SpringCloud官方文档:https://docs.spring.io/spring-cloud-netflix/docs/4.0.1/reference/html/

六、部署eurekaserver到ubuntu22.04服务器

每次都启动eureka的项目,太繁琐了,我们把eureka部署到Ubuntu,就可以愉快的玩耍了。最好部署到一台可以远程访问的服务器,这样在任何地方都可以注册服务和消费服务了。

6.1 配置文件设置

这里为了演示,我们准备好了一台 ubuntu22.04,IP地址为192.168.169.128

eurekaserver项目,创建application-text.yml文件,内容如下

server:
  port: 8761 # 端口号

spring:
  security:
    user:
      name: eureka
      password: eurekapwd
  application:
    name: eurekaServer # Eureka名称

eureka:
  server:
    enable-self-preservation: true
  instance:
    prefer-ip-address: ture
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka:eurekapwd@192.168.169.128:8761/eureka/

application.properties中增加让test生效配置。

spring.profiles.active=test
6.2 生成eurekaserver的jar包

生成eurekaserver的jar包:

image-20230906154343842

6.3 ubuntu安装jdk1.8
sudo su -

apt update

apt upgrade -y

apt install openjdk-8-jre-headless

java -version
6.4 运行eurekaServer-0.0.1-SNAPSHOT.jar包

我们把eurekaServer-0.0.1-SNAPSHOT.jar包 放在/usr/software目录下,根据个人喜好目录存放即可。使用MobaXterm等SSH工具上传即可。

cd /usr
#创建software文件夹,在此文件夹下有我们的eurekaServer-0.0.1-SNAPSHOT.jar包,可以通过上传工具上传过来
mkdir software
#赋予权限
chmod -R 777 software
#进入到software目录
cd software

#运行jar包
nohup java -jar eurekaServer-0.0.1-SNAPSHOT.jar > log.txt &

#开放8761端口
ufw allow 8761
ufw enable
6.5 验证eurekaserver服务

打开http://192.168.169.128:8761/查看,Eureka已经启动了。

image-20230906154948081

eurekaClient项目修改defaultZonehttp://eureka:eurekapwd@192.168.169.128:8761/eureka/prefer-ip-address改为true

defaultZone: http://eureka:eurekapwd@192.168.169.128:8761/eureka/
prefer-ip-address: true

重启eurekaClient项目,并刷新eurekaserver,查看服务是否注册上来。

image-20230906160544912

七、eureka相关说明

7.1 EurekaServer REST API接口
POST    /eureka/apps/{appId}                                            注册新的实例

DELETE  /eureka/apps/{appId}/{instanceId}                               注销应用实例

PUT     /eureka/apps/{appId}/{instanceId}                               应用实例发送心跳

GET     /eureka/apps                                                    查询所有的实例

GET     /eureka/apps/{appId}                                            查询指定appId的实例

GET     /eureka/apps/{appId}/{instanceId}                               查询指定appId和instanceId的实例

GET     /eureka/instances/{instanceId}                                  查询指定的instanceId的实例

PUT     /eureka/apps/{appId}/{instanceId}/status?value=OUT_OF_SERVICE   暂停应用实例

PUT     /eureka/apps/{appId}/{instanceId}/status?value=UP               恢复应用实例

PUT     /eureka/apps/{appId}/{instanceId}/metadata?key=value            更新元数据信息

GET     /eureka/vips/{vipAddress}                                       根据vip地址查询

GET     /eureka/svips/{svipAddress}                                     根据svip地址查询
7.2 Client端参数
eureka.client.register-with-eureka: true                     是否注册自己到Eureka Server上面
eureka.client.fetch-registry: true                           是否从Eureka Server上面拉取服务信息
eureka.client.enable: true                                   是否启用Eureka客户端,不启用则不注册到Eureka Server
eureka.client.healthcheck.enable: true                       是否启用Eureka健康检查
eureka.client.availability-zones: new HashMap<>()            告诉client有哪些可用的region和zone
eureka.client.filter-only-up-instances: true                 是否过滤出InstanceStatus为UP的实例
eureka.client.region: us-east-1                              指定该应用实例所在的region,AWS datacenters适用
eureka.client.prefer-same-zone-eureka: true                  是否优先使用与该应用相同Zone的Eureka Server
eureka.client.cache-refresh-executor-thread-pool-size: 2     缓存刷新线程池CacheRefreshThread的初始化线程数
eureka.client.registry-fetch-interval-seconds: 30            Eureka client拉取服务注册信息间隔时间(s)
eureka.client.instance-info-replication-interval-seconds: 30 复制实例变化信息到Eureka服务器所需要的时间间隔(s)
eureka.client.eureka-service-url-poll-interval-seconds:  300 轮询Eureka服务端地址更改的间隔时间(s)
eureka.client.eureka-server-read-timeout-seconds: 8          读取Eureka Server信息的超时时间(s)
eureka.client.eureka-server-connect-timeout-seconds: 5       连接Eureka Server的超时时间(s)
eureka.client.eureka-server-total-connections: 200           从Eureka客户端到所有Eureka服务端的连接总数
eureka.client.eureka-server-total-connections-per-host: 50   从Eureka客户端到每个Eureka服务端主机的连接总数
eureka.client.eureka-connection-idle-timeout-seconds: 30     Eureka服务端连接的空闲关闭时间(s)
eureka.instance.metadata-map: new HashMap<>()                指定应用实例的元数据信息
eureka.instance.prefer-ip-address: false                     是否优先使用ip地址来替代hostname作为实例hostname字段值 
eureka.instance.lease-expiration-duration-in-seconds: 90     Eureka clent最后一次心跳后,Eureka Server剔除需要等待时间(s)
eureka.instance.lease-renewal-interval-in-seconds: 30        客户端向Eureka Server发送心跳周期(s)
7.3 Server端参数
eureka.server.enable-self-preservation: true                 Eureka Server是否开启自我保护模式
eureka.server.renewal-percent-threshold: 0.85                指定每分钟需要收到的续约次数的阙值,如果阈值比最小值大,则自我保护模式开启
eureka.server.eviction-interval-timer-in-ms: 60*1000         指定EvictionTask定时任务的调度频率,用于剔除过期的实例
eureka.server.wait-time-in-ms-when-sync-empty: 1000*60*5     在Eureka服务器获取不到集群里对等服务器上的实例时,需要等待的时间

八、代码地址

代码共享地址:http://www.huerpu.cc:2080/root/springcloud-finchley

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

勤奋的凯尔森同学

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值