Nacos 持久化及集群的搭建【微服务】

文章目录

    • 一、统一配置管理
    • 二、微服务配置拉取
    • 三、配置热更新
    • 四、多环境共享配置
    • 五、Nacos 集群搭建
      • 1. 集群结构
      • 2. 初始化数据库
      • 3. 搭建集群
    • 六、Nginx 反向代理
    • 七、启动项目测试

一、统一配置管理

案例练习的时候我们只有两个微服务,管理起来非常简单,但在真正的项目中将会出现大量的微服务,当一些核心配置发生改变的时候,我们就需要修改所有与它相关的微服务,且不得不重启,这样带来的代价是非常大的。所以我们希望这些配置文件能够实现统一的管理,并且保证更改热更新,无需重启即可生效。
此时我们需要一个配置管理服务,将核心的经常需要改动的配置放上去,微服务启动的时候就可以去读取该配置,再与本地的配置相结合,作为完整配置去使用。当这些核心配置需要改动的时候,直接在配置管理服务中去改动就 OK 了,改完之后它就会立即通知微服务,完成配置的读取。

不管是注册中心还是配置管理服务,它们都是由 Nacos 实现的,所以配置管理服务也是在 Nacos 控制台设置的!

① 点击配置列表中的加号添加配置

在这里插入图片描述

② 填写配置表单,Data ID 其实就是配置文件的名称,该名称不能冲突,一般的命名格式为:服务名-生产环境.后缀名(userserver-dev.yaml)

在这里插入图片描述

③ 编写配置内容并发布,注意这里的内容并不是啥都往上写,我们只写核心的、有热更新需求的配置

在这里插入图片描述

在这里插入图片描述

二、微服务配置拉取

配置获取步骤如下:
项目启动 → 读取 Nacos 中的配置文件 → 读取本地配置文件 → 创建 spring 容器 → 加载 bean

Nacos 中的配置文件与本地配置文件相结合,组成最终的配置文件!

项目启动后,我们需要知道去哪里读取 Nacos 配置文件(当然是 Nacos)?要读取的又是哪个文件(落实到文件名)?而这些信息其实都被提前配到了一个叫 bootstrap.yml 文件中。

bootstrap.yml 是引导类配置文件,它的优先级高于 application.yml 文件,所以我们可以把 Nacos 地址以及文件的相关信息都写到 bootstrap.yml 里面,完成 Nacos 配置的读取,而后与本地文件相结合。

① 引入 Nacos 的配置管理客户端依赖

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

在这里插入图片描述

② 在 userserver 中的 resource 目录中添加一个 bootstrap.yml 文件,并编写 Nacos 地址和远程文件相关信息,服务名称+开发环境+文件后缀名其实就是远程配置文件的 Data ID

spring:application:name: userserver #服务名称profiles:active: dev #开发环境cloud:nacos:server-addr: localhost:8848 #Nacos地址config:file-extension: yaml #文件后缀名

在这里插入图片描述

③ 把 application.yml 中重复的配置删掉(服务名称和 Nacos 地址)

在这里插入图片描述

④ 在 UserController 中编写测试代码,试一下是否配置成功,@Value 注解读取配置

在这里插入图片描述

Spring Cloud 新版本默认将 Bootstrap 禁用,所以还需要引入 spring-cloud-starter-bootstrap 依赖到父工程中,否则会报错,旧版本可忽略这一步!

<dependency><!-- 新版本默认将 Bootstrap 禁用,需引入依赖 --><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

⑤ 启动项目并访问

在这里插入图片描述

三、配置热更新

上面的图片可以看到当前时间已经显示出来了,也就是说我们的 Nacos 生效了,那么热更新呢?我们接下来可以试一下配置自动刷新!

我们把远程配置修改一下并发布,刷新浏览器,发现它并没有热更新还是以前的配置,这是为什么呢?

在这里插入图片描述

在这里插入图片描述

Nacos 中的配置文件变更后,微服务无需重启就可以感知,不过需要通过下面两种配置实现:

