四、Consul服务注册与发现

news2024/11/24 2:53:32

一、Consul服务注册与发现

1、为什么引入

微服务所在的IP地址和端口号硬编码到订单微服务中,会存在非常多的问题

(1)如果订单微服务和支付微服务的IP地址或者端口号发生了变化,则支付微服务将变得不可用,需要同步修改订单微服务中调用支付微服务的IP地址和端口号。

(2)如果系统中提供了多个订单微服务和支付微服务,则无法实现微服务的负载均衡功能。

(3)如果系统需要支持更高的并发,需要部署更多的订单微服务和支付微服务,硬编码订单微服务则后续的维护会变得异常复杂。

所以,在微服务开发的过程中,需要引入服务治理功能,实现微服务之间的动态注册与发现,从此刻开始我们正式进入SpringCloud实战。

2、对照大纲

二、为什么不再使用传统老牌的Eureka

  1. Eureka停更进维

    Home · Netflix/eureka Wiki · GitHub

  2. Eureka对初学者不友好 

    首次看到自我保护机制

  3.  注册中心独立且和微服务功能解耦

    目前主流服务中心,希望单独隔离出来而不是作为一个独立微服务嵌入到系统中


     

    按照Netflix的之前的思路,注册中心Eureka也是作为一个微服务且需要程序员自己开发部署;

    实际情况,希望微服务和注册中心分离解耦,注册中心和业务无关的,不要混为一谈。

    提供类似tomcat一样独立的组件,微服务注册上去使用,是个成品。

  4. 阿里巴巴Nacos的崛起

    Service discovery and configuration management​

三、consul简介

1、是什么

a、consul官网地址(Consul by HashiCorp)

b、What is Consul?

Consul 是一套开源的分布式服务发现和配置管理系统,由 HashiCorp 公司用 Go 语言开发

提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格,总之Consul提供了一种完整的服务网格解决方案。它具有很多优点。包括: 基于 raft 协议,比较简洁; 支持健康检查, 同时支持 HTTP 和 DNS 协议 支持跨数据中心的 WAN 集群 提供图形界面 跨平台,支持 Linux、Mac、Windows。

What is Consul? | Consul | HashiCorp Developer

c、禁止使用问题

条款链接

https://www.hashicorp.com/terms-of-evaluation 

放心用

HashiCorp是一家非常知名的基础软件提供商,很多人可能没听过它的名字,但是其旗下的6款主流软件,Terraform、Consul、Vagrant、Nomad、Vault,Packer 相信不少程序员都听说或使用过,尤其是Consul使用者不尽其数。截止目前为止,从HashiCorp 官网上的声明来看,开源项目其实还是“安全”的,被禁用的只是Vault企业版(并且原因是Vault产品目前使用的加密算法在中国不符合法规,另一方面是美国出口管制法在涉及加密相关软件上也有相应规定。因此这两项原因使得HashiCorp不得不在声明中说明风险)而非其他所有开源产品(Terraform、Consul等)。因此,大家可以暂时放下心来,放心使用!

d、spring consul

Spring Cloud Consul

2、能干嘛

Consul 具有如下特性:

a、服务发现

提供HTTP和DNS两种发现方式。

b、健康监测

支持多种方式,HTTP、TCP、Docker、Shell脚本定制化监控

c、KV存储

Key、Value的存储方式

d、多数据中心

Consul支持多数据中心

e、可视化Web界面

3、去哪下

Install | Consul | HashiCorp Developer

4、怎么用

Spring Cloud Consul

两大作用

四、安装并运行consul 

1、windows安装

a、官网下载

Install | Consul | HashiCorp Developer

b、下载完成后只有一个consul.exe文件,对应全路径下查看版本号信息

c、使用开发模式启动

因为现在处于探索实践阶段,为了避免各种加密安全问题等,需要使用 -dev 参数,以开发模式启动

1)、开发模式:【consul.exe agent -dev】,开发模式不会持久化数据,重启之后保存的配置信息就会丢失。

2)、生产模式:【consul.exe agent -server -bootstrap-expect 1 -data-dir d:/consul/data 】

