当前位置: 首页 > news >正文

配置中心--Spring Cloud Config

目录

概述

环境说明

步骤

创建远端git仓库

准备配置文件

配置中心--服务端

配置中心--客户端

配置中心的高可用

配置中心--服务端

配置中心--客户端

消息总线刷新配置

配置中心--服务端

配置中心--客户端


概述

因为微服务架构有很多个服务,手动一个一个管理各个服务配置很麻烦,不同的环境(开发、测试、生产)往往需要不同的配置文件,运行期间也需要动态调整配置,修改配置后微服务需要自动更新配置,所以需要一个统一管理应用配置的组件。

配置中心是一种统一管理各种应用配置的基础服务组件。本文讲解的配置中心组件为Spring Cloud Config。

本文的操作可在 微服务调用链路追踪 的基础上进行 或者 在 Spring Cloud Stream实践 的基础上进行。

环境说明

jdk1.8

maven3.6.3

mysql8

spring cloud2021.0.8

spring boot2.7.12

idea2022

rabbitmq3.12.4

步骤

创建远端git仓库

创建远端git仓库,管理配置文件,使用gitee,创建仓库名称为config-repo(创建时点击创建README文件,方便直接用浏览器上传文件)

可使用远端仓库管理微服务公共的配置,而非公共的配置可放在各自微服务的application.yml中。

公共的配置,例如:数据库配置、Eureka配置等

非公共的配置,例如:端口号、应用名称等

准备配置文件

配置中心的配置文件命名规则为:

{application}-{profile}.yml
{application}-{profile}.properties

application为应用名称 profile指的开发环境(用于区分开发环境、测试环境、生产环境等)

复制product-serviceapplication.yml,重命名为application-pro.yml,抽取公共配置,例如:数据库配置、zipkin、sleuth、rabbitmq、eureka等,同时添加一个name属性(用于区别不同的环境配置),公共的配置放在远端git仓库。

application-pro.yml

spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/shop1?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8username: rootpassword: 123jpa:database: MySQLshow-sql: trueopen-in-view: truegenerate-ddl: true #自动创建表zipkin:sender:type: rabbit #数据的传输方式,以rabbit的方式向server端发送数据sleuth:sampler:probability: 1 #采样比,日志的采样比例,默认0.1,测试环境设置为100%收集日志rabbitmq:host: localhostport: 5672username: guestpassword: guestlistener: #这里配置重试策略direct:retry:enabled: truesimple:retry:enabled: trueeureka:client:service-url:defaultZone: http://localhost:9000/eureka/instance:prefer-ip-address: trueinstance-id: ${spring.cloud.client.ip-address}:${server.port}logging:level:root: infoorg.springframework.web.servlet.DispatcherServlet: DEBUGorg.springframework.cloud.sleuth: DEBUGname: product-pro

复制application-pro.yml得到application-dev.yml

application-dev.yml

配置内容如下,区别在于name的值为product-dev

spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/shop1?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8username: rootpassword: 123jpa:database: MySQLshow-sql: trueopen-in-view: truegenerate-ddl: true #自动创建表zipkin:sender:type: rabbit #数据的传输方式,以rabbit的方式向server端发送数据sleuth:sampler:probability: 1 #采样比,日志的采样比例,默认0.1,测试环境设置为100%收集日志rabbitmq:host: localhostport: 5672username: guestpassword: guestlistener: #这里配置重试策略direct:retry:enabled: truesimple:retry:enabled: trueeureka:client:service-url:defaultZone: http://localhost:9000/eureka/instance:prefer-ip-address: trueinstance-id: ${spring.cloud.client.ip-address}:${server.port}logging:level:root: infoorg.springframework.web.servlet.DispatcherServlet: DEBUGorg.springframework.cloud.sleuth: DEBUGname: product-dev

通过浏览器界面,手动上传application-pro.ymlapplication-dev.yml到git仓库

点击上传文件区域,选中需要上传的文件:application-pro.ymlapplication-dev.yml

 填写提交信息,点击提交

上传成功后,如下图

配置中心--服务端

创建子工程config_server

引入依赖

	<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-config-server</artifactId></dependency></dependencies>

启动类

package org.example.config;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;@SpringBootApplication
@EnableConfigServer //开启配置中心服务端功能
public class ConfigServerApplication {public static void main(String[] args) {SpringApplication.run(ConfigServerApplication.class, args);}
}