① 方式一:在 @Value 注入的变量所在类上添加属性刷新的注解 @RefreshScope

在这里插入图片描述

在这里插入图片描述

② 方式二:使用 @ConfigurationProperties 注解,可以完成配置的自动更新

package com.zxe.userserver.pojo;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {private String dateformat;public String getDateformat() {return dateformat;}public void setDateformat(String dateformat) {this.dateformat = dateformat;}
}

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

推荐使用方式二,因为 @ConfigurationProperties 本身就可以自动更新,无需再添加其他注解!

四、多环境共享配置

什么情况下会遇到微服务的配置共享呢?比如某属性它在开发、生产、测试等环境下的值是一样的,这就没必要在每个环境中都写一遍了,代码冗余,而且如果要改动,每个配置文件都得改,这样显然是不合理的。我们想要只配置一次该属性,不管环境怎么变,该配置始终能被加载,这就是多环境配置共享。

我们之前的 Nacos 远程配置文件是 userserver-dev.yaml,dev 是跟环境相关的。而多环境配置不需要环境相关信息,所以这里的文件名应该是 userserver.yaml,当微服务启动的时候,userserver-dev.yaml 和 userserver.yaml 都会被读取,前者只在 dev 环境下加载,而后者在任何环境中都会被加载,因此,多环境共享配置可以写入这个文件里面。

① 新建配置并发布,DataID 为 userserver.yaml

在这里插入图片描述

在这里插入图片描述

② 编写测试代码,实体类新增 envSharedValue 属性

在这里插入图片描述

在这里插入图片描述

③ 便于测试,我们先在 dev 环境下启动一个服务,修改环境后再启动一个服务,观察控制台输出可以看到,userserver.yaml 的配置内容会同时在这两个环境中显示,这就是多环境共享配置

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

配置文件的优先级:
服务名-生产环境.yaml > 服务名.yaml > 本地配置

优先级:远程大于本地,具体大于共享!

五、Nacos 集群搭建

1. 集群结构

实际上,Nacos 的工作量远不止这些,所以为了减小 Nacos 的压力,我们一定为它配置集群模式,此处用 Nginx 来做负载均衡。
假设 A 为消费者,B 为生产者:在集群模式下,A 需要拉取 B,就会向 Nacos 发起拉取请求,此请求会被 Nginx 拦截走做负载均衡,即从 Nacos 集群中挑选一个节点出来,最终我们就是从该结点上拉取服务列表的,在该列表内部继续做负载均衡,挑选出一个具体的实例去处理真正的请求。

在这里插入图片描述

2. 初始化数据库

Nacos默认数据存储在内嵌数据库中,不属于生产可用的数据库。其实数据库也应该用主从模式的高可用数据库集群,为了节省时间这里我们以单点的数据库为例。

首先新建一个数据库,命名为 nacos,而后导入下面的 SQL:

/** Copyright 1999-2018 Alibaba Group Holding Ltd.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*//******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info   */
/******************************************/
CREATE TABLE `config_info` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`data_id` varchar(255) NOT NULL COMMENT 'data_id',`group_id` varchar(255) DEFAULT NULL,`content` longtext NOT NULL COMMENT 'content',`md5` varchar(32) DEFAULT NULL COMMENT 'md5',`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',`src_user` text COMMENT 'source user',`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',`app_name` varchar(128) DEFAULT NULL,`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',`c_desc` varchar(256) DEFAULT NULL,`c_use` varchar(64) DEFAULT NULL,`effect` varchar(64) DEFAULT NULL,`type` varchar(64) DEFAULT NULL,`c_schema` text,`encrypted_data_key` text NOT NULL COMMENT '秘钥',PRIMARY KEY (`id`),UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_aggr   */
/******************************************/
CREATE TABLE `config_info_aggr` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`data_id` varchar(255) NOT NULL COMMENT 'data_id',`group_id` varchar(255) NOT NULL COMMENT 'group_id',`datum_id` varchar(255) NOT NULL COMMENT 'datum_id',`content` longtext NOT NULL COMMENT '内容',`gmt_modified` datetime NOT NULL COMMENT '修改时间',`app_name` varchar(128) DEFAULT NULL,`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',PRIMARY KEY (`id`),UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_beta   */
/******************************************/
CREATE TABLE `config_info_beta` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`data_id` varchar(255) NOT NULL COMMENT 'data_id',`group_id` varchar(128) NOT NULL COMMENT 'group_id',`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',`content` longtext NOT NULL COMMENT 'content',`beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',`md5` varchar(32) DEFAULT NULL COMMENT 'md5',`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',`src_user` text COMMENT 'source user',`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',`encrypted_data_key` text NOT NULL COMMENT '秘钥',PRIMARY KEY (`id`),UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_tag   */
/******************************************/
CREATE TABLE `config_info_tag` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`data_id` varchar(255) NOT NULL COMMENT 'data_id',`group_id` varchar(128) NOT NULL COMMENT 'group_id',`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',`tag_id` varchar(128) NOT NULL COMMENT 'tag_id',`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',`content` longtext NOT NULL COMMENT 'content',`md5` varchar(32) DEFAULT NULL COMMENT 'md5',`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',`src_user` text COMMENT 'source user',`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',PRIMARY KEY (`id`),UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_tags_relation   */
/******************************************/
CREATE TABLE `config_tags_relation` (`id` bigint(20) NOT NULL COMMENT 'id',`tag_name` varchar(128) NOT NULL COMMENT 'tag_name',`tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',`data_id` varchar(255) NOT NULL COMMENT 'data_id',`group_id` varchar(128) NOT NULL COMMENT 'group_id',`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',`nid` bigint(20) NOT NULL AUTO_INCREMENT,PRIMARY KEY (`nid`),UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = group_capacity   */
/******************************************/
CREATE TABLE `group_capacity` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',`group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',PRIMARY KEY (`id`),UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = his_config_info   */
/******************************************/
CREATE TABLE `his_config_info` (`id` bigint(20) unsigned NOT NULL,`nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,`data_id` varchar(255) NOT NULL,`group_id` varchar(128) NOT NULL,`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',`content` longtext NOT NULL,`md5` varchar(32) DEFAULT NULL,`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,`src_user` text,`src_ip` varchar(50) DEFAULT NULL,`op_type` char(10) DEFAULT NULL,`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',`encrypted_data_key` text NOT NULL COMMENT '秘钥',PRIMARY KEY (`nid`),KEY `idx_gmt_create` (`gmt_create`),KEY `idx_gmt_modified` (`gmt_modified`),KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = tenant_capacity   */
/******************************************/
CREATE TABLE `tenant_capacity` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',PRIMARY KEY (`id`),UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';CREATE TABLE `tenant_info` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`kp` varchar(128) NOT NULL COMMENT 'kp',`tenant_id` varchar(128) default '' COMMENT 'tenant_id',`tenant_name` varchar(128) default '' COMMENT 'tenant_name',`tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',`create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',`gmt_create` bigint(20) NOT NULL COMMENT '创建时间',`gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',PRIMARY KEY (`id`),UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';CREATE TABLE `users` (`username` varchar(50) NOT NULL PRIMARY KEY,`password` varchar(500) NOT NULL,`enabled` boolean NOT NULL
);CREATE TABLE `roles` (`username` varchar(50) NOT NULL,`role` varchar(50) NOT NULL,UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
);CREATE TABLE `permissions` (`role` varchar(50) NOT NULL,`resource` varchar(255) NOT NULL,`action` varchar(8) NOT NULL,UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');

在这里插入图片描述

3. 搭建集群

条件有限,我们只能在一台电脑上部署 Nacos 节点。

① 进入 Nacos 的 conf 目录,修改配置文件 cluster.conf.example,重命名为 cluster.conf

在这里插入图片描述

② 打开 cluster.conf,修改 IP 地址和端口号,这里三个节点均为本机,所以 IP 是你自己本机的 IP 地址(不方便展示,我这里用127.0.0.1代替),如果在生产环境中应该是三台真实机器的 IP 地址,注意 2.0 版本以上的 Nacos 端口号一定不能是连续的数字,否则到后面启动的时候会报错

cmd → ipconfig 查看,注意这里的 IP 必须是外网 IP,如果使用内网 IP 就会出现服务列表在各 Nacos 节点上不同步的问题!

127.0.0.1:2222
127.0.0.1.3333
127.0.0.1.4444

在这里插入图片描述

③ 编辑 application.properties 文件,打开数据源(去掉前面的注释符号),告诉 Nacos 我们用的是 mysql 集群,打开数据库数量(我们只有一台 mysql),打开数据库配置(修改自己的数据库名、账号和密码)

在这里插入图片描述

④ 将 Nacos 文件夹复制三份,分别命名为 nacos1、nacos2、nacos3

在这里插入图片描述

⑤ 分别修改三个文件夹中的 application.properties,填写各自的端口号

在这里插入图片描述

⑥ 分别启动三个 Nacos 节点

startup.cmd

在这里插入图片描述

如果你的 Nacos 版本是 2.0 以上的,那么这时当你在启动第二个节点的时候就会报错(低版本不影响,不报错的可直接跳过这里),报错信息如下:

在这里插入图片描述

简单的来说就是端口被占用了!由于Nacos 2.0 版本新增了 gRPC 通讯方式,导致自身还需要两个端口 9848 和 9849,这就要保证 8848、9848、9849 是空闲的。
而这两个端口号是怎么来的呢?我们都知道原端口号是 8848,那么 9848 和 9849 其实就是原端口号加 1000 和 1001 的结果,如果节点配置的是连续的端口号(比如1111、1112、1113),那么当第二个节点启动的时候,9848 和 9849 这两个端口一定是被第一个节点占用的,所以在前面 cluster.conf 中配置端口的时候,端口号至少应该隔一个位置。

六、Nginx 反向代理

Nginx 下载点击这里!

在这里插入图片描述

① 编辑 conf 目录下的 nginx.conf,将配置代码粘贴到 http 花括号里面

同样,这里的 127.0.0.1 也要替换成你的外网 IP 地址!

upstream nacos-cluster {server 127.0.0.1:2222;server 127.0.0.1:3333;server 127.0.0.1:4444;
}server {listen       80;server_name  localhost;location /nacos {proxy_pass http://nacos-cluster;}
}

在这里插入图片描述

在这里插入图片描述

只要访问到 localhost/nacos 路径,就会被 Nginx 代理到 http://nacos-cluster 集群,然后做负载均衡,最终选择一个节点出来去处理请求。

② Nacos 2.0 以上版本还需配置 grpc 协议,依然是在 nginx.conf 文件里面,粘贴以下代码

注意不要粘在 http 里面!

# nacos的grpc协议配置
stream {upstream nacoscluster-grpc{# nacos2版本,grpc端口与要比主端口多1000server 127.0.0.1:3222 weight=1;server 127.0.0.1:4333 weight=1;server 127.0.0.1:5444 weight=1;}server{listen 1080;proxy_pass nacoscluster-grpc;}
}

在这里插入图片描述

③ 在 nginx.exe 所在目录下 cmd 打开黑窗口,start nginx.exe 启动 Nginx

在这里插入图片描述

④ Nginx 启动成功之后,打开浏览器并访问 localhost/nacos,代理成功,我们看到的 Nacos 只有一个,实际上 Nginx 已经在 Nacos 集群中做了负载均衡

在这里插入图片描述

七、启动项目测试

① Nacos 地址已经不再是 8848 了,Nginx 里面配的是 80,所以代码里面的 Nacos 端口也要改成 80

在这里插入图片描述

② 启动服务测试一下,多刷新几次 Nacos 控制台,可以看到我们的服务已经注册进去了

在这里插入图片描述

在这里插入图片描述

③ 接下来可以新建一个配置文件,测试以下共享配置是否也可以生效

在这里插入图片描述

在这里插入图片描述

④ 这个配置其实已经存到 nacos 数据库里面了,这就是 Nacos 数据的持久化

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【100个Cocos实例】通过重写源码实现循环PageView

引言 Cocos中通过重写源码实现循环PageView 大家好&#xff0c;有小伙伴私信我&#xff1a; 有没有办法实现循环的PageView列表的方法呢 本文将介绍一下Cocos中通过重写源码实现循环PageView。 本文源工程可在文末阅读原文获取&#xff0c;小伙伴们自行前往。 1.什么是Page…

【Spring实战】25 Spring Boot Admin 应用

文章目录 1. 查看健康信息2. 使用 Micrometer 和 "/metrics"3. 管理包和类的日志级别4. 其他功能总结 Spring Boot Admin 是一个功能强大的工具&#xff0c;用于监控和管理多个 Spring Boot 应用程序。通过上一篇文章 【Spring实战】24 使用 Spring Boot Admin 管理…

景联文科技GPT教育题库:AI教育大模型的强大数据引擎

GPT-4发布后&#xff0c;美国奥数队总教练、卡耐基梅隆大学数学系教授罗博认为&#xff0c;这个几乎是用“刷题”方式喂大的AI教育大模型的到来&#xff0c;意味着人类的刷题时代即将退出历史舞台。 未来教育将更加注重学生的个性化需求和多元化发展&#xff0c;借助GPT和AI教育…

工厂方法模式(Factory Method)

文章目录 定义与类型适用场景优点缺点工厂方法代码示例 定义与类型 定义&#xff1a;定义一个创建对象的接口&#xff0c;但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。 类型&#xff1a;创建型。 适用场景 创建对象需要大量重复的代码…

mysql视图和sql语句

mysql视图和sql语句 一.mysql视图1.数据的虚拟表示&#xff1a;2.简化复杂查询&#xff1a;3.安全性和权限控制&#xff1a;4.逻辑数据组织&#xff1a;5.更新限制&#xff1a;6.视图的创建&#xff1a; 二.mysq语句使用案列 MySQL的视图&#xff08;View&#xff09;是一个虚拟…

如何向嵌入式设备中添加tcpdump工具

说明&#xff1a;tcpdump是一个在网络设备调试中一个非常重要的工具&#xff0c;它并不像hexdump等工具集成在busybox里面&#xff0c;也不像其他的软件一样只需要依赖linux标准的库就可以实现&#xff0c;它需要pcap相关的库和加密的相关库。 本文主要是基于realtek 83系列的…

[VUE]5-TypeScript

目录 1 TypeScript 介绍2、安装3、快速上手4、TypeScript 常用类型4.1 类型标注的位置4.2 字符串、数字、布尔类型4.3 字面量类型4.4 ⭐interface 类型4.5 class 类型 ​&#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#xff0c;…

三、Qt核心与Qt类库

一、Qt核心&#xff1a;元对象系统 1、Qt核心特点 Qt对标准C进行了扩展&#xff0c;引入了一些新的概念和功能元对象编译器&#xff08;MOC&#xff09;是一个预处理器&#xff0c;先将Qt的特性程序转为标准C程序&#xff0c;再由标准C编译器进行编译Qt为C语言增加的特性在Qt…

LeetCode第32题 : 最长有效括号

题目介绍 给你一个只包含 ( 和 ) 的字符串&#xff0c;找出最长有效&#xff08;格式正确且连续&#xff09;括号子串的长度。 示例 1&#xff1a; 输入&#xff1a;s "(()" 输出&#xff1a;2 解释&#xff1a;最长有效括号子串是 "()" 示例 2&#xf…

【Python机器学习】线性模型——用于多分类的线性模型

很多线性分类模型只使用与二分类问题&#xff0c;将二分类算法推广到多分类算法的一种常见方法是“一对其余”方法。在“一对其余”方法中&#xff0c;对每个类别都学习一个二分类模型&#xff0c;将这个类别和其他类别尽量区分&#xff0c;这样就生成了与类别数相同的二分类模…

设计模式——最全梳理,最好理解

新年献礼&#xff01; 设计模式呕心梳理 创建型模式 单例模式&#xff08;Singleton Pattern&#xff09;https://blog.csdn.net/qq_34869143/article/details/134874044 整理中... 结构型模式 代理模式&#xff08;Proxy Pattern&#xff09;https://blog.csdn.net/qq_34…

Elasticsearch:Serarch tutorial - 使用 Python 进行搜索 (二)

这个是继上一篇文章 “Elasticsearch&#xff1a;Serarch tutorial - 使用 Python 进行搜索 &#xff08;一&#xff09;” 的续篇。在今天的文章中&#xff0c;我们接着来完成如何进行分页及过滤。 分页 - pagination 应用程序处理大量结果通常是不切实际的。 因此&#xff0…

css3 transform:scale

transform:scale 语法&#xff1a;transform:scale(x,y); <html> <head><style>.box1 {display: inline-block;width: 200px;height: 200px;background-color: pink;}.box2 {display: inline-block;width: 200px;height: 200px;background-color: red;tran…

电脑丢失dll文件怎么办,dll修复工具可一键修复dll问题

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中最常见的就是“找不到指定的模块”或“无法找到某某.dll文件”。这种情况通常是由于dll文件丢失或损坏导致的。那么&#xff0c;究竟是什么原因导致了dll文件的丢失呢&#xff1f;又该如何预防dll文件…

Linux vi/vim 教程

文章目录 【 1. vi/vim 的三种模式 】1.1 命令模式1.2 输入模式1.3 底线命令模式 【 2. 实例 】【 3. vim 的其他命令 】 所有的 Unix Like 系统都会内建 vi 文本编辑器&#xff0c;其他的文本编辑器则不一定会存在。目前我们使用比较多的是 vim 编辑器。vim 从 vi 发展出来&am…

transforms的操作

一、transforms的操作 1、transforms.RandomChoice transforms.RandomChoice 是一个数据转换操作&#xff0c;用于从一系列的转换方法中随机选择一个进行数据增强。 参数&#xff1a; transforms&#xff1a;一个包含多个转换方法的列表或元组。 示例&#xff1a; import …

[Javaweb/LayUI/上机考试作业/开源]学生/图书/课程/仓库等管理系统六合一基础功能通用模板

展示 考试要求 给定用户表和六张图书/教师/顾客/仓库....的表&#xff08;随机给每人抽选&#xff09;&#xff0c;要求实现用户登录注册&#xff0c;异步更新&#xff0c;对物品增删改查&#xff0c;精确/模糊查询等。 环境 tomcat 9 mysql 8 java 17 项目结构 项目类图 写前…

区间预测 | Matlab实现CNN-LSTM-KDE的卷积长短期神经网络结合核密度估计多变量时序区间预测

区间预测 | Matlab实现CNN-LSTM-KDE的卷积长短期神经网络结合核密度估计多变量时序区间预测 目录 区间预测 | Matlab实现CNN-LSTM-KDE的卷积长短期神经网络结合核密度估计多变量时序区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.CNN-LSTM-KDE多变量时间序列区…

JDK 11:崭新特性解析

JDK 11&#xff1a;崭新特性解析 JDK 11&#xff1a;崭新特性解析1. HTTP Client&#xff08;标准化&#xff09;示例代码 2. 局部变量类型推断的扩展示例代码 3. 新的字符串方法示例代码 4. 动态类文件常量示例代码 5. Epsilon 垃圾收集器使用方式 结语 JDK 11&#xff1a;崭新…

Redis(一)

1、redis Redis是一个完全开源免费的高性能&#xff08;NOSQL&#xff09;的key-value数据库。它遵守BSD协议&#xff0c;使用ANSI C语言编写&#xff0c;并支持网络和持久化。Redis拥有极高的性能&#xff0c;每秒可以进行11万次的读取操作和8.1万次的写入操作。它支持丰富的数…