在D盘创建consul/data文件夹,用于持久化Consul

consul agent -dev

通过以下地址可以访问Consul的首页:http://localhost:8500

结果页面

2、linux安装

Consul是HashiCorp开源的一个中间件,里面包含服务注册与发现、分布式一致性协议、健康检查、key/value存储、多数据中心,并且不需要依赖其他工具。服务部署简单,只有一个可运行的二进制的包,每个节点都需要运行agent,它有server和client两种运行模式,官方建议每个数据中心需要3或5个server节点以保证数据安全,同时保证leader的选举能正确的进行。

a、下载安装包

wget https://releases.hashicorp.com/consul/1.17.0/consul_1.17.0_linux_amd64.zip

b、解压并将其移动到/usr/local/consul/bin目录

运行(假设当前在/usr/local/consul目录):

unzip consul_1.17.0_linux_amd64.zip
mv consul bin/
consul --version

c、建立consul的数据存放目录 

mkdir data

d、 建立consul的日志存放目录 

mkdir logs

d、启动consul

nohup /usr/local/consul/bin/consul agent -server -data-dir=/usr/local/consul/data -bootstrap -ui -advertise=192.168.1.22 -client=192.168.1.22 > /usr/local/consul/logs/consul.log 2>&1 &

tail -f /usr/local/consul/logs/consul.log

e、访问ui

浏览器输入:http://192.168.1.22:8500/ui/dc1/services

3、 集群搭建(linux)

a、集群的时候因为参数较多,建议用一个json文件存放配置文件

执行

cd /usr/local/console/config
touch consul_config.json

consul_config.json的内容如下(这里只写出一台,其它的机器也就是改三个ip,改下node_name) 

{
  "datacenter": "dc_ayo",
  "data_dir": "/usr/local/consul/data",
  "log_level": "INFO",
  "server": true,
  "node_name": "node22",
  "ui": true,
  "bind_addr": "192.168.1.22",
  "client_addr": "192.168.1.22",
  "advertise_addr": "192.168.1.22",
  "bootstrap_expect": 3,
  "ports":{
    "http": 8500,
    "dns": 8600,
    "server": 8300,
    "serf_lan": 8301,
    "serf_wan": 8302
    }
}

参数解释:

-bind:为该节点绑定一个地址

-enable-script-checks=true:设置检查服务为可用

-join:加入到已有的集群中

-server 表示当前使用的server模式

-node:指定当前节点在集群中的名称

-config-file - 要加载的配置文件

-config-dir:指定配置文件,定义服务的,默认所有以.json结尾的文件都会读

-datacenter: 数据中心没名称,不设置的话默认为dc

-client: 客户端模式

-ui: 使用consul自带的ui界面

-data-dir consul存储数据的目录

-bootstrap:用来控制一个server是否在bootstrap模式,在一个datacenter中只能有一个server处于bootstrap模式,当一个server处于bootstrap模式时,可以自己选举为raft leader

ui: 相当于-ui 命令行标志。

acl_token:agent会使用这个token和consul server进行请求

acl_ttl:控制TTL的cache,默认是30s

addresses:一个嵌套对象,可以设置以下key:dns、http、rpc

advertise_addr:等同于-advertise

bootstrap:等同于-bootstrap

bootstrap_expect:等同于-bootstrap-expect

bind_addr:等同于-bind

ca_file:提供CA文件路径,用来检查客户端或者服务端的链接

cert_file:必须和key_file一起

check_update_interval:

client_addr:等同于-client

datacenter:等同于-dc

data_dir:等同于-data-dir

disable_anonymous_signature:在进行更新检查时禁止匿名签名

enable_debug:开启debug模式

enable_syslog:等同于-syslog

encrypt:等同于-encrypt

key_file:提供私钥的路径

leave_on_terminate:默认是false,如果为true,当agent收到一个TERM信号的时候,它会发送leave信息到集群中的其他

log_level:等同于-log-level node_name:等同于-node

ports:这是一个嵌套对象,可以设置以下key:dns(dns地址:8600)、http(http api地址:8500)、rpc(rpc:8400)、serf_lan(lan port:8301)、serf_wan(wan port:8302)、server(server rpc:8300)

