01.Eureka学习

01.Eureka学习

父工程

dependencyManagement对以来版本进行管理

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>comexample</groupId>
    <artifactId>springCloudTest</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>eureka-service</module>
    </modules>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.12.RELEASE</spring-boot.version>
        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
        <lombok.version>1.18.26</lombok.version>
        <mybatis-plus.version>3.5.2</mybatis-plus.version>
        <mysql.version>8.0.33</mysql.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

服务注册

注册中心

新建一个springboot项目作为eureka服务的注册中心

<?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>comexample</groupId>
        <artifactId>springCloudTest</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>eureka-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-service</name>
    <description>eureka-service</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.12.RELEASE</spring-boot.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>
</project>

配置application.yml

server:
  # 应用服务 WEB 访问端口
  port: 8080
spring:
  application:
    # 应用名称
    name: eureka-service

eureka:
  instance:
    hostname: localhost
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: false
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

在启动类中标注@EnableEurekaServer注解

启动项目,访问http://localhost:8080/,即可访问注册中心

在这里插入图片描述

服务的提供者

新建一个项目作为服务的提供者

<?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>comexample</groupId>
        <artifactId>springCloudTest</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>provide-demo1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>provide-demo1</name>
    <description>provide-demo1</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</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-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
logging:
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
mybatis-plus:
  # 配置mybatis-plus 打印sql日志
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # mybatis-plus下划线转驼峰配置,默认为true
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      # 配置全局默认主键类型,实体类不用加@TableId(value ="id",type = IdType.AUTO)
      id-type: auto
      # 1代表已经删除,0代表没有删除
      logic-delete-value: 1
      logic-not-delete-value: 0
  # xml文件路径
  mapper-locations: classpath:/mapper/**/*.xml
  # 配置mybatis-plus 包路径
  type-aliases-package: com.example.demo.domain
server:
  # 应用服务 WEB 访问端口
  port: 8081
spring:
  application:
    # 应用名称
    name: provide-demo1
  datasource:
    # 数据库驱动
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 数据源名称
    name: defaultDataSource
    # 数据库用户名&密码
    username: root
    password: 123456
    # 数据库连接地址
    url: jdbc:mysql://localhost:3306/provider?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8

eureka:
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: true
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8080/eureka/
// 开启服务注册
@EnableEurekaClient
@MapperScan("com.example.mapper")
@SpringBootApplication
public class ProvideDemo1Application {
    public static void main(String[] args) {
        SpringApplication.run(ProvideDemo1Application.class, args);
    }
}

此时,启动provider-demo1后,再次访问eureka注册中心可查看到该服务

在这里插入图片描述

服务的消费者

新建consumer-demo,步骤与新建服务的提供者一样

logging:
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
mybatis-plus:
  # 配置mybatis-plus 打印sql日志
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # mybatis-plus下划线转驼峰配置,默认为true
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      # 配置全局默认主键类型,实体类不用加@TableId(value ="id",type = IdType.AUTO)
      id-type: auto
      # 1代表已经删除,0代表没有删除
      logic-delete-value: 1
      logic-not-delete-value: 0
  # xml文件路径
  mapper-locations: classpath:/mapper/**/*.xml
  # 配置mybatis-plus 包路径
  type-aliases-package: com.example.demo.domain
server:
  # 应用服务 WEB 访问端口
  port: 9091
spring:
  application:
    # 应用名称
    name: consumer-demo
  datasource:
    # 数据库驱动
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 数据源名称
    name: defaultDataSource
    # 数据库用户名&密码
    username: root
    password: 123456
    # 数据库连接地址
    url: jdbc:mysql://localhost:3306/consumer?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8

eureka:
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: true
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8080/eureka/

同理,消费者也注册到Eureka中了

在这里插入图片描述

RestTemplate

使用RestTemplate,通过消费者调用提供者的接口

在调用接口之前,需要先将对应mysql的数据库准备好

provider

