【Linux】Docker 中搭建Redis单节点以及集群

引言

搭建集群首先需要安装Docker,Linux中安装比较简单,具体可以参考[【Docker】Linux安装Docker(极简版)]。

[【RocketMq】RocketMq 4.9.4 Windows-docker 部署] 中提到了Windows安装Docker的一部分些细节,这里不再过多讨论,安装完成之后的Redis集群搭建同样可以参考本篇进行构建。

过去个人在Mac上搭建过一次集群,和本文的搭建思路相似。如果是Mac用户可以参考:[M1-Mac中docker的redis集群配置]

Docker拉取Redis

查找和拉取Redis的命令为 docker search redisdocker pull reids:latest(或指定其他版本),查找之后拉取指定版本的Redis到本地Docker即可。

具体的操作流程如下,这里省略了docker search redis的过程。下面是在windows的Docker操作,Linux指定效果一致:

单节点启动

单节点非常简单,适合立马上手使用学习的开发者,按照下面的命令执行:

#默认拉取一个最新的redis镜像
docker pull redis
#在默认的6379端口上启动一个redis服务
docker run --name test-redis -p 6379:6379 -d redis
#进入容器内部
docker exec -it test-redis /bin/bash
# 连接redis
redis-cli
#进入之后安装惯例 ping一下即可
ping

自定义配置单节点

Linux中可以使用下面的方式:

docker run -d -p 6380:6379 -v /usr/docker/redis/myRedis/redis.conf:/etc/redis/redis.conf -v /usr/docker/redis/myRedis/data:/data --name myRedis redis redis-server /etc/redis/redis.conf

在Windows版本的docker仅仅是路径配置不太一样,需要替换为指定盘符的地址。

集群搭建

集群构建的步骤其实并不算特别复杂,关键在于配置以及一些模版命令上需要读者自行修改。

自定义redis-net

创建docker newwork 虚拟网段用于redis集群节点通信使用。

此命令需要提前执行,否则后续的步骤会报错,建议一开始立即执行。

docker network create redis-net

创建redis.conf配置模版

我们需要创建一个docker/redis/目录,在新建目录内创建6个redis.conf文件。比较笨的传统办法是一个个构建,当然这样一个个复制实在是太麻烦了,我们寻找更快的方式,下文会进行介绍。

为了更高效的构建redis的配置,我们通过创建模板的方式构建redis.conf模板,注意这一份配置文件格式既不能有误也不能乱写,否则整个redis构建过程是必定会出问题的,配置文件如下:

先来个简单版本的模板:

port ${PORT}
cluster-enabled yes
protected-mode no
cluster-config-file nodes.conf
cluster-node-timeout 5000
#对外ip,这里的ip要改为你的服务器Ip。【注意不能使用127.0.0.1】
cluster-announce-ip 192.168.58.128
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
appendonly yes

如果对于模板构建熟练,可以使用复杂点的版本,具体内容如下:

# 启动端口
port ${PORT}

# 绑定IP, 0.0.0.0 为本地    
#bind 0.0.0.0  

# 日志等级
#loglevel notice    

# 日志文件位置
#logfile /opt/docker/${PORT}/redis${PORT}_log.txt

# 是否开启 AOF 持久化模式,默认 no
appendonly yes

# aof持久化文件格式
appendfilename appendonly.${PORT}.aof

# 集群文件
cluster-enabled yes

# 集群配置文件的名称,每个节点都有一个集群相关的配置文件,持久化保存集群的信息。
# 不配置,默认配置为nodes-6379.conf                        
#cluster-config-file nodes.${PORT}.conf
cluster-config-file nodes.conf

# 节点互连超时的阀值,集群节点超时毫秒数
cluster-node-timeout 5000

# 集群节点 IP,填写宿主机的 IP
cluster-announce-ip 192.168.58.128

# 集群节点映射端口
cluster-announce-port ${PORT}

# 集群节点总线端口
# 此参数建议+10000
cluster-announce-bus-port 1${PORT}

# 断线时间过长的从节点不允许设置为master,该参数就是用来判断slave节点与master断线的时间是否过长,作为计算参数之一
# 公式:(node-timeout * slave-validity-factor) + repl-ping-slave-perio,假设 node-timeout = 30,默认的repl-ping-slave-period是10秒,则如果超过310秒此slave将不会尝试进行故障转移 cluster-slave-validity-factor 10