protocol:等同于-protocol

rejoin_after_leave:等同于-rejoin

retry_join:等同于-retry-join

retry_interval:等同于-retry-interval

server:等同于-server

syslog_facility:当enable_syslog被提供后,该参数控制哪个级别的信息被发送,默认Local0

ui_dir:等同于-ui-dir

b、启动集群

在22上执行执行

nohup /usr/local/consul/bin/consul agent -config-file=/usr/local/consul/config/consul_config.json > /usr/local/consul/logs/consul.log 2>&1 &

在23和24上分别执行 

nohup /usr/local/consul/bin/consul agent -config-file=/usr/local/consul/config/consul_config.json  -retry-join=192.168.1.22:8301 > /usr/local/consul/logs/consul.log 2>&1 &

注意:

如果在同一台电脑上搭建集群,需修改配置文件中的ports节点,保持端口不冲突

"ports":{
    "http": 8500,
    "dns": 8600,
    "grpc_tls": 8513,
    "server": 8300,
    "serf_lan": 8301,
    "serf_wan": 8302
    }

c、查看集群状态

/usr/local/consul/bin/consul members -http-addr=192.168.1.22:8500
/usr/local/consul/bin/consul info -http-addr=192.168.1.22:8500

4、docker安装

a、下载 Consul 的 Docker 镜像 

docker pull hashicorp/consul:1.17.0

b、创建 Consul 的容器

docker run --name consul -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600/udp -v /usr/consul/data:/consul/data hashicorp/consul:1.17.0 consul agent -dev -client=0.0.0.0

 c、查看consul容器是否运行成功

五、服务注册与发现 

1、服务提供者8001

a、支付服务provider8001注册进consul

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

    <parent>
        <groupId>com.lzx.cloud</groupId>
        <artifactId>cloud2024</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>cloud-provider-payment8001</artifactId>
    <description>微服务提供者支付Module模块</description>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--SpringBoot通用依赖模块-->
        <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>

        <!--SpringBoot集成druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>

        <!-- Swagger3 调用方式 http://你的主机IP地址:5555/swagger-ui/index.html -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        </dependency>

        <!--mybatis和springboot整合-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <!--SpringCloud consul discovery -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!--Mysql数据库驱动8 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--persistence-->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
        </dependency>

        <!--通用Mapper4-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
        </dependency>

        <!--hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>

        <!-- fastjson2 -->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>

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

        <!-- 引入自己定义的api通用包 -->
        <dependency>
            <groupId>com.lzx.cloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring.boot.version}</version>
            </plugin>
        </plugins>
    </build>
</project>

配置来源

Quick Start :: Spring Cloud Consul

c、YML

server:
  port: 8001

# ==========applicationName + druid-mysql8 driver===================
spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://112.74.84.186:3306/db2024?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
    username: root
    password: lzx1922026241@
  ####Spring Cloud Consul for Service Discovery
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}

# ========================mybatis===================
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.lzx.cloud.entities
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

d、主启动

package com.lzx.cloud;

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

/**
 * @author admin
 */
@EnableDiscoveryClient
@SpringBootApplication
@MapperScan("com.lzx.cloud.mapper")
public class Main8001 {

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

}

@EnableDiscoveryClient

开启服务发现

e、启动8001并查看consul控制台

2、服务消费者80

a、修改微服务cloud-consumer-order80

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

    <parent>
        <groupId>com.lzx.cloud</groupId>
        <artifactId>cloud2024</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>cloud-consumer-order80</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--web + actuator-->
        <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>

        <!--SpringCloud consul discovery -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--hutool-all-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>

        <!--fastjson2-->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
        </dependency>

        <!-- swagger3 调用方式 http://你的主机IP地址:5555/swagger-ui/index.html -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        </dependency>

        <!-- 引入自己定义的api通用包 -->
        <dependency>
            <groupId>com.lzx.cloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring.boot.version}</version>
            </plugin>
        </plugins>
    </build>

</project>

c、YML

server:
  port: 80