配置application.yml

server:port: 11111
spring:application:name: config-servercloud:config:server:git:uri: https://gitee.com/xxx/config-repo.git

uri的值是刚才创建的远端git仓库的地址,注意修改为自己的仓库地址。

启动config_server服务

浏览器访问

http://localhost:11111/application-dev.yml

访问不到数据

原因是gitee仓库是私有的,需要把仓库公开或者配置gitee的登录信息。

解决方法1:将git仓库开源

解决方法2:修改配置,加上gitee的用户名和密码

cloud:config:server:git:uri: https://gitee.com/xxx/config-repo.gitusername: xxxpassword: xxx

两种方法选择其中一个。

解决后,再次访问

http://localhost:11111/application-dev.yml

成功看到数据如下 

配置中心--客户端

配置中心客户端就是各个微服务

这里创建一个微服务:config_client_1

config_client_1项目结构如下

添加依赖

	<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!--引入EurekaClient--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--消息总线bus--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-bus</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-stream-binder-rabbit</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency></dependencies>

刷新依赖

非公共的配置application.yml

server:port: 9101
spring:application:name: config-client1

bootstrap.yml

spring:cloud:config:name: application #应用名称对应git配置文件的前半部分,例如:application-dev.yml,这里就写applicationprofile: dev #开发环境label: master #git中的分支uri: http://localhost:11111 #config_server的请求地址

ConfigClientApplication.java

package org.example.config.client;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;@SpringBootApplication
@EntityScan("org.example.config.client.entity.Product")
public class ConfigClientApplication {public static void main(String[] args) {SpringApplication.run(ConfigClientApplication.class, args);}
}

Product.java

package org.example.config.client.entity;import lombok.Data;import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.math.BigDecimal;/*** 商品实体类*/
@Data
@Entity
@Table(name="tb_product")
public class Product {@Idprivate Long id;private String productName;private Integer status;private BigDecimal price;private String productDesc;private String caption;private Integer inventory;
}

ProductController.java

package org.example.config.client.controller;import org.example.config.client.entity.Product;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/config-client/product")
public class ProductController {@Value("${name}")private String name;@RequestMapping("/get")public Product getProduct(){Product product = new Product();product.setProductName(name);return product;}
}

启动eureka、config_server、config_client_1服务

注意:因为远端git仓库的配置文件有eureka配置,所以拉取到配置后,需要启动eureka服务

浏览器访问

http://localhost:9101/config-client/product/get