/*
 Navicat Premium Data Transfer

 Source Server         : mysql-demo
 Source Server Type    : MySQL
 Source Server Version : 80013 (8.0.13)
 Source Host           : localhost:3306
 Source Schema         : provide

 Target Server Type    : MySQL
 Target Server Version : 80013 (8.0.13)
 File Encoding         : 65001

 Date: 04/08/2023 23:10:12
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for provider
-- ----------------------------
DROP TABLE IF EXISTS `provider`;
CREATE TABLE `provider`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `gender` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `age` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of provider
-- ----------------------------
INSERT INTO `provider` VALUES (1, '小王', '男', 12);
INSERT INTO `provider` VALUES (2, '大黄', '男', 15);
INSERT INTO `provider` VALUES (3, '阿丽', '女', 18);

SET FOREIGN_KEY_CHECKS = 1;

consumer

/*
 Navicat Premium Data Transfer

 Source Server         : mysql-demo
 Source Server Type    : MySQL
 Source Server Version : 80013 (8.0.13)
 Source Host           : localhost:3306
 Source Schema         : consumer

 Target Server Type    : MySQL
 Target Server Version : 80013 (8.0.13)
 File Encoding         : 65001

 Date: 04/08/2023 23:12:05
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for consumer
-- ----------------------------
DROP TABLE IF EXISTS `consumer`;
CREATE TABLE `consumer`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of consumer
-- ----------------------------
INSERT INTO `consumer` VALUES (1, '皇妃', '湖北');
INSERT INTO `consumer` VALUES (2, '皇子', '湖南');

SET FOREIGN_KEY_CHECKS = 1;

使用mybatisX插件快速生成domain、mapper、service

新建一个common项目,将通用的工具类以及依赖可放入其中,最后在服务的提供者消费者中引入common依赖即可

json依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>2.0.31</version>
</dependency>

工具类R

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

import java.util.HashMap;
import java.util.Map;

/**
 * @author:93879
 * @date:2023/06/09/23:31
 * @description:
 */
public class R extends HashMap<String, Object> {
    private static final long serialVersionUID = 1L;

    /**
     * 存元素 和setData的区别是 这个方法可以指定key的值
     */
    @Override
    public R put(String key, Object value) {
        super.put(key, value);
        return this;

    }

    public R setData(Object data) {
        put("data", data);
        return this;
    }

    /**
     * 获取数据
     * 远程调用服务时,另一个服务也会返回R类型的数据,这个方法可以获取key为data的value值
     * 利用fastjson进行反序列化
     */
    public <T> T getData(TypeReference<T> typeReference) {
        Object data = get("data");    //默认是map
        String jsonString = JSON.toJSONString(data);//转为json字符串
        T t = JSON.parseObject(jsonString, typeReference);//转为对象
        return t;
    }


    /**
     * 利用fastjson进行反序列化
     */
    public <T> T getData(String key, TypeReference<T> typeReference) {
        Object data = get(key);    //默认是map
        //转为json字符串
        String jsonString = JSON.toJSONString(data);//转为json字符串
        //转成需要的对象
        T t = JSON.parseObject(jsonString, typeReference);//转为对象
        return t;
    }

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    //无参构造
    public R() {
        put("code", 200);
        put("msg", "success");
    }

    //返回错误码500的错误,错误内容:未知异常,请联系管理员
    public static R error() {
        return error(500, "未知异常,请联系管理员");
    }

    //返回错误码500的错误,错误内容需要自己传入
    public static R error(String msg) {
        return error(500, msg);
    }

    //返回自定义错误码,自定义错误内容
    public static R error(int code, String msg) {
        R r = new R();
        r.put("code", code);
        r.put("msg", msg);
        return r;
    }

    //返回正常,内容需要自己传入
    public static R ok(String msg) {
        R r = new R();
        r.put("msg", msg);
        return r;
    }

    //存入多条返回消息
    public static R ok(Map<String, Object> map) {
        R r = new R();
        r.putAll(map);
        return r;
    }

    //默认返回 0 success
    public static R ok() {
        return new R();
    }

    //获取code(状态码)的值
    public Integer getCode() {
        return (Integer) this.get("code");
    }
}

编写providerController

@RestController
@RequestMapping("provider")
public class ProviderController {
    @Autowired
    private ProviderService providerService;
    @GetMapping("/{id}")
    public Provider findById(@PathVariable("id") Long id){
        return providerService.getById(id);
    }

    @GetMapping("/list")
    public List<Provider> findAll(){
        return providerService.list();
    }
}

在这里插入图片描述

接下来可以尝试使用消费者进行消费了

配置RestTemplate

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @Author: 93879
 * @Date: 2023/08/04/23:07
 * @Description:
 */
@Configuration
public class ApplicationContextConfig {
    @Bean
    public RestTemplate getTemplate() {
        return new RestTemplate();
    }
}