spring:
  application:
    name: cloud-consumer-order
  ####Spring Cloud Consul for Service Discovery
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        prefer-ip-address: true #优先使用服务ip进行注册
        service-name: ${spring.application.name}

d、主启动类

package com.lzx.cloud;

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

/**
 * @author admin
 * 该注解用于向使用consul为注册中心时注册服务
 */
@EnableDiscoveryClient
@SpringBootApplication
public class Main80 {

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

}

@EnableDiscoveryClient

开启服务发现

e、Controller

package com.lzx.cloud.controller;

import lombok.RequiredArgsConstructor;
import com.lzx.cloud.entities.PayDTO;
import com.lzx.cloud.resp.ResultData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

/**
 * @author admin
 */
@RestController
@SuppressWarnings("all")
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class OrderController {

    private final RestTemplate restTemplate;
    
    /**
     * 先写死,硬编码
     * public static final String PAYMENT_SRV_URL = "http://localhost:8001";
     * <p> 
     *     
     * 改写成服务注册中心上的微服务名称
     */
    public static final String PAYMENT_SRV_URL = "http://cloud-payment-service";


    /**
     * 一般情况下,通过浏览器的地址栏输入url,发送的只能是get请求
     * 我们底层调用的是post方法,模拟消费者发送get请求,客户端消费者
     * 参数可以不添加@RequestBody
     *
     * @param payDTO 支付流水信息
     * @return 调用结果
     */
    @GetMapping("/consumer/pay/add")
    public ResultData<?> addOrder(PayDTO payDTO) {
        return restTemplate.postForObject(PAYMENT_SRV_URL + "/pay/add", payDTO, ResultData.class);
    }

    /**
     * 根据主键ID获取支付交易信息
     *
     * @param id 支付交易主键ID
     * @return 支付交易信息
     */
    @GetMapping("/consumer/pay/get/{id}")
    public ResultData<?> getPayInfo(@PathVariable("id") Integer id) {
        return restTemplate.getForObject(PAYMENT_SRV_URL + "/pay/get/" + id, ResultData.class, id);
    }

}
 

d、启动80并查看consul控制台

e、访问测试地址

http://localhost/consumer/pay/get/10

结果如何

一个bug

java.net.UnknownHostException: cloud-payment-service

配置修改RestTemplateConfig

package com.lzx.cloud.config;

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

/**
 * @author admin
 */
@Configuration
public class RestTemplateConfig {

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

}

3、三个注册中心异同点

a、CPA

C:Consistency(强一致性)

A:Availability(可用性)

P:Partition tolerance(分区容错性)

b、经典CAP图

最多只能同时较好的满足两个。

CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:

CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。

CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。

AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。

AP(Eureka)

AP架构

当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性。

当数据出现不一致时,虽然A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺牲了一致性结论:违背了一致性C的要求,只满足可用性和分区容错,即AP

CP(Zookeeper/Consul)

CP架构

当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性,Consul 遵循CAP原理中的CP原则,保证了强一致性和分区容错性,且使用的是Raft算法,比zookeeper使用的Paxos算法更加简单。虽然保证了强一致性,但是可用性就相应下降了,例如服务注册的时间会稍长一些,因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 ;在leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用。结论:违背了可用性A的要求,只满足一致性和分区容错,即CP

六、服务配置与刷新

1、分布式系统面临的 → 配置问题

微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。比如某些配置文件中的内容大部分都是相同的,只有个别的配置项不同。就拿数据库配置来说吧,如果每个微服务使用的技术栈都是相同的,则每个微服务中关于数据库的配置几乎都是相同的,有时候主机迁移了,我希望一次修改,处处生效。

当下我们每一个微服务自己带着一个application.yml,上百个配置文件的管理....../(ㄒoㄒ)/~~

2、官网说明

3、服务配置案例步骤

1)、需求

通用全局配置信息,直接注册进Consul服务器,从Consul获取

既然从Consul获取自然要遵守Consul的配置规则要求