# 可以配置值为1,表示master的slave数量大于这个数值,slave才能迁移到孤立的master上面
# 如果这个数值被设置为2,则只有一个主节点拥有2个可工作节点才会从一个从节点迁移。
cluster-migration-barrier 1

# 默认情况下,集群全部的slot有节点负责,集群状态才为ok,才能提供服务。  设置为no,可以在slot没有全部分配的时候提供服务。
# 不建议设置为no,因为容易造成分区并且可能导致小分区的Master节点一直在被写入造成数据不平衡的问题。
#cluster-require-full-coverage no

# redis 连接密码 访问认证
#requirepass 123456

# 主节点访问认证
#masterauth 123456

# 是否启动保护模式
protected-mode no

以上两个版本其实就是配置多和少的区别,个人以简单版本的文件进行记录和演示。新手如果不熟悉Docker集群搭建,建议把上面的配置单独配置保存,以便需要的时候立刻翻阅回忆构建流程。

模板配置

拥有redis.conf模板之后,我们开始依据这个模板构建集群目录和对应的数据存储。

集群配置

首先我们可以执行下面的命令构建对应的目录和配置,注意在构建之前跳转到自己部署redis集群的根目录,比如个人先cd /opt/docker/redis当中:

for port in `seq 6000 6000`; do 
  mkdir -p ./${port}/conf && PORT=${port} envsubst < ./redis_template_version2.conf > ./${port}/conf/redis.conf && mkdir -p ./${port}/data;
done

上面的命令是几个子命令拼凑在一起的,比较好理解:

  1. 在当前目录下构建“端口”对应的文件夹
  2. 定义把文件内部的${port}替换为对应的端口,重定向到页面替换。
  3. 输出到端口文件夹下面的conf/redis.conf,这样每个端口文件夹相当于一个独立的redis服务
  4. 最后构建data存储数据目录

这里略微解释一下${xx}这样的写法含义: 用shell格式字符串中的值替换环境变量。要替换的变量需要是${var}$var格式。 比如: echo '{{$HOME}}' | envsubst, 替换环境变量stdin输出到stdout: envsubst < {{path/to/input_file}},将输入文件中的环境变量替换为stdout: redis_template_version2.conf 就是前面的.conf模板文件的目录里。

简单版本的内容如下,这个文件的配置内容较为简化:

port ${PORT}
cluster-enabled yes
protected-mode no
cluster-config-file nodes.conf
cluster-node-timeout 5000
#对外ip,这里的ip要改为你的服务器Ip。【注意不能使用127.0.0.1】,因为Docker自身运行有一层内部网络,这个网络是为了支持节点内部通信的。
cluster-announce-ip 192.168.58.128
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
appendonly yes

构建完成之后,我们可以看到对应的文件夹内容如下(部分文件为个人实验命令):

为了方便展示,这里使用 tree 命令,注意tree通常需要手动安装,具体的安装过程如下:

sudo yum install tree

最后整个树形目录构建如下:

[zxd@localhost docker]$ tree
.
├── 6000
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── 6001
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── 6002
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── 6003
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── 6004
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── 6005
│?? ├── conf
│?? │?? └── redis.conf
│?? └── data
│??     ├── appendonlydir [error opening dir]
│??     └── nodes.conf
├── redis-back1.conf
├── redis_init_config.txt
├── redis_init.txt
├── redis_template.conf
└── redis_templat_version2.conf

运行redis节点

构建集群需要确保每一个节点都能够单独执行:

for port in `seq 6000 6000`; do
  docker run -d -ti -p ${port}:${port} -p 1${port}:1${port} -v /opt/docker/redis/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /opt/docker/redis/${port}/data:/data  --restart always --name redis-${port} --net redis-net --sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf;
done

之后docker ps查看所有节点是否正常启动,同时对于每个节点进行连接测试,由于篇幅有限,这里就不过多介绍了。

如果是线上部署,建议每个节点进入试一遍看看是否能正常单节点运行,保证都可以正常启动的情况下,开始尝试构建集群。

构建redis集群