响应
{"id":null,"productName":"product-dev","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

pruductName为product-dev,与git的application-dev.yml的name属性一致

config_client_1bootstrap.yml的profile改为pro

重启config_client_1服务

再次访问

http://localhost:9101/config-client/product/get
响应
{"id":null,"productName":"product-pro","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

 pruductName为product-pro,与git的application-pro.yml的name属性一致

修改git的配置

查看application-pro.yml文件,点击编辑

product-pro改为product-pro1 

点击提交

浏览器访问

http://localhost:9101/config-client/product/get

发现数据未更新,还是product-pro

解决方式:

方式一:重启config_client_1服务

发现重启可以拿到最新数据,但是,在生产环境中,重启服务有时候不太方便。

方式二:手动刷新

修改config_client_1服务

pom.xml,引入actuator依赖(之前已引入,跳过)

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

在需要的更新数据的类上添加@RefreshScope,开启动态刷新

修改bootstrap.yml

#开启动态刷新的端点
management:endpoints:web:exposure:include: refresh

重启config_client_1服务

访问

http://localhost:9101/config-client/product/get

productName是product-pro1

将git配置文件的name值修改为product-pro2

发起post请求刷新数据

curl -X POST "http://localhost:9101/actuator/refresh"

可使用postman或cmd命令行发起请求,这里使用cmd命令行发起post请求

再次访问

http://localhost:9101/config-client/product/get

响应最新的数据:product-pro2

手动刷新操作总结:

  1. 引入actuator依赖

  2. 需要的更新数据的类上添加@RefreshScope,开启动态刷新

  3. bootstrap.yml开启动态刷新的端点

  4. 修改git配置

  5. 发起post请求手动刷新数据

手动刷新能解决在不重启应用情况下,能做到动态刷新配置。但当服务很多时或需要更新的数据接口很多的情况下,就需要发起很多次Post请求,手动刷新显得很麻烦。可以使用消息总线技术解决该问题。

配置中心的高可用

一台配置中心服务容易出现单点故障问题,将配置中心集群化构成高可用的配置中心可以解决配置中心单点故障问题。

将多个配置中心注册到eureka,提供统一的服务名称,客户端通过服务名称调用配置中心。

配置中心--服务端

修改config_server服务

添加依赖

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

刷新依赖

application.yml添加eureka相关配置

eureka:client:service-url:defaultZone: http://localhost:9000/eurekainstance:prefer-ip-address: trueinstance-id: ${spring.cloud.client.ip-address}:${server.port}

修改config_server配置文件,添加default-label: master配置

cloud:config:server:git:uri: https://gitee.com/xxx/config-repo.gitdefault-label: master

注意修改uri为自己git远端仓库地址。 

启动eureka、config_server服务

查看Eureka Web UI,看到了一台配置中心服务

http://localhost:9000/

通过复制配置方式,得到另外一台配置中心

修改端口号,复制运行配置,再启动一台配置中心服务

刷新查看Eureka Web UI,看到CONFIG-SERVER配置中心服务有两个实例。

配置中心--客户端

config_client_1服务

修改bootstrap.yml,添加eureka配置,修改通过服务名称(config-server)拿到配置

spring:cloud:config:name: application #应用名称对应git配置文件的前半部分,例如:application-dev.yml,这里就写applicationprofile: pro #开发环境label: master #git中的分支#uri: http://localhost:11111 #config_server的请求地址discovery:enabled: true #开启服务发现service-id: config-server #配置服务的服务名称
#开启动态刷新的端点
management:endpoints:web:exposure:include: refresheureka:client:service-url:defaultZone: http://localhost:9000/eurekainstance:prefer-ip-address: trueinstance-id: ${spring.cloud.client.ip-address}:${server.port}

重启config_client_1服务

访问

http://localhost:9101/config-client/product/get
响应
{"id":null,"productName":"product-pro2","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

能正常拿到数据,说明配置正常

高可用测试

测试关闭其中一个服务,是否还可以正常提供服务

再次访问

访问依然正常,说明实现了配置中心的高可用。

总结:

  1. 服务端,添加服务注册依赖及配置,注册到eureka中,开启两个服务。

  2. 客户端,添加eureka配置,使用服务名称获取配置

  3. 测试:断开一个服务,不影响访问

消息总线刷新配置

此前,通过发起Post请求手动刷新配置,服务接口很多时,就需要发起很多次Post请求,显得很麻烦。

通过消息总线刷新配置流程如下:

配置中心--服务端

config_server服务

添加依赖

		<!--消息总线依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-stream-rabbit</artifactId></dependency>

刷新依赖

配置application.yml

配置Spring Cloud Bus的RabbitMQ连接信息,启用Spring Cloud Bus(spring.cloud.bus.enabled=true默认已启动),同时暴露动态刷新的端点。

server:port: 11112
spring:application:name: config-servercloud:config:server:git:uri: https://gitee.com/liang_123456/config-repo.gitdefault-label: master
#    bus:
#      enabled: truerabbitmq:host: 127.0.0.1port: 5672username: guestpassword: guest#开启动态刷新的端点
management:endpoints:bus-refresh:enabled: trueweb:exposure:include: bus-refresheureka:client:service-url:defaultZone: http://localhost:9000/eurekainstance:prefer-ip-address: trueinstance-id: ${spring.cloud.client.ip-address}:${server.port}

注意:开启动态刷新端点的management要顶格写

配置中心--客户端

spring-client_1服务

和config_server一样,添加依赖,如果已经存在就不用再添加

		<!--消息总线依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-stream-rabbit</artifactId></dependency>

刷新依赖

配置rabbitmq信息,因为是配置中心,所以在git远端仓库的配置文件配置即可,查看远端git配置文件,已经配置,如下

重启eureka、config_server和spring-client_1服务

访问

http://localhost:9101/config-client/product/get
响应
{"id":null,"productName":"product-pro2","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

修改git远端配置

访问

http://localhost:9101/config-client/product/get
响应
{"id":null,"productName":"product-pro2","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

响应product-pro2,说明还不是最新配置

发起Post请求, 刷新服务端配置

curl -X POST "http://localhost:11112/actuator/busrefresh"

注意:新版本发起post请求路径要改为busrefresh,而不是bus-refresh

访问

http://localhost:9101/config-client/product/get

响应
{"id":null,"productName":"product-pro3","status":null,"price":null,"productDesc":null,"caption":null,"inventory":null}

响应的数据也是product-pro3,说明使用消息总线方式刷新配置成功。 


 

完成!enjoy it!

相关文章:

配置中心--Spring Cloud Config

目录 概述 环境说明 步骤 创建远端git仓库 准备配置文件 配置中心--服务端 配置中心--客户端 配置中心的高可用 配置中心--服务端 配置中心--客户端 消息总线刷新配置 配置中心--服务端 配置中心--客户端 概述 因为微服务架构有很多个服务&#xff0c;手动一个一…...

笔记-模拟角频率和数字角频率的关系理解

先建议阅读前人此文&#xff08;点击这里&#xff09;&#xff0c;有助于理解。 模拟频率&#xff1a;f 模拟角频率&#xff1a;Ω 数字角频率&#xff1a;ω 其中&#xff1a;在模拟信号中Ω 2πf 正弦波表示&#xff1a;sin(2πft) sin(Ωt) 数字信号就是离散的&#xff…...

Zookeeper+Kafka集群

注&#xff1a;本章使用的Kafka为2.7.0版本 Zookeeper概述 1.Zookeeper定义 Zookeeper是一个开源的分布式的&#xff0c;为分布式框架提供协调服务的Apache项目。 2.Zookeeper工作机制 Zookeeper从设计模式角度来理解&#xff1a;是一个基于观察者模式设计的分布式服务管理…...

Sunshine+Moonlight+Android手机串流配置(局域网、无手柄)

目录 前言Sunshine&#xff08;服务端&#xff09;ApplicationConfigurationGeneralAdvance Moonlight&#xff08;客户端&#xff09;配对打开虚拟手柄串流按键调整退出串流 原神&#xff0c;启动&#xff01; 前言 写这篇文章单纯是因为搜来搜去没有很符合我需求的教程&#…...

从顺序表中删除具有最小值的元素(假设唯一) 并由函数返回被删元素的值。空出的位 置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。

题目描述&#xff1a;从顺序表中删除具有最小值的元素(假设唯一) 并由函数返回被删元素的值。空出的位置由最后一个元素填补&#xff0c;若顺序表为空&#xff0c;则显示出错信息并退出运行。 bool DeleteMin(SqList &L,int &min){if(L.length 0)return false;min L…...

详解—[C++ 数据结构]—AVL树

目录 一.AVL树的概念 二、AVL树节点的定义 三、AVL树的插入 3.1插入方法 四、AVL树的旋转 1. 新节点插入较高左子树的左侧---左左&#xff1a;右单旋 2. 新节点插入较高右子树的右侧---右右&#xff1a;左单旋 3.新节点插入较高左子树的右侧---左右&#xff1a;先左单旋…...

卷积神经网络(CNN):乳腺癌识别.ipynb

文章目录 一、前言一、设置GPU二、导入数据1. 导入数据2. 检查数据3. 配置数据集4. 数据可视化 三、构建模型四、编译五、训练模型六、评估模型1. Accuracy与Loss图2. 混淆矩阵3. 各项指标评估 一、前言 我的环境&#xff1a; 语言环境&#xff1a;Python3.6.5编译器&#xf…...

有文件实体的后门无文件实体的后门rootkit后门

有文件实体后门和无文件实体后门&RootKit后门 什么是有文件的实体后门&#xff1a; 在传统的webshell当中&#xff0c;后门代码都是可以精确定位到某一个文件上去的&#xff0c;你可以rm删除它&#xff0c;可以鼠标右键操作它&#xff0c;它是有一个文件实体对象存在的。…...

GPT实战系列-大模型训练和预测,如何加速、降低显存

GPT实战系列-大模型训练和预测&#xff0c;如何加速、降低显存 不做特别处理&#xff0c;深度学习默认参数精度为浮点32位精度&#xff08;FP32&#xff09;。大模型参数庞大&#xff0c;10-1000B级别&#xff0c;如果不注意优化&#xff0c;既耗费大量的显卡资源&#xff0c;…...

SQL Sever 基础知识 - 数据排序

SQL Sever 基础知识 - 二 、数据排序 二 、对数据进行排序第1节 ORDER BY 子句简介第2节 ORDER BY 子句示例2.1 按一列升序对结果集进行排序2.2 按一列降序对结果集进行排序2.3 按多列对结果集排序2.4 按多列对结果集不同排序2.5 按不在选择列表中的列对结果集进行排序2.6 按表…...

vscode配置使用 cpplint

标题安装clang-format和cpplint sudo apt-get install clang-format sudo pip3 install cpplint标题以下settings.json文件放置xxx/Code/User目录 settings.json {"sync.forceDownload": false,"workbench.sideBar.location": "right","…...

C++ 系列 第四篇 C++ 数据类型上篇—基本类型

系列文章 C 系列 前篇 为什么学习C 及学习计划-CSDN博客 C 系列 第一篇 开发环境搭建&#xff08;WSL 方向&#xff09;-CSDN博客 C 系列 第二篇 你真的了解C吗&#xff1f;本篇带你走进C的世界-CSDN博客 C 系列 第三篇 C程序的基本结构-CSDN博客 前言 面向对象编程(OOP)的…...

C++ 指针详解

目录 一、指针概述 指针的定义 指针的大小 指针的解引用 野指针 指针未初始化 指针越界访问 指针运算 二级指针 指针与数组 二、字符指针 三、指针数组 四、数组指针 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 指针与数组 一维数组 字符数组…...

.locked、locked1勒索病毒的最新威胁:如何恢复您的数据?

导言&#xff1a; 网络安全问题变得愈加严峻。.locked、locked1勒索病毒是近期备受关注的一种恶意软件&#xff0c;给用户的数据带来了巨大威胁。本文将深入探讨.locked、locked1勒索病毒的特征&#xff0c;探讨如何有效恢复被其加密的数据&#xff0c;并提供一些建议&#xf…...

Apache Sqoop使用

1. Sqoop介绍 Apache Sqoop 是在 Hadoop 生态体系和 RDBMS 体系之间传送数据的一种工具。 Sqoop 工作机制是将导入或导出命令翻译成 mapreduce 程序来实现。在翻译出的 mapreduce 中主要是对 inputformat 和 outputformat 进行定制。 Hadoop 生态系统包括&#xff1a;HDFS、Hi…...

【UGUI】实现UGUI背包系统的六个主要交互功能

在这篇教程中&#xff0c;我们将详细介绍如何在Unity中实现一个背包系统的六个主要功能&#xff1a;添加物品、删除物品、查看物品信息、排序物品、搜索物品和使用物品。让我们开始吧&#xff01; 一、添加物品 首先&#xff0c;我们需要创建一个方法来添加新的物品到背包中。…...

电压驻波比

电压驻波比 关于IF端口的电压驻波比 一个信号变频后&#xff0c;从中频端口输出&#xff0c;它的输出跟输入是互异的。这个电压柱波比反映了它输出的能量有多少可以真正的输送到后端连接的器件或者设备。...

Open3D 最小二乘拟合二维直线(直接求解法)

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。爬虫网站自重。 一、算法原理 平面直线的表达式为: y = k x + b...

面试题目总结(二)

1. IoC 和 AOP 的区别 控制反转(Ioc) 和面向切面编程(AOP) 是两个不同的概念&#xff0c;它们在软件设计中有着不同的应用和目的。 IoC 是一种基于对象组合的编程模式&#xff0c;通过将对象的创建、依赖关系和生命周期等管理权交给外部容器或框架来实现程序间的解耦。IoC 的…...

TrustZone概述

目录 一、概述 1.1 在开始之前 二、什么是TrustZone? 2.1 Armv8-M的TrustZone 2.2 Armv9-A Realm Management Ext...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西&#xff0c;但是如果把三者放在一起&#xff0c;它们之间到底什么关系&#xff1f;又有什么联系呢&#xff1f;我不是很明白&#xff01;&#xff01;&#xff01; 就比如说&#xff1a; 沙箱&#…...

​​企业大模型服务合规指南:深度解析备案与登记制度​​

伴随AI技术的爆炸式发展&#xff0c;尤其是大模型&#xff08;LLM&#xff09;在各行各业的深度应用和整合&#xff0c;企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者&#xff0c;还是积极拥抱AI转型的传统企业&#xff0c;在面向公众…...