2)、修改cloud-provider-payment8001

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

    <parent>
        <groupId>com.lzx.cloud</groupId>
        <artifactId>cloud2024</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>cloud-provider-payment8001</artifactId>
    <description>微服务提供者支付Module模块</description>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--SpringBoot通用依赖模块-->
        <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>

        <!--SpringBoot集成druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>

        <!-- Swagger3 调用方式 http://你的主机IP地址:5555/swagger-ui/index.html -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        </dependency>

        <!--mybatis和springboot整合-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <!--SpringCloud consul discovery -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!--SpringCloud consul config-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-config</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

        <!--Mysql数据库驱动8 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--persistence-->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
        </dependency>

        <!--通用Mapper4-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
        </dependency>

        <!--hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>

        <!-- fastjson2 -->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>

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

        <!-- 引入自己定义的api通用包 -->
        <dependency>
            <groupId>com.lzx.cloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring.boot.version}</version>
            </plugin>
        </plugins>
    </build>
</project>

b、YML

配置规则说明

新增配置文件bootstrap.yml 

是什么

applicaiton.yml是用户级的资源配置项

bootstrap.yml是系统级的,优先级更加高

Spring Cloud会创建一个“Bootstrap Context”,作为Spring应用的`Application Context`的父上下文。初始化的时候,`Bootstrap Context`负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的`Environment`。

`Bootstrap`属性有高优先级,默认情况下,它们不会被本地配置覆盖。 `Bootstrap context`和`Application Context`有着不同的约定,所以新增了一个`bootstrap.yml`文件,保证`Bootstrap Context`和`Application Context`配置的分离。

application.yml文件改为bootstrap.yml,这是很关键的或者两者共存

因为bootstrap.yml是比application.yml先加载的。bootstrap.yml优先级高于application.yml

bootstrap.yml

spring:
  application:
    name: cloud-payment-service
    ####Spring Cloud Consul for Service Discovery
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
      config:
        # default value is ",",we update '-'
        profile-separator: '-'
        format: YAML
# config/cloud-payment-service/data
#       /cloud-payment-service-dev/data
#       /cloud-payment-service-prod/data

application.yml

server:
  port: 8001

# ==========applicationName + druid-mysql8 driver===================
spring:
  profiles:
    # 多环境配置加载内容dev/prod,不写就是默认default配置
    active: dev
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://112.74.84.186:3306/db2024?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
    username: root
    password: lzx1922026241@

# ========================mybatis===================
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.lzx.cloud.entities
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3)、consul服务器key/value配置填写

  1. 参考规则

  2. 创建config文件夹,以/结尾 



    To create a folder, end a key with /
  3. config文件夹下分别创建其它3个文件夹,以/结尾



    cloud-payment-service、cloud-payment-service-dev、cloud-payment-service-prod
  4. 上述3个文件夹下分别创建data内容,data不再是文件

4)、controller

package com.lzx.cloud.controller;

import com.lzx.cloud.entities.Pay;
import com.lzx.cloud.entities.PayDTO;
import com.lzx.cloud.resp.ResultData;
import com.lzx.cloud.resp.ReturnCodeEnum;
import com.lzx.cloud.service.PayService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author admin
 */
