【 Eureka 注册中心 】

1、认识 Eureka

首先我们来解决第一问题,服务的管理。

问题分析

在刚才的案例中,user-service 对外提供服务,需要对外暴露自己的地址。而 consumer(调用者)需要记录服务提供者的地址。将来地址出现变更,还需要及时更新。这在服务较少的时候并不觉得有什么,但是在现在日益复杂的互联网环境,一个项目肯定会拆分出十几,甚至数十个微服务。此时如果还人为管理地址,不仅开发困难,将来测试、发布上线都会非常麻烦,这与 DevOps 的思想是背道而驰的。

网约车

这就好比是 网约车出现以前,人们出门叫车只能叫出租车。一些私家车想做出租却没有资格,被称为黑车。而很多人想要约车,但是无奈出租车太少,不方便。私家车很多却不敢拦,而且满大街的车,谁知道哪个才是愿意载人的。一个想要,一个愿意给,就是缺少引子,缺乏管理啊。

此时滴滴这样的网约车平台出现了,所有想载客的私家车全部到滴滴注册,记录你的车型(服务类型),身份信息(联系方式)。这样提供服务的私家车,在滴滴那里都能找到,一目了然。

此时要叫车的人,只需要打开APP,输入你的目的地,选择车型(服务类型),滴滴自动安排一个符合需求的车到你面前,为你服务,完美!

Eureka做什么?

Eureka 就好比是滴滴,负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉 Eureka ,然后 Eureka 会把符合你需求的服务告诉你。

同时,服务提供方与 Eureka 之间通过“心跳”机制进行监控,当某个服务提供方出现问题,Eureka 自然会把它从服务列表中剔除。

这就实现了服务的自动注册、发现、状态监控。

2、原理图

基本架构:

在这里插入图片描述

  • Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址
  • 提供者:启动后向 Eureka 注册自己信息(地址,提供什么服务)
  • 消费者:向Eureka订阅服务,Eureka 会将对应服务的所有提供者地址列表发送给消费者,并且定期更新
  • 心跳(续约):提供者定期通过 http 方式向 Eureka 刷新自己的状态

3、入门案例

编写EurekaServer

接下来我们创建一个项目,启动一个 EurekaServer:

在这里插入图片描述
在这里插入图片描述

完整的 pom 文件:

<?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>cloud-demo</artifactId>
        <groupId>cn.ys.demo</groupId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.ys.demo</groupId>
    <artifactId>eureka-demo</artifactId>

    <dependencies>
        <!-- Eureka服务端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

</project>

编写启动类:

package cn.ys;

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

@SpringBootApplication
@EnableEurekaServer // 声明这个应用是一个EurekaServer
public class EurekaServer {

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

}

编写配置:

server:
  port: 10086 # 端口
spring:
  application:
    name: eureka-server # 应用名称,会在 Eureka 中显示(例如,查看注册中心该 Application 名字就为:EUREKA-SERVER)
eureka:
  client:
    register-with-eureka: false # 是否注册自己的信息到 EurekaServer,默认是true
    fetch-registry: false # 是否拉取其它服务的信息,默认是 true
    service-url: # EurekaServer 的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址。
      defaultZone: http://127.0.0.1:${server.port}/eureka
  instance:
    prefer-ip-address: true # 希望使用 IP 地址,如果不使用 IP 地址,则,不需要加该配置
    ip-address: 127.0.0.1 # 注册中心的 IP 地址

启动服务,并访问:http://127.0.0.1:10086/eureka

在这里插入图片描述

在这里插入图片描述

user-service 注册到 Eureka

注册服务,就是在服务上添加 Eureka 的客户端依赖,客户端代码会自动把服务注册到 EurekaServer 中。

我们在 user-service 中添加 Eureka 客户端依赖:

<!-- Eureka客户端 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

在启动类上开启 Eureka 客户端功能

通过添加 @EnableDiscoveryClient@EnableEurekaClient 来开启 Eureka 客户端功能

package cn.ys.user;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import tk.mybatis.spring.annotation.MapperScan;

@EnableDiscoveryClient // 开启 EurekaClient 功能
@SpringBootApplication
@MapperScan("cn.ys.user.mapper")
public class UserServiceApplication {

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

}
  • @EnableEurekaClient :只能使用 Eureka 作为注册中心
  • @EnableDiscoveryClient:不仅可以使用 Eureka 作为注册中心,可以使用 其他注册中心

编写配置

server:
  port: 8081
spring:
  application:
    name: user-service # 应用名称
  datasource:
    url: jdbc:mysql://yangnanxi.cn:3306/springcloud
    username: yang
    password: 123456
    hikari:
      maximum-pool-size: 30
      minimum-idle: 10
eureka:
  client:
    service-url: # EurekaServer地址
      defaultZone: http://127.0.0.1:10086/eureka
  instance:
    prefer-ip-address: true # 当调用 getHostname 获取实例的 hostname 时,返回 ip 而不是 host 名称
    ip-address: 127.0.0.1 # 指定自己的 ip 信息,不指定的话会自己寻找

注意:

  • 这里我们添加了 spring.application.name 属性来指定应用名称,将来会作为应用的 id 使用。
  • 不用指定 register-with-eureka 和 fetch-registry,因为默认是 true

重启项目,访问Eureka监控页面查看

在这里插入图片描述

我们发现 user-service 服务已经注册成功了

消费者从 Eureka 获取服务

接下来我们修改 consumer-demo,尝试从 EurekaServer 获取服务。

方法与消费者类似,只需要在项目中添加 EurekaClient 依赖,就可以通过服务名称来获取信息了!

1)添加依赖:

Eureka 客户端:

<!-- Eureka客户端 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2)在启动类开启 Eureka 客户端

package cn.ys;

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

@EnableDiscoveryClient // 开启Eureka客户端
@SpringBootApplication
public class ConsumerApplication {

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

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

}

3)修改配置:

server:
  port: 8080
spring:
  application:
    name: consumer-demo # 应用名称
eureka:
  client:
    service-url: # EurekaServer 地址
      defaultZone: http://127.0.0.1:10086/eureka
  instance:
    prefer-ip-address: true # 当其它服务获取地址时提供ip而不是hostname
    ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找

4)修改 ConsumerController 代码,用 DiscoveryClient 类的方法,根据服务名称,获取服务实例:

package cn.ys.consumer.controller;

import cn.ys.consumer.pojo.User;
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.GetMapping;
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 java.util.List;

@RestController
@RequestMapping("consumer")
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("{id}")
    public User queryById(@PathVariable("id") Long id ){
//        String url = "http://localhost:8081/user/" + id;
//        User user = restTemplate.getForObject(url, User.class);

        // 根据服务名称,获取服务实例
        List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
        // 因为只有一个UserService,因此我们直接get(0)获取
        ServiceInstance instance = instances.get(0);
        // 获取ip和端口信息
        String url = "http://" + instance.getHost() + ":" +instance.getPort() + "/user/" + id;
        User user = restTemplate.getForObject(url, User.class);
        return user;
    }

}

注意:DiscoveryClient 导包为 :import org.springframework.cloud.client.discovery.DiscoveryClient;,而不是 import com.netflix.discovery.DiscoveryClient;
在这里插入图片描述

5)Debug 跟踪运行:

在这里插入图片描述

生成的 URL:

在这里插入图片描述

访问结果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42112635/article/details/88360884