consumerController

import com.example.service.ConsumerService;
import com.example.util.R;
import org.springframework.beans.factory.annotation.Autowired;
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;

/**
 * @Author: 93879
 * @Date: 2023/08/05/8:09
 * @Description:
 */
@RestController
@RequestMapping("consumer")
public class ConsumerController {
    private static final String PROVIDER_URL = "http://localhost:8081/provider/";

    @Autowired
    private ConsumerService consumerService;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/provider/{id}")
    public R findProvider(@PathVariable("id") Integer id){
        Object data = restTemplate.getForObject(PROVIDER_URL + id.toString(), Object.class);
        return R.ok().setData(data);
    }

    @GetMapping("/providers/list")
    public R findProvider(){
        List data = restTemplate.getForObject(PROVIDER_URL + "list", List.class);
        return R.ok().setData(data);
    }
}

在这里插入图片描述

服务调用成功

但是这个时候朋友们就有疑惑了,所以Eureka干嘛了?就只是注册一下服务吗?

其实上面的代码有很大的问题,因为连提供者的url都是写成静态变量嵌入代码内的

所以接下来需要对代码进行修改,不指定url,而是通过服务名来访问

consumerController

private static final String PROVIDER_URL = "http://PROVIDE-DEMO1/provider/";

ApplicationContextConfig

@Configuration
public class ApplicationContextConfig {
    @Bean
    // 开启负载均衡
    @LoadBalanced
    public RestTemplate getTemplate() {
        return new RestTemplate();
    }
}

在这里插入图片描述

本来以为没有配置集群时候,是不需要开启负载均衡的

但是也要开启,否则报错如下

08-05 08:38:45:271 ERROR 15288 --- [nio-9091-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://PROVIDE-DEMO1/provider/list": PROVIDE-DEMO1; nested exception is java.net.UnknownHostException: PROVIDE-DEMO1] with root cause

java.net.UnknownHostException: PROVIDE-DEMO1
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:196) ~[na:1.8.0_281]
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:162) ~[na:1.8.0_281]
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:394) ~[na:1.8.0_281]
	at java.net.Socket.connect(Socket.java:606) ~[na:1.8.0_281]
	at java.net.Socket.connect(Socket.java:555) ~[na:1.8.0_281]

Eureka集群

eureka集群的配置是将多个eureka注册中心互相注册

新建第二个eureka-service项目

修改hosts文件‪C:\Windows\System32\drivers\etc\hosts

hosts文件内添加如下内容,用以区分两个服务

127.0.0.1  eureka1.server
127.0.0.1  eureka2.server

eureka-service1

server:
  # 应用服务 WEB 访问端口
  port: 8081
spring:
  application:
    # 应用名称
    name: eureka-service1

eureka:
  instance:
    hostname: eureka1.server
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: false
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: false
    service-url:
      defaultZone: http://eureka2.server:8082/eureka/

eureka-service2

server:
  # 应用服务 WEB 访问端口
  port: 8082
spring:
  application:
    # 应用名称
    name: eureka-service2

eureka:
  instance:
    hostname: eureka2.server
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: false
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: false
    service-url:
      defaultZone: http://eureka1.server:8081/eureka/

启动这两个eureka-service服务

在这里插入图片描述

服务注册成功

修改服务提供者和消费者的yml,注册至eureka集群

eureka:
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: true
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/

在这里插入图片描述

可以看到此时两个eureka注册中心都注册了provider和consumer

尝试调用consumer接口后成功

在这里插入图片描述

1.注册至eureka的服务并不是以服务名来命名,而是主机名

2.访问服务时希望提示ip地址

配置yml

provider

eureka:
  instance:
    instance-id: provider1-service
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: true
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/

consumer

eureka:
  instance:
    # 注册至eureka中心的名字,默认是主机名
    instance-id: consumer-service
    # 是否显示ip
    prefer-ip-address: true
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: true
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/

在这里插入图片描述

现在需要新建一个提供者,将提供者也设置成集群

consumerController

private static final String PROVIDER_URL = "http://PROVIDE-DEMO/provider/";

provider-demo1