@Slf4j
@RestController
@Tag(name = "支付微服务模块", description = "支付CRUD")
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class PayController {

    private final PayService payService;

    @Value("${server.port}")
    private String port;

    /**
     * 新增支付交易信息
     *
     * @param pay 支付交易信息
     * @return 受影响行数
     */
    @PostMapping(value = "/pay/add")
    @Operation(summary = "新增", description = "新增支付流水方法,json串做参数")
    public ResultData<String> addPay(@RequestBody Pay pay) {
        log.info(pay.toString());
        int i = payService.add(pay);
        return ResultData.success("成功插入记录,返回值:" + i);
    }

    /**
     * 删除支付交易信息
     *
     * @param id 支付交易主键ID
     * @return 受影响行数
     */
    @DeleteMapping(value = "/pay/del/{id}")
    @Operation(summary = "删除", description = "删除支付流水方法")
    public ResultData<Integer> deletePay(@PathVariable("id") Integer id) {
        return ResultData.success(payService.delete(id));
    }

    /**
     * 更新支付交易
     *
     * @param payDTO 支付交易信息
     * @return 受影响行数
     */
    @PutMapping(value = "/pay/update")
    @Operation(summary = "修改", description = "修改支付流水方法")
    public ResultData<String> updatePay(@RequestBody PayDTO payDTO) {
        Pay pay = new Pay();
        BeanUtils.copyProperties(payDTO, pay);

        int i = payService.update(pay);
        return ResultData.success("成功修改记录,返回值:" + i);
    }

    /**
     * 根据主键ID获取支付交易信息
     *
     * @param id 支付交易主键ID
     * @return 支付交易信息
     */
    @SuppressWarnings("all")
    @GetMapping(value = "/pay/get/{id}")
    @Operation(summary = "按照ID查流水", description = "查询支付流水方法")
    public ResultData<Pay> getById(@PathVariable("id") Integer id) {
        if (id == -4) {
            throw new RuntimeException("id不能为负数");
        }

        return ResultData.success(payService.getById(id));
    }

    /**
     * 获取所有支付交易信息列表
     *
     * @return 所有支付交易信息列表
     */
    @GetMapping(value = "/pay/get/all")
    @Operation(summary = "查询所有支付流水", description = "查询所有支付流水方法")
    public ResultData<List<Pay>> getAll() {
        return ResultData.success(payService.getAll());
    }

    /**
     * 测试异常
     *
     * @return 测试结果
     */
    @SuppressWarnings("all")
    @GetMapping(value = "/pay/error")
    public ResultData<Integer> getPayError() {
        Integer i = 200;

        try {
            log.info("--------come here");
            int data = 10 / 0;
            log.info("计算结果:{}", data);
        } catch (Exception e) {
            log.error("异常信息", e);
            return ResultData.fail(ReturnCodeEnum.RC500.getCode(), e.getMessage());
        }

        return ResultData.success(i);
    }

    /**
     * 获取配置文件中信息
     * @param companyInfo 公司信息
     * @return 配置文件中信息
     */
    @GetMapping(value = "/pay/get/info")
    public String getInfoByConsul(@Value("${company.info}") String companyInfo) {
        return "companyInfo: " + companyInfo + "\t" + "port: " + port;
    }

}

5)、测试

spring:
   profiles:
     active: dev  多环境配置加载内容dev
spring:
   profiles:
     active: prod  多环境配置加载内容prod
spring:
   profiles:
     active:   多环境配置加载内容默认

通过修改application.yml里面的激活配置部分,进行内容的验证 

http://localhost:8001/pay/get/info

4、动态刷新案例步骤

1)、问题

接上一步,如果在consul的dev配置分支修改了内容,马上访问,结果无效。

http://localhost:8001/pay/get/info

会发现还是原来的内容,/(ㄒoㄒ)/~~ ,没有做到及时响应和动态刷新

2)、步骤

a、@RefreshScope主启动类添加

package com.lzx.cloud;

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

/**
 * @author admin
 *
 * 动态刷新
 */
@RefreshScope
@EnableDiscoveryClient
@SpringBootApplication
@MapperScan("com.lzx.cloud.mapper")
public class Main8001 {

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

}

b、bootstrap.yml修改下(只为演示实际别改)

spring.cloud.consul.config.watch.wait-time

官网说明

修改步骤

spring:
  application:
    name: cloud-payment-service
    ####Spring Cloud Consul for Service Discovery
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
      config:
        # default value is ",",we update '-'
        profile-separator: '-'
        format: YAML
        watch:
          wait-time: 1
# config/cloud-payment-service/data
#       /cloud-payment-service-dev/data
#       /cloud-payment-service-prod/data

controller

 @Value("${server.port}")
 private String port;

 /**
  * 获取配置文件中信息
  *
  * @param companyInfo 公司信息
  * @return 配置文件中信息
  */
 @GetMapping(value = "/pay/get/info")
 private String getInfoByConsul(@Value("${company.info}") String companyInfo) {
     return "companyInfo: " + companyInfo + "\t" + "port: " + port;
 }

5、思考

截止到这,服务配置和动态刷新全部通过,假设我重启Consul,之前的配置还在吗?

try try