我们启动6个节点之后,只需要进入到某一个节点的容器内部执行构建集群的命令即可,以个人的启动过程为例,执行下面的步骤:

  1. 执行docker ps命令。检查所有集群均正常搭建。

  1. 获取其中一个节点的容器id,当然也可以直接通过最后一列的NAMES进入,我们执行下面的命令:
docker exec -it d0073d25a732 /bin/bash

或者执行命令

`

docker exec -it redis-6000 /bin/bash

顺利进入到容器当中,此时还需要执行redis-cli真正进入到redis内部。注意启动端口是从6000-6005,直接用默认的redis-cli 会进入到6379的端口,这样连接是会失败的,所以我们最好指定端口和ip运行redis-cli

docker exec -it redis-6000 /bin/bash

root@d0073d25a732:/data# redis-cli -h 192.168.58.128 -p 6000
192.168.58.128:6000> ping
PONG
192.168.58.128:6000> 

注意:进入节点容器内部之后,可以直接执行redis-cli,也可以进入到/usr/local/bin下运行相关命令。

到了关键的步骤,我们开始构建redis节点集群。注意这一步建议进入容器之后跳转到/usr/local/bin

redis-cli --cluster create 192.168.58.128:6000 192.168.58.128:6001 192.168.58.128:6002 192.168.58.128:6003 192.168.58.128:6004 192.168.58.128:6005 --cluster-replicas 1

自己构建集群需要把Ip和端口进行相对应的修改操作

root@d0073d25a732:/usr/local/bin# ./redis-cli --cluster create 192.168.58.128:6000 192.168.58.128:6001 192.168.58.128:6002 192.168.58.128:6003 192.168.58.128:6004 192.168.58.128:6005 --cluster-replicas 1

最终的打印内容如下:

>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.58.128:6004 to 192.168.58.128:6000
Adding replica 192.168.58.128:6005 to 192.168.58.128:6001
Adding replica 192.168.58.128:6003 to 192.168.58.128:6002
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: a3d907505eb8575c95fb91f13d8580e144ae2ebd 192.168.58.128:6000
   slots:[0-5460] (5461 slots) master
M: d429ebb22ff24dcc4a01f77776e3b8ba367c0365 192.168.58.128:6001
   slots:[5461-10922] (5462 slots) master
M: 868b2e39ebf455e086c5e418537a04f1fc24f23b 192.168.58.128:6002
   slots:[10923-16383] (5461 slots) master
S: c2e9e28bf4dec5f9603e176eea4e19857a548c27 192.168.58.128:6003
   replicates 868b2e39ebf455e086c5e418537a04f1fc24f23b
S: 9dc71ed4313eb7db87bee287954c38d26a9ef950 192.168.58.128:6004
   replicates a3d907505eb8575c95fb91f13d8580e144ae2ebd
S: cbbc3c7a21a16581ddd3136d7169eecb6c2faf83 192.168.58.128:6005
   replicates d429ebb22ff24dcc4a01f77776e3b8ba367c0365
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 192.168.58.128:6000)
M: a3d907505eb8575c95fb91f13d8580e144ae2ebd 192.168.58.128:6000
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 868b2e39ebf455e086c5e418537a04f1fc24f23b 192.168.58.128:6002
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 9dc71ed4313eb7db87bee287954c38d26a9ef950 192.168.58.128:6004
   slots: (0 slots) slave
   replicates a3d907505eb8575c95fb91f13d8580e144ae2ebd
M: d429ebb22ff24dcc4a01f77776e3b8ba367c0365 192.168.58.128:6001
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: c2e9e28bf4dec5f9603e176eea4e19857a548c27 192.168.58.128:6003
   slots: (0 slots) slave
   replicates 868b2e39ebf455e086c5e418537a04f1fc24f23b
S: cbbc3c7a21a16581ddd3136d7169eecb6c2faf83 192.168.58.128:6005
   slots: (0 slots) slave
   replicates d429ebb22ff24dcc4a01f77776e3b8ba367c0365
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

如果出现类似的提示,说明集群创建成功,如果报错则确定节点是否正确,构建集群的命令是否正确,比如IP和端口是否写对,是否存在对应的节点等等。

连接测试

要连接Docker的Redis,首先要进入到某个容器的内部,然后再容器内部的Shell连接上Redis集群,下面是个人的实验步骤:

  1. docker ps -a 查看当前的集群情况,这里的容器ID为d0073d25a732
[zxd@localhost ~]$ docker ps -a
CONTAINER ID   IMAGE                                      COMMAND                  CREATED       STATUS                     PORTS                                                                                                               NAMES
27ea2f9dced7   mysql:5.7                                  "docker-entrypoint.s…"   3 weeks ago   Up About an hour           33060/tcp, 0.0.0.0:13306->3306/tcp, :::13306->3306/tcp                                                              mysql57
8aad8f4d75af   apache/rocketmq:4.9.4                      "sh mqbroker -c ../c…"   3 weeks ago   Up About an hour           0.0.0.0:10909->10909/tcp, :::10909->10909/tcp, 9876/tcp, 10912/tcp, 0.0.0.0:10911->10911/tcp, :::10911->10911/tcp   rmqbroker
dc2aefc4db1f   apache/rocketmq:4.9.4                      "sh mqnamesrv"           3 weeks ago   Up About an hour           10909/tcp, 0.0.0.0:9876->9876/tcp, :::9876->9876/tcp, 10911-10912/tcp                                               rmqnamesrv
195d102724b5   apacherocketmq/rocketmq-dashboard:latest   "sh -c 'java $JAVA_O…"   3 weeks ago   Up About an hour           0.0.0.0:8888->8080/tcp, :::8888->8080/tcp                                                                           rocketmq-dashboard
cb04e4c79e39   redis                                      "docker-entrypoint.s…"   3 weeks ago   Exited (255) 3 weeks ago   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp                                                                           test-redis
d0073d25a732   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6000->6000/tcp, :::6000->6000/tcp, 0.0.0.0:16000->16000/tcp, :::16000->16000/tcp, 6379/tcp                  redis-6000
559261cf34e6   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6005->6005/tcp, :::6005->6005/tcp, 0.0.0.0:16005->16005/tcp, :::16005->16005/tcp, 6379/tcp                  redis-6005
bd0fd81d54e7   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6004->6004/tcp, :::6004->6004/tcp, 0.0.0.0:16004->16004/tcp, :::16004->16004/tcp, 6379/tcp                  redis-6004
7a5545e038e8   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6003->6003/tcp, :::6003->6003/tcp, 0.0.0.0:16003->16003/tcp, :::16003->16003/tcp, 6379/tcp                  redis-6003
599b070b4afd   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6002->6002/tcp, :::6002->6002/tcp, 0.0.0.0:16002->16002/tcp, :::16002->16002/tcp, 6379/tcp                  redis-6002
d551114d11de   3e12e2ceb68f                               "docker-entrypoint.s…"   6 weeks ago   Up About an hour           0.0.0.0:6001->6001/tcp, :::6001->6001/tcp, 0.0.0.0:16001->16001/tcp, :::16001->16001/tcp, 6379/tcp                  redis-6001
  1. 我们进入到容器内部,使用命令docker exec -it d0073d25a732 /bin/bash
[zxd@localhost ~]$ docker exec -it d0073d25a732 /bin/bash
root@d0073d25a732:/data# 
  1. 进入到容器之后,使用命令redis-cli -c -h 192.168.58.128 -p 6000连接,然后经典的pingpong测试即可,注意这里的-c代表集群模式连接:
root@d0073d25a732:/data# redis-cli -c -h 192.168.58.128 -p 6000
192.168.58.128:6000> ping
PONG

以上整个docker集群搭建完毕。

常见问题

Could not connect to Redis at 127.0.0.1:6379: Connection refused

[root@rongle bin]# redis-cli
Could not connect to Redis at 127.0.0.1:6379: Connection refused
[root@rongle /]# redis-server /etc/redis.conf
[root@rongle /]# redis-cli
redis 127.0.0.1:6379>

这是 redis初学者比较常见的问题,可以从下面几个方面排查问题:

  1. redis.conf 是否关闭“保护模式”以及注释掉bind配置(默认 127.0.0.1)
  2. 是否启动端口和IP和连接的端口和IP不一致。
  3. docker的redis节点是否正常启动,如果在status里面发现不断重启,多半还是redis.conf存在问题。
  4. 命令的格式和规范是否正确。

收尾

以上就是快速构建docker redis集群的方式,整个过程不算很难,但是对于配置这一块需要小心不要写错了,否则很容易浪费时间调试,因为在Docker中会对于redis容器进行无限重启。

参考资料

Docker搭建Redis Cluster集群及扩容和收容 - Dvomu - 博客园 (cnblogs.com)

Redis集群原理及搭建(Twemproxy、Predixy代理搭建、Redis Cluster集群) - Dvomu - 博客园 (cnblogs.com)

本文转载于网络 如有侵权请联系删除

相关文章

  • 使用 eBPF 在生产环境调试 Go 应用

    本文是描述我们如何在生产中使用eBPF调试应用程序的系列文章中的第一篇,无需重新编译/重新部署,这篇文章介绍了如何使用gobpf[1]和uprobes为Go应用程序建立一个函数参数跟踪器,这种技术也可以扩展到其他编译语言,如C++、Rust等。 介绍通常在调试应用的时候,我们对捕获程序的状态比较感兴趣,这可以让我们检查应用程序正在做什么,并确定我们代码中的错误所在,观察状态的一个简单方法是使用调试器来捕获函数参数,对于Go应用程序,我们经常使用的是Delve或gdb。Delve和gdb在开发环境中调试效果很好,但在生产中并不经常使用,调试器会对程序造成很大的干扰,甚至允许状态变化,这可能就会导致生产环境的应用出现一些意外的故障。为了更干净地捕获函数参数,我们将探索使用Linux4.x+中可用的增强型BPF(eBPF[2])和更高级别的Go库gobpf的使用。什么是eBPF?ExtendedBPF(eBPF)是Linux4.x+中的一种内核技术,你可以把它看作是一个轻量级的沙盒虚拟机,它运行在Linux内核内部,可以提供对内核内存的验证访问。如下所示,eBPF允许内核运行BPF字节码,虽

  • 震撼!全网第一张源码分析全景图揭秘Nginx

    不管是C/C++技术栈,还是PHP,Java技术栈,从事后端开发的朋友对nginx一定不会陌生。想要深入学习nginx,阅读源码一定是非常重要的一环,但nginx源码量毕竟还是不算少,一不小心就容易陷入某个细节,迷失在茫茫码海之中。如果有一张地图,让我们开启上帝视角,总览全局,帮助我们快速学习整体框架结构,又能不至于迷失其中那就再好不过了!看到这篇文章的你有福了,笔者花了不少时间,把这件事给做了,先来看个全貌(限于平台图片尺寸设定,这里只能看个大概,想获取高清大图请看文末):下面选取一些关键部分来一窥神秘的nginx。主进程启动nginx主进程启动后,进行一系列的初始化,包括但不限于:命令行参数解析时间初始化日志初始化ssl初始化操作系统相关初始化一致性hash表初始化模块编号处理核心初始化另外一个最重要的初始化由ngx_init_cycle()函数完成,该函数围绕nginx中非常核心的一个全局数据结构ngx_cycle_t展开。该函数完成了几个核心初始化:配置文件解析创建并监听socket初始化nginx各模块nginx核心模块群nginx是一个模块化设计的软件,优秀的架构设计使得n

  • “战事”再升级!美国新规今日正式生效:限制AI软件出口至中国

    中美“战事”进一步升级!特朗普政府在1月3日采取的限制人工智能(AI)软件的出口新规于今日正式生效。 据路透社等海外媒体报道,新规规定出口某些地理空间图像软件的美国公司必须申请许可,才能将上述软件发送到海外(加拿大除外)。而限制这类人工智能软件的出口,是美国防止敏感技术被中国等竞争对手国家掌握的手段之一。根据文件显示,应用于智能化传感器、无人机、卫星和其他自动化设备的目标识别软件(无论民用或军用)都在限制范围之内。根据美国政府发布的公开文件,新规中的地理空间图像软件是指为训练深度神经网络以自动分析地理空间图像和点云而专门设计的软件。这类软件包括以下特征:即:1.提供图形用户界面,使用户能够从地理空间图像和点云中识别目标(如车辆、房屋等),以提取感兴趣对象的正面和负面样本;2.通过对正面样本进行大小、颜色和旋转归一化操作来减少像素变化;3.训练深度卷积神经网络以从正、负面样本中检测出感兴趣的目标;4.使用训练过的深度卷积神经网络,将正面样本中的旋转模式与地理空间图像中目标的旋转模式进行匹配,从而识别出地理空间图像中的目标。注:点云是给定坐标系定义的数据点的集合。点云也被认为是数字化曲面模

  • 深入机器学习系列之:Random Forest

    BaggingBagging采用自助采样法(bootstrapsampling)采样数据。给定包含m个样本的数据集,我们先随机取出一个样本放入采样集中,再把该样本放回初始数据集,使得下次采样时,样本仍可能被选中,这样,经过m次随机采样操作,我们得到包含m个样本的采样集。按照此方式,我们可以采样出T个含m个训练样本的采样集,然后基于每个采样集训练出一个基本学习器,再将这些基本学习器进行结合。这就是Bagging的一般流程。在对预测输出进行结合时,Bagging通常使用简单投票法,对回归问题使用简单平均法。若分类预测时,出现两个类收到同样票数的情形,则最简单的做法是随机选择一个,也可以进一步考察学习器投票的置信度来确定最终胜者。Bagging的算法描述如下图所示。随机森林随机森林是Bagging的一个扩展变体。随机森林在以决策树为基学习器构建Bagging集成的基础上,进一步在决策树的训练过程中引入了随机属性选择。具体来讲,传统决策树在选择划分属性时,在当前节点的属性集合(假设有d个属性)中选择一个最优属性;而在随机森林中,对基决策树的每个节点,先从该节点的属性集合中随机选择一个包含k个属

  • Jx.Cms开发笔记(七)-升级BootstrapBlazor到6.9.x

    由于BootstrapBlazor升级到6.9以后的升级还是非常大的,比如图标库升级到了6.1.2,bs升级到了5.2.0。所以这里记录一下升级过程。升级BootstrapBlazor主程序直接升级BootstarpBlazor到最新版本,没有错误,但是我们会发现我们的BootstrapBlazor自带图标全部变成方块了。这就需要升级图标库。升级图标库由于这个项目使用BootstrapBlazor的时间比较早,当时还没有BootstrapBlazor.Fontawasome的扩展库,我们是直接内部引用了fontawasome的css库。在现在看已经不合时宜了,因为BootstrapBlazor已经有了扩展库,我们可以直接用扩展库来处理我们的图标库,随时跟着项目升级走。所以我们直接从NuGet中安装BootstrapBlazor.FontAwasome。然后参照官网的安装说明,将我们_AdminHost.cshtml中的<linkrel="stylesheet"href="/Admin/css/font-awesome.min.css">改为引用NuGet包中的<lin

  • chmod 755 究竟是什么鬼?

    参考博客:https://blog.csdn.net/z50L2O08e2u4afToR9A/article/details/82504829

  • java中Lambda表达式相关的四大内置核心函数式接口

    知识点:java8中四大内置核心函数式接口 /***1.Consumer<T>:消费型接口*voidaccept(Tt);**2.Supplier<T>:供给型接口*Tget();**3.Function<T,R>:函数型接口*Rapply(Tt);**4.Predicate<T>:断言型接口*booleantest(Tt)***/publicclassTestLambda{//1.Consumer<T>:消费型接口voidaccept(Tt);@Testpublicvoidtest(){shopping(1000,(x)->System.out.println("今天购物发了"+x+"元"));}publicvoidshopping(doublemoney,Consumer<Double>con){con.accept(money);}//2.Supplier<T>:供给型接口Tget();@Testpublicvoidtest2(){List<Integer>numList=get

  • 拓展欧几里得模板

    关于原理,自行百度,如果还是看不懂,就强行数论入门吧,反正学了也不亏 intexgcd(inta,intb,int&x,int&y){ if(b==0){ x=1;y=0; returna; } intr=exgcd(b,a%b,x,y); intt=x;x=y;y=t-a/b*y; returnr; } 复制   

  • WindowsAPI-C#_使用特性StructLayout转化类型

    [StructLayout(LayoutKind.Explicit)]与[FieldOffset(0)]:FieldOffset(偏移量) [StructLayout(LayoutKind.Sequential)]与[MarshalAs(UnmanagedType.U4)]:UnmanagedType.类型 未写完 365个夜晚,我希望做到两天更一篇博客。加油,小白!

  • 【sqli-labs】 less57 GET -Challenge -Union -14 queries allowed -Variation4 (GET型 挑战 联合查询 只允许14次查询 变化4)

    双引号闭合 http://192.168.136.128/sqli-labs-master/Less-57/?id=1"%23复制 和less56一样查数据  

  • trading env &amp; action

    10/2021   env:earning:疫情下的供应链短缺,影响公司10月底的earning,>>短期的影响,在明年年初应该会出现好转。       intestrate:美联储tapering下, 购债规模降低,债卷跌,长期利率涨,短期波动会持续,长期利率上涨的趋势不会变         myplan:短期内保持观望的态度,关注服务业公司的机会。 10月低11月初的阶段,在大环境定下来后,决定是否加仓科技股。  

  • postman输入cookie进入登录状态

    问题描述 当直接调用接口,有可能会提示未登录 解决 找到登录的cookie,然后添加SESSION=ZGZiMzg1OTYtOWU4Yi00MDc2LWFhNDAtOTU2YjNkZTA2MmFm;Path=/console/;HttpOnly;即可 其中SESSION部分需要事时替换 操作过程 例如要执行修改某个属性 打开F12 修改属性,点击操作update 复制session 点击标头,获取请求接口 点击负载,获取总实体 postman中body主体即为{entity,ignoreEmpty,qualifyName} 点击预览,可以复制data数据替换entity中的内容 打开postman,创建request 请求接口为表头获取的接口 Body为负载中的总实体+预览中的entity

  • Consul 介绍

      1.Consul是什么?   Consul是一种多服务解决方案,提供具有服务发现,配置和分段功能的全功能控制平面。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全服务网格。Consul需要数据平面并支持代理和本机集成模型。Consul附带一个简单的内置代理,因此一切都可以开箱即用,但也支持第三方代理集成,如Envoy。     2. Consul特性?     服务发现:Consul的客户可以注册服务,例如 api或mysql,而其他客户可以使用Consul来发现给定服务的提供者。使用DNS或HTTP,应用程序可以轻松找到它们所依赖的服务。 运行状况检查:Consul客户端可以提供任意数量的运行状况检查,这些检查与给定服务(“是Web服务器返回200OK”)或本地节点(“内存利用率低于90%”)相关联。运营商可以使用此信息来监控群集运行状况,服务发现组件使用此信息将流量路由远离不健康的主机。 KV存储:应用程序可以将Consul的分层键/值存储用于任何用途,包括动态配置,功能标记,协调,领导者选举等。简单的HTTPAPI使其

  • js冒泡排序

    今天面试了家公司,最后要写个js的简单数组排序,很久都写不出来,好尴尬,随着语言的发展,这些简单方法越来越不被重视了。。。   <html> <head> <scripttype="text/javascript"> functionsort(arr){ for(vari=0;i<arr.length;i++){ for(varj=0;j<arr.length-i-1;j++){ if(arr[j]<arr[j+1]){ vartemp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; } } } returnarr; } vararr=[2,5,3,1,7,8,78,89]; sort(arr); </script> </head> <body> </body> </html>复制  

  • Sql面试总结

    1.数据表T用来记录用户登录、注销信息,其中只有4个记录: user(用户名) operate(操作) time(时间) LiMing Login 2010/10/248:03 WangYi Login 2010/10/248:14 WangYi Logout 2010/10/2416:14 LiMing Logout 2010/10/2416:44 请写出一个SQL查询语句,返回用户在线时间情况的结果集: LiMing 8:13 WangYi 8:46 createtabletb([user]varchar(20),operatevarchar(20),[time]datetime) insertintotbselect'LiMing','Login','2010/10/248:03' unionall select'WangYi','Login','2010/10/248:14' unionall select'WangYi','Logout','2010/10/2416:14' unionall select'LiMing','Logout','2010/10/2416:44'

  • linux python3 源码安装

    https://www.jianshu.com/p/53285c211985 tar-xvfPython-3.6.1.tar.xz make makeinstall 复制 懂得,原来世界如此简单!

  • Pytest集成Allure生成测试报告,并集成jenkins

    Pytest集成Allure生成测试报告,并集成jenkins 1、Allure安装 1)Allure报告的demo样式(是不是很漂亮呢) 2)Allure下载 选择需要的版本,下载zip文件,解压即可 2、添加allure环境变量 path:D:\ProgramFiles\allure-2.13.1\bin 复制 3、查看生成的allure报告 1.生成allure报告 #要先进入到allure生成的报告文件夹上级目录 cmd:allureserveallure生成的报告文件夹 复制 启动后会自动跳转到http://192.168.11.1:54011/打开测试报告 2.生成测试报告进化。。。 像上面的查看测试报告,比较麻烦,我们可以多做一步,使查看报告简便一些 cmd:alluregenerate<allure测试结果目录>-o<存放报告的目录>--clean 复制 执行完会得到一个文件夹 这样打开的测试报告跟第一种查看的测试报告数据是一样的,打开的时候就不需要在每次在dos窗口下输入命令了,但是这种的在PyCharm中可以直接浏览器打开,

  • 洛谷OJ P1036 选数

    题目描述 输入格式 输出格式 基本思路 一次选一个数,注意按照升序来选(因为是组合不是排列,避免最终选出的数集重复),采用递归的方式,每选完一个数在调用自身选下一个数,直到递归出口(全部选完) 程序清单 #include<stdio.h> #include<math.h> #include<stdbool.h> inta[20+5];//数组下标代表数在数组中的位置 intamt; intn,k,js=0; boolisprime(intx); voidsort(intw,intm);//从上一个数(第w-1个数,位置在m处)开始往后选出下一个数(第w个数)并加入总和,保证不重样 intmain() { scanf("%d%d",&n,&k); for(inti=0;i<n;i++)//输入第0到第n-1共n个数(位置即0到n-1) { scanf("%d",&a[i]); } sort(1,-1);//开始选第一个数,缺省第一个数的上一个数位置为-1 printf("%d",js); r

  • Android studio的主题颜色修改

    1、选择喜欢的主题 http://color-themes.com/?view=index好几十款,总有一款你喜欢复制   2、下载你喜欢的主题,注意是jar文件 1、File->ImportSettings... 2、然后选择你下载的jar文件,重启OK复制   3、androidstudio主题修改 http://blog.csdn.net/luohai859/article/details/37928091复制  

  • 大数据量冲击下Windows网卡异常分析定位

    背景 mqtt的服务端ActiveMQ在windows上,多台PC机客户端不停地向MQ发送消息。 现象 观察MQ自己的日志data/activemq.log里显示,TCP链接皆异常断开。此时尝试从服务端ping其他客户端,发现皆无法ping通。可知服务端网卡必定故障无法正常运作。 定位思路 原有的组网采用多PC通过hub互联,工作方式上讲hub是广播模式,多PC大数据量发送必然引发广播风暴,使网卡超载运行直至异常。 改为百兆交换机后,交换机能够隔离冲突域,数据交互情况明显有所好转。但仍偶现网卡故障的情况。 参考linux的网卡收包理论,通过修改conf/activemq.xml,为Mqtt_Uri加上transport.ioBufferSize=1048576&amp;transport.socketBufferSize=4194304。调整服务端MQ的接收socketBuffer为4M,此后网卡能够保持长期正常运行。说明增加socketBuffer可以减缓网卡往内存塞包的压力,降低网卡丢包又引发重传的恶性循环的可能,但也证明此时网卡的负载能力已濒临临界点。 与此同时,观察w

  • HCIA学习笔记四十:DHCP中继代理

    一、DHCPRelay组网场景 • DHCPRelay组网场景如下图:把用户的上线请求报文转发给DHCPServer。 二、DHCP Relay工作流程 • DHCPRelay的工作流程: 三、DHCPRelay实验 3.1、拓扑图 •分别在路由器中拖出1台AR2220、交换机中拖出一台S5700、终端中拖出2台PC机,然后选择设备连线,点击Copper进行设备接线,完成后开启设备。 3.2、配置 PC1: •双击PC1,在基础配置中将IPv4配置更改为DHCP模式。 PC2: •双击PC2,在基础配置中将IPv4配置更改为DHCP模式。 LSW1: <Huawei>system-view  //进入全局配置模式[Huawei]undoinfo-centerenable  //关闭信息告警提示 [Huawei]sysnameLSW1  //改名 [LSW1]vlan2  //创建VLAN2 [LSW1-vlan2]vlan3  //创建VLAN3 [LSW1-vlan3]intg0/0/2  //进入接口 [LSW1-Gigabi

相关推荐

推荐阅读