logging:
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
mybatis-plus:
  # 配置mybatis-plus 打印sql日志
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # mybatis-plus下划线转驼峰配置,默认为true
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      # 配置全局默认主键类型,实体类不用加@TableId(value ="id",type = IdType.AUTO)
      id-type: auto
      # 1代表已经删除,0代表没有删除
      logic-delete-value: 1
      logic-not-delete-value: 0
  # xml文件路径
  mapper-locations: classpath:/mapper/**/*.xml
  # 配置mybatis-plus 包路径
  type-aliases-package: com.example.demo.domain
server:
  # 应用服务 WEB 访问端口
  port: 8091
spring:
  application:
    # 应用名称
    name: provide-demo
  datasource:
    # 数据库驱动
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 数据源名称
    name: defaultDataSource
    # 数据库用户名&密码
    username: root
    password: 123456
    # 数据库连接地址
    url: jdbc:mysql://localhost:3306/provider?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8

eureka:
  instance:
    instance-id: provider1-service
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: true
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/

provider-demo2

logging:
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
mybatis-plus:
  # 配置mybatis-plus 打印sql日志
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # mybatis-plus下划线转驼峰配置,默认为true
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      # 配置全局默认主键类型,实体类不用加@TableId(value ="id",type = IdType.AUTO)
      id-type: auto
      # 1代表已经删除,0代表没有删除
      logic-delete-value: 1
      logic-not-delete-value: 0
  # xml文件路径
  mapper-locations: classpath:/mapper/**/*.xml
  # 配置mybatis-plus 包路径
  type-aliases-package: com.example.demo.domain
server:
  # 应用服务 WEB 访问端口
  port: 8092
spring:
  application:
    # 应用名称
    name: provide-demo
  datasource:
    # 数据库驱动
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 数据源名称
    name: defaultDataSource
    # 数据库用户名&密码
    username: root
    password: 123456
    # 数据库连接地址
    url: jdbc:mysql://localhost:3306/provider?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8

eureka:
  instance:
    instance-id: provider2-service
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: true
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/

在这里插入图片描述

记住将多个提供者的服务名配置成同一个

为了区分到底调用的是提供者1还是提供者2,稍微改改代码即可

![]](https://img-blog.csdnimg.cn/400ea29625ee4ef3ab689be81b3061ed.png)

所以这里需要涉及到负载均衡的策略了(默认轮询)

服务发现

可以通过服务发现来获取该服务的信息

mport com.example.domain.Provider;
import com.example.service.ProviderService;
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 java.util.HashMap;
import java.util.Map;

/**
 * @Author: 93879
 * @Date: 2023/08/05/7:57
 * @Description:
 */
@RestController
@RequestMapping("provider")
public class ProviderController {
    @Autowired
    private DiscoveryClient discoveryClient;
    @GetMapping("/discovery")
    public Map<String,Object> discovery(){
        Map<String, Object> map = new HashMap<>();
        map.put("services",discoveryClient.getServices());
        for (ServiceInstance instance : discoveryClient.getInstances("PROVIDE-DEMO")) {
            map.put("Host",instance.getHost());
            map.put("Port",instance.getPort());
            map.put("Uri",instance.getUri());
            map.put("InstanceId",instance.getInstanceId());
            map.put("ServiceId",instance.getServiceId());
            map.put("Metadata",instance.getMetadata());
            map.put("Scheme",instance.getScheme());
        }
        return map;
    }
}

Eureka自我保护

保护模式主要用于一 组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,
Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
如果在Eureka Server的首页看到以下这段提示,则说明Eureka进入了保护模式:

在这里插入图片描述

可能导致的问题

1.某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存

2.属于分布式CAP里面的AP分支(保证高可用、分区容错性),在Consul里讲到

禁用自我保护

eureka-service

eureka:
  instance:
    hostname: eureka1.server
    # 注册至eureka中心的名字,默认是主机名
    instance-id: eureka-service1
    # 是否显示ip
    prefer-ip-address: true
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: false
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: false
    service-url:
      defaultZone: http://eureka2.server:8082/eureka/
  server:
    # 关闭自我保护机制
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 2000

provider/consumer

eureka:
  instance:
    # 注册至eureka中心的名字,默认是主机名
    instance-id: consumer-service
    # 是否显示ip
    prefer-ip-address: true
    #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
    lease- renewal-interval- in-seconds: 3
    #Eureka,服务端在收到最后-次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
    lease-expiration-duration-in-seconds: 5
  client:
    # 是否将自己注册到注册中心
    register-with-eureka: true
    # 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/

在这里插入图片描述

项目Demo

分享链接

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值