引出问题

Consul配置持久化...... (下一章)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1588517.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【科技】2024最新微信机器人一键部署教程

外话 话说上次写文章好像又过了几个月了…… 其实还是因为马上小升初的各种密考&#xff0c;其它地方不知道&#xff0c;反正广东这块名校基本上都得密考考进去 笔者连考几次都惨不忍睹…… 不过5月份会有一个信息技术特长生招生&#xff0c;看看能不能吧~ 正文 先说&#xff…

新质生产力与智能制造:推动制造业转型升级的双引擎

引言 随着科技的不断进步和全球制造业的快速发展&#xff0c;新质生产力与智能制造成为推动制造业转型升级的关键驱动力。新质生产力强调的是以科技创新和制度创新为核心&#xff0c;通过提高生产效率和经济效益来推动经济发展。而智能制造则是利用现代信息技术&#xff0c;实现…

Python | Leetcode Python题解之第24题两两交换链表中的节点

题目&#xff1a; 题解&#xff1a; class Solution:def swapPairs(self, head: ListNode) -> ListNode:dummyHead ListNode(0)dummyHead.next headtemp dummyHeadwhile temp.next and temp.next.next:node1 temp.nextnode2 temp.next.nexttemp.next node2node1.next…

【稳定检索|投稿优惠】2024年生物学与智能计算国际会议 (ICBIC 2024)

2024年生物学与智能计算国际会议 (ICBIC 2024) 2024 International Conference on Biology and Intelligent Computing 【会议简介】 2024年生物学与智能计算国际会议即将在上海召开。本次会议旨在汇聚生物学与智能计算领域的专家学者&#xff0c;共同探讨两者交叉融合的前沿…

一文带你搞懂软件开发/怎么开发?哪些常见陷阱?如何避坑?

引言 在当今数字化时代&#xff0c;软件开发已成为推动科技进步和商业发展的重要引擎。然而&#xff0c;软件开发并非一帆风顺&#xff0c;其中蕴藏着许多陷阱和挑战。如何避免这些陷阱&#xff0c;提高软件开发的效率和质量&#xff0c;成为开发者们面临的重要问题 本文将深入…

关于Ansible的模块 ⑦

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 在继《关于Ansible的模块 ①》、《关于Ansible的模块 ②》、《关于Ansible的模块 ③》与《关于Ansible的模块 ④》、《关于ansib…

NVMe 基础

NVMe&#xff08;Non-Volatile Memory Express&#xff09;是一种高速、低延迟的I/O接口协议&#xff0c;专为闪存存储设备设计&#xff0c;包括固态硬盘&#xff08;SSD&#xff09;和其他非易失性存储设备。NVMe协议是为取代早期的AHCI&#xff08;Advanced Host Controller …

bufbomb 报错 ./stdio-common/vfprintf-internal.c: No such file or directory.

注意&#xff1a;此方法针对HUST特供 bufbomb 的 level2&#xff0c;其它情况不保证有效。 有同学可能发现&#xff0c;当跳入bang函数时&#xff0c;无论是gdb还是直接执行&#xff0c;都会出现以下报错 其实若是再仔细排查一下&#xff0c;会发现实际上只有跳到 <bang0&…

呼出气一氧化碳:评估呼吸健康与戒烟状态的关键指标

一氧化碳&#xff08;CO&#xff09;是一种无色、无味、有毒的气体&#xff0c;通常由不完全燃烧产生。在生物学领域&#xff0c;CO作为一种重要的信使分子&#xff0c;在多种生物过程中发挥着作用。特别值得一提的是&#xff0c;它作为血红素加氧酶&#xff08;HO&#xff09;…

基于二级片内硬件堆栈的后向CFI 验证方法研究,第4章 硬件设计与实现(二)

4.3 批处理验证实现 批处理验证是为了进一步降低硬件资源消耗和降低系统功耗提出的二级片内硬件堆栈的另一种实现方法&#xff0c;批处理验证的硬件结构图如图4.7所示&#xff0c;也由指令检测单元、返回地址缓冲区、MAC计算单元、MAC存储单元组成。 图4.7 批处理验证硬件框图…

基于SpringBoot+Vue的咖啡商城(带文档)

项目介绍: 基于SpringBootVue的咖啡商城&#xff08;带文档&#xff09; 网上咖啡商城系统&#xff0c;咖啡商城系统 前后端分离&#xff0c;Java开发&#xff0c;Vue框架&#xff0c;Redis分布式缓存&#xff0c;MyBatis 运行环境&#xff1a;JDK1.8MySQLMavenRedisNode.js 项…

【Python-MP4文体提取】

Python-MP4文体提取 ■ pip 和 setuptools工具■ OpenCV和Tesseract■ Tesseract OCR V5.0安装教程&#xff08;Windows&#xff09;■ 1. 运行程序出现如下问题&#xff1a;我们需要安装Tesseract OCR■ 2. 下载Tesseract-OCR■ 3. 安装Tesseract-OCR■ 4. 添加到环境变量的系…

Linux磁盘扩容并设置挂载点

背景 使用pve创建了一个虚拟机&#xff0c;各种环境配置都安装好了之后发现分配的磁盘空间太小了&#xff0c;默认的就30多个G&#xff0c;这还没咋玩呢就满了&#xff0c;像扩容却找遍了这个pve都没找到扩容按钮&#xff0c;并且我这个磁盘不是lvm结构的&#xff0c;所以好像…

01攻防世界web-Training-WWW-Robots

写在前面&#xff1a; 一入网安深似海&#xff0c;学习需要毅力和强大的坚持。 1.Training-WWW-Robots 题目 解题过程 访问网址后面加上/robots.txt 进入fl0g.php文件&#xff0c;找到flag 相关知识点1.Robots&#xff1a; 理解一下robotS文件中的user-agent: 以及Disallow…

学习Rust的第三天:猜谜游戏

Welcome to the third day of learning rust, I am referring to the book “The Rust Programming Language” by Steve Klabnik. Today we build a guessing game in rust. 欢迎来到学习Rust的第三天&#xff0c;基于Steve Klabnik的《The Rust Programming Language》一书。…

数据生成 | Matlab实现基于SNN浅层神经网络的数据生成

数据生成 | Matlab实现基于SNN浅层神经网络的数据生成 目录 数据生成 | Matlab实现基于SNN浅层神经网络的数据生成生成效果基本描述模型描述程序设计参考资料 生成效果 基本描述 1.Matlab实现基于SNN浅层神经网络的数据生成&#xff0c;运行环境Matlab2021b及以上&#xff1b; …

微软卡内基梅隆大学:无外部干预,GPT4等大语言模型难以自主探索

目录 引言&#xff1a;LLMs在强化学习中的探索能力探究 研究背景&#xff1a;LLMs的在情境中学习能力及其重要性 实验设计&#xff1a;多臂老虎机环境中的LLMs探索行为 实验结果概览&#xff1a;LLMs在探索任务中的普遍失败 成功案例分析&#xff1a;Gpt-4在特定配置下的探…

TS在interface和type的区别

在TypeScript中&#xff0c;interface和type都是用来定义类型的方式 (1)语法&#xff1a; interface 关键字用于定义接口,一般定义对象类型,可以描述对象的形状&#xff0c;即一个对象应该具有哪些属性和方法。interface可以声明对象应该具有的结构和属性。 type 关键字用于…

Java 中文官方教程 2022 版(三十二)

原文&#xff1a;docs.oracle.com/javase/tutorial/reallybigindex.html 一个基本的打印程序 原文&#xff1a;docs.oracle.com/javase/tutorial/2d/printing/printable.html 本节解释了如何创建一个基本的打印程序&#xff0c;显示打印对话框&#xff0c;并将文本“Hello Worl…

导入芯片原厂SDK Mirror源码到gerrit

下载镜像代码 repo init --mirror --repo-url ssh://xx/repo.git -u ssh://xx/manifests.git -m manifest.xml repo sync 创建AOSP project 对All Project权限修改 创建repo 在刚才下载的codebase根目录执行如下命令&#xff1a; repo forall -c echo $REPO_PROJECT; ssh -p 29…