Ruiyeclub

  • HOME
  • ARCHIVES
  • ABOUT
  • LINKS
🐤SpringBoot学习入门Demo,持续更新中...: https://github.com/ruiyeclub/SpringBoot-Hello

Docker如何通过容器名称进行连接

Posted on 2025-04-18

在Docker环境中,容器间的通信是构建微服务架构的基础。使用容器名称进行连接相比直接使用IP地址具有显著优势。

一、为什么需要使用容器名称连接?

  1. IP地址不稳定性问题:
    • 容器每次重启可能获得不同的IP地址(容器启动时会从子网中动态获取可用IP)
    • 在集群环境中IP地址变化更为频繁
    • 硬编码IP地址会导致连接失效

  2. 管理复杂性降低:
    • 使用有意义的名称比记忆IP更直观
    • 无需维护IP地址映射表
    • 配置文件中使用名称更具可读性

  3. 动态扩展支持:
    • 服务扩容时无需修改连接配置
    • 自动适应容器替换和迁移
    • 与负载均衡和服务发现机制更好配合

二、实现容器名称连接的核心条件

1. 必须使用自定义网络

Docker的默认bridge网络(docker0)不支持通过容器名称连接,只有自定义网络才提供内置DNS服务:

1
2
# 创建支持名称解析的自定义网络
docker network create my-app-network

2. 容器必须加入同一网络

所有需要互相通信的容器必须连接到同一个自定义网络:

1
2
docker run -d --name service-a --network my-app-network my-image
docker run -d --name service-b --network my-app-network my-image

三、实战演示:通过名称连接MySQL与应用

场景准备

假设我们需要部署一个Web应用连接MySQL数据库

步骤1:创建专用网络

1
docker network create app-network

步骤2:启动MySQL容器

1
2
3
4
5
6
docker run -d \
--name mysql-db \
--network app-network \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=myapp \
mysql:8.0

步骤3:启动应用容器

1
2
3
4
5
6
7
docker run -d \
--name web-app \
--network app-network \
-e DB_HOST=mysql-db \
-e DB_PASSWORD=secret \
-p 8080:8080 \
my-web-app

连接验证

在web-app容器中:

1
2
3
4
5
6
# 进入容器shell
docker exec -it web-app sh

# 测试连接MySQL
ping mysql-db # 应能成功解析
nc -zv mysql-db 3306 # 检查端口连通性

四、特殊场景处理:1Panel环境下的网络集成

1Panel等管理面板会创建自己的网络(如1panel-network),需要将自定义容器加入该网络:

查看1Panel管理的MySQL网络

1
docker inspect 1Panel-mysql-Zhb7 | grep NetworkMode

将应用容器加入同一网络

1
docker network connect 1panel-network my-app-container

验证连接

1
2
# 在应用容器中测试
ping 1Panel-mysql-Zhb7

五、常见问题排查

  1. 无法解析容器名:
    • 确认容器在同一自定义网络
    • 检查网络连接状态:docker network inspect <network>
    • 验证DNS解析:docker exec -it container-name nslookup target-name

  2. 连接超时:
    • 检查目标服务是否监听正确端口
    • 验证防火墙/安全组设置
    • 测试基础连通性:ping和telnet

  3. 1Panel环境特殊问题:
    • 确认容器已加入1panel-network
    • 检查1Panel的网络隔离策略
    • 查看1Panel的日志获取连接失败详情

六、踩坑记录

关于mysql的容器应用连接


使用Redis和RedisTemplate设计当日访问量和访问人数统计

Posted on 2025-04-01

在Java中使用Redis和RedisTemplate来统计当日访问量和访问人数(UV)是一个常见的需求。下面我将提供一个完整的实现方案。

1. 设计思路

• **访问量(PV)**:使用Redis的INCR命令统计总访问次数
• **访问人数(UV)**:使用Redis的HyperLogLog数据结构统计独立访客数
• 过期时间:设置当日24点自动过期

2. 实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.concurrent.TimeUnit;

@Service
public class VisitStatisticsService {

private final RedisTemplate<String, String> redisTemplate;

public VisitStatisticsService(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}

// 获取当日PV的key
private String getTodayPVKey() {
return "stat:pv:" + LocalDate.now().toString();
}

// 获取当日UV的key
private String getTodayUVKey() {
return "stat:uv:" + LocalDate.now().toString();
}

// 获取当天剩余的秒数(到24点的秒数)
private long getRemainingSecondsToday() {
ZonedDateTime now = ZonedDateTime.now(ZoneId.systemDefault());
ZonedDateTime midnight = now.toLocalDate().plusDays(1).atStartOfDay(ZoneId.systemDefault());
return midnight.toEpochSecond() - now.toEpochSecond();
}

/**
* 记录访问
* @param userId 用户ID(可以为IP地址或其他唯一标识)
*/
public void recordVisit(String userId) {
// 获取当天剩余的秒数
long remainingSeconds = getRemainingSecondsToday();

// 记录PV(访问量)
ValueOperations<String, String> valueOps = redisTemplate.opsForValue();
String pvKey = getTodayPVKey();
valueOps.increment(pvKey);
redisTemplate.expire(pvKey, remainingSeconds, TimeUnit.SECONDS);

// 记录UV(独立访客)
String uvKey = getTodayUVKey();
redisTemplate.opsForHyperLogLog().add(uvKey, userId);
redisTemplate.expire(uvKey, remainingSeconds, TimeUnit.SECONDS);
}

/**
* 获取当日访问量(PV)
*/
public Long getTodayPV() {
String pvKey = getTodayPVKey();
String value = redisTemplate.opsForValue().get(pvKey);
return value == null ? 0L : Long.parseLong(value);
}

/**
* 获取当日访问人数(UV)
*/
public Long getTodayUV() {
String uvKey = getTodayUVKey();
return redisTemplate.opsForHyperLogLog().size(uvKey);
}

/**
* 获取历史某天的访问量(PV)
* @param date 日期
*/
public Long getPVByDate(LocalDate date) {
String pvKey = "stat:pv:" + date.toString();
String value = redisTemplate.opsForValue().get(pvKey);
return value == null ? 0L : Long.parseLong(value);
}

/**
* 获取历史某天的访问人数(UV)
* @param date 日期
*/
public Long getUVByDate(LocalDate date) {
String uvKey = "stat:uv:" + date.toString();
return redisTemplate.opsForHyperLogLog().size(uvKey);
}
}

3. 使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@RestController
@RequestMapping("/api/visit")
public class VisitController {

private final VisitStatisticsService visitStatisticsService;

public VisitController(VisitStatisticsService visitStatisticsService) {
this.visitStatisticsService = visitStatisticsService;
}

@GetMapping("/record")
public String recordVisit(@RequestParam String userId) {
visitStatisticsService.recordVisit(userId);
return "Visit recorded for user: " + userId;
}

@GetMapping("/stats")
public Map<String, Object> getStats() {
Map<String, Object> result = new HashMap<>();
result.put("pv", visitStatisticsService.getTodayPV());
result.put("uv", visitStatisticsService.getTodayUV());
return result;
}
}

4. 设计说明

  1. PV统计:
    • 使用简单的计数器(INCR命令)
    • 每个访问请求调用一次INCR
    • 键格式:stat:pv:yyyy-MM-dd

  2. UV统计:
    • 使用HyperLogLog数据结构
    • 内存占用小(每个HyperLogLog约12KB)
    • 误差率约0.81%
    • 键格式:stat:uv:yyyy-MM-dd

  3. 过期时间:
    • 自动计算到当天24点的剩余秒数
    • 设置键的过期时间
    • 避免数据无限增长

  4. 扩展性:
    • 可以轻松扩展为按小时、周、月统计
    • 可以添加用户行为分析(如访问页面、停留时间等)

5. 性能优化

  1. 批量操作:如果有批量记录需求,可以使用pipeline提高性能
  2. 持久化:如果需要长期保存数据,可以定期将Redis数据持久化到数据库
  3. 分布式:此方案天然支持分布式环境

6. 注意事项

  1. HyperLogLog有约0.81%的误差率,如果要求精确计数,可以使用Set数据结构(但内存消耗更大)
  2. Redis重启可能导致数据丢失,重要数据应考虑持久化方案
  3. 在高并发场景下,INCR命令是原子操作,无需担心并发问题

这个实现方案简单高效,适合大多数Web应用的访问统计需求。


绕过cloudflare 5秒盾的技术方案解析

Posted on 2025-02-18

Cloudflare 的 5秒盾(Under Attack Mode)是网站防护的常见手段,通过 JavaScript 挑战验证访客真实性。很多网站会使用Cloudflare提供安全服务,导致爬虫的时候显示403状态。

55187d199c2a9079caff09622c6f78f9933ed773

一、解决方案及代码示例

1. 使用 cloudscraper 库

原理:模拟 Cloudflare 预期的请求特征

1
2
3
4
5
import cloudscraper

scraper = cloudscraper.create_scraper()
response = scraper.get("https://target-site.com")
print(response.text)

2. 使用 curl_cffi 库

优势:支持多浏览器指纹模拟

1
2
3
4
5
6
7
from curl_cffi import requests

response = requests.get(
"https://target-site.com",
impersonate="chrome110" # 支持 chrome99-110 / edge99-110
)
print(response.text)

3. 第三方 API 服务

推荐服务:

  • ScrapingBee(自带代理轮转)
  • ScraperAPI
  • ZenRows
1
2
3
4
5
6
import requests

API_KEY = "your_api_key"
response = requests.get(
f"https://api.scrapingbee.com/v1/?api_key={API_KEY}&url=target-site.com"
)

4. FlareSolverr 服务

架构:基于 Puppeteer 的中间件服务

部署步骤:

1
2
3
4
5
6
docker run -d \
--name flaresolverr \
-p 8191:8191 \
-e LOG_LEVEL=info \
--restart unless-stopped \
ghcr.io/flaresolverr/flaresolverr:latest

调用示例:

1
2
3
4
5
6
7
8
import requests

payload = {
"cmd": "request.get",
"url": "https://target-site.com",
"maxTimeout": 60000
}
response = requests.post("http://localhost:8191/v1", json=payload)

二、方案对比分析

方案 执行速度 维护成本 隐匿性 适用场景
cloudscraper ★★★★ 低 中 中小规模常规采集
curl_cffi ★★★★★ 低 高 需要最新指纹场景
第三方API ★★★ 中 高 企业级高频采集
FlareSolverr ★★ 高 极高 复杂JS验证场景

三、对抗升级建议

  1. IP轮换策略:结合住宅代理使用(推荐 BrightData)
  2. 指纹随机化:定期更换 User-Agent/TLS 指纹
  3. 请求限速:设置 3-10 秒随机延迟
  4. 头信息校验:携带完整 Accept-Encoding/Cookie 等头

RabbitMQ常见面试题技术文档

Posted on 2025-02-07

RabbitMQ 常见面试题技术文档


一、基础概念

1. 什么是消息队列(Message Queue)?RabbitMQ 的核心作用是什么?

答案:
消息队列是一种异步通信机制,用于解耦生产者和消费者,实现系统间可靠的消息传递。
RabbitMQ 的核心作用包括:

  • 异步处理:提升系统响应速度和吞吐量。
  • 应用解耦:通过中间件隔离服务间的直接依赖。
  • 流量削峰:缓冲突发流量,避免系统过载。
  • 消息广播:支持一对多消息分发模式。

2. AMQP 协议是什么?RabbitMQ 如何基于 AMQP 工作?

答案:
AMQP(Advanced Message Queuing Protocol)是应用层协议,定义了消息中间件的统一通信标准。
RabbitMQ 基于 AMQP 模型:

  • 生产者(Producer)发送消息到 Exchange。
  • Exchange 根据路由规则(Binding Key)将消息分发到 Queue。
  • 消费者(Consumer)从 Queue 中获取消息。

二、核心组件

3. RabbitMQ 的核心组件有哪些?

答案:

  • Exchange:消息路由中心,决定消息如何分发到队列。
  • Queue:存储消息的缓冲区,消费者从中订阅消息。
  • Binding:定义 Exchange 和 Queue 之间的映射规则。
  • Channel:复用 TCP 连接的轻量级通信通道。
  • Virtual Host:逻辑隔离单元,类似命名空间。

4. Exchange 的四种类型及其区别?

答案:

类型 路由规则 典型场景
Direct 精确匹配 Routing Key 点对点消息(如订单处理)
Topic 通配符匹配 Routing Key(* 和 #) 分类消息广播(如日志分类)
Fanout 忽略 Routing Key,广播到所有队列 全局通知(如系统配置更新)
Headers 基于消息头键值对匹配 复杂路由逻辑(较少使用)

三、消息机制

5. RabbitMQ 如何保证消息不丢失?

答案:

  • 生产者确认模式(Publisher Confirm):确保消息到达 Broker。
  • 消息持久化:Exchange、Queue 和消息均设置为持久化(durable=true)。
  • 消费者手动应答(Manual Acknowledgement):消息处理完成后发送 ACK。

6. 什么是死信队列(Dead Letter Queue, DLQ)?如何触发?

答案:
死信队列用于存储无法被正常消费的消息。触发条件:

  1. 消息被消费者拒绝(basic.reject 或 basic.nack)且不重新入队。
  2. 消息 TTL(存活时间)过期。
  3. 队列达到最大长度限制。

四、高级特性

7. 如何实现延迟队列?

答案:
RabbitMQ 原生不支持延迟队列,但可通过以下方式实现:

  1. 消息 TTL + 死信队列:设置消息的 TTL,过期后转发到 DLQ。
  2. 插件(如 rabbitmq-delayed-message-exchange):使用延迟交换机。

8. 如何避免消息重复消费?

答案:

  • 幂等性设计:业务逻辑天然支持重复处理(如数据库唯一约束)。
  • 去重表:记录已处理消息的唯一标识(如消息 ID)。
  • Redis 分布式锁:在消费前加锁。

五、可靠性与性能

9. RabbitMQ 的集群模式有哪些?

答案:

  • 普通集群:队列元数据同步,但消息存储在单个节点(无高可用)。
  • 镜像队列(Mirrored Queues):队列数据跨节点复制,实现高可用。

10. 如何提升 RabbitMQ 的吞吐量?

答案:

  • 批量发送(Batch Publish)。
  • 多线程 Channel(避免单 Channel 阻塞)。
  • 优化 ACK 机制:批量确认或异步确认。
  • 调整预取数量(prefetchCount)提升消费者并发能力。

六、实战场景

11. 如何保证消息顺序性?

答案:

  • 单队列单消费者:牺牲并发性保证顺序。
  • 消息分组:通过 Routing Key 将需要顺序的消息路由到同一队列。

12. 设计一个秒杀系统时,如何用 RabbitMQ 应对瞬时高并发?

答案:

  • 削峰填谷:将请求写入队列,后端服务按处理能力消费。
  • 队列容量限制:避免内存溢出。
  • 快速失败机制:队列满时直接拒绝新请求。

七、监控与管理

13. 如何监控 RabbitMQ 的运行状态?

答案:

  • 管理界面:通过 Web UI 查看连接、队列、吞吐量等指标。
  • 命令行工具:rabbitmqctl list_queues。
  • Prometheus + Grafana:集成监控告警。

八、对比与其他中间件

14. RabbitMQ 与 Kafka 的核心区别是什么?

答案:

维度 RabbitMQ Kafka
设计目标 消息可靠传输与复杂路由 高吞吐量日志流处理
消息保留 消费后删除 按时间或大小保留
吞吐量 万级 QPS 百万级 QPS
适用场景 业务解耦、延迟消息 日志收集、实时流处理

文档说明

本文档涵盖 RabbitMQ 的核心概念、工作机制及典型应用场景,适用于面试准备或技术方案设计参考。
持续更新建议:结合 RabbitMQ 官方文档(https://www.rabbitmq.com)和实际项目经验补充案例。

PS: 该内容有DeepSeek R1深度学习总结(deepseek牛逼!!!)


使用1Panel作为服务器管理面板

Posted on 2025-01-15

📝记录一下使用1panel作为服务器管理面板,之前基本是使用手搓命令构建服务,了解过宝塔面板,感觉太过臃肿且需要注册账户,后续考虑服务部署都是用1panel面板进行操作。

官方文档:https://1panel.cn/docs/

一、产品介绍

1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。
UI展示

二、安装部署

  1. Ubuntu安装:
1
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh

image-20250115134821023

  1. 通过访问地址和面板用户密码进行登录

三、功能使用

  1. 前端页面创建网址后选择静态网址进行配置,后台选择反向代理

image-20250115140517787

  1. 通过网址设置配置HTTPS和设置NGINX

图像_副本

四、计划任务

可以通过linux定时任务自动执行shell等脚本命令

截屏2025-01-15 14.16.51


Docker搭建和部署禅道

Posted on 2024-10-16

禅道项目管理工具提供了丰富的功能模块,包括任务管理、需求管理、Bug跟踪、版本控制、团队协作、项目报表等,这些功能覆盖了项目管理的各个方面。全面的功能模块使得项目团队可以在一个统一的平台上进行协同工作,无需再整合多个系统,从而提高了工作效率。

公司使用禅道来管理项目需求、进度以及Bug测试,新版禅道添加了很多功能,这里我搭建使用的是老版本12.5.3。

Docker拉取禅道镜像

1
docker pull idoop/zentao:12.5.3

image-20241016134837422

运行禅道容器

1
2
3
4
5
docker run --privileged=true -d -p 8082:80 -p 3316:3306 \
-e ADMINER_USER="admin" -e ADMINER_PASSWD="123456" \
-v /dockerdatafile/chandao/:/opt/zbox/ \
--name zentao-server \
idoop/zentao:12.5.3

参数说明:

  • ADMINER_USER:指定禅道管理员账号

  • ADMINER_PASSWD:指定禅道管理员首次登录密码

访问禅道

浏览器访问宿主机器地址加8082端口,登录使用用户名 admin,密码 123456

image-20241016135156614

使用1Panel创建网站

可通过域名进行访问

image-20241016135651301


Pandas转JSON无法显示中文的问题

Posted on 2024-09-18

问题解释:

在使用pandas转换DataFrame到JSON格式时,如果DataFrame中含有中文字符,可能会遇到无法正确显示中文的问题。这通常是因为默认情况下,pandas会将字符串编码为Unicode Escape形式,这不是JSON的标准格式,而是Python内部的表现形式。

解决方法:

  1. 在转换为JSON之前,确保DataFrame的编码是正确的,通常使用UTF-8编码。

  2. 使用to_json方法时,设置参数ensure_ascii=False,这样可以避免ASCII编码的问题,正确显示中文。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
import pandas as pd

# 创建一个包含中文的DataFrame

df = pd.DataFrame({'data': ['中文内容', '更多中文', '最后一条']})

# 转换为JSON,确保使用utf-8编码,并且不使用ASCII编码

json_str = df.to_json(orient='records', force_ascii=False)

print(json_str)

这段代码会创建一个包含中文的DataFrame,并将其转换为JSON格式,正确显示中文字符。


使用ohttps自动部署https证书

Posted on 2024-08-12

在使用第三方托管网站做个人网站,例如:Github Pages,想要给网站加上https,可以通过ohttps来创建Let’s Encrypt的https证书,单纯想给网站加上https也可以。

安装Nginx

先确保服务器(我这里是win服务器)已经安装了nginx,选择适合自己的版本,然后下载解压到服务器上,双击运行nginx.exe,访问服务器ip地址,出现Welcome to Nginx!则表示安装启动成功。

使用ohttps部署ssl证书

  1. 创建证书

image-20240812124550577

  1. 需要在自己域名管理解析中加入ohttps的记录

image-20240812124657919

  1. 在nginx配置中需要ssl_certificate_key和ssl_certificate

ssl_certificate_key: 私钥文件通常包含与SSL证书配对的私钥,用于加密和解密通信中的数据,文件后缀.key,内容开头—–BEGIN RSA PRIVATE KEY—–

ssl_certificate: SSL证书文件包含用于验证服务器身份的公钥以及相关信息,如服务器的域名和证书颁发机构(CA)的签名,文件后缀为.crt或者是.pem,内容开头—–BEGIN CERTIFICATE—–

image-20240812125505357

下载这两个文件,然后存放到服务器上

配置Nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
worker_processes  1;

events {
worker_connections 1024;
}


http {
server_names_hash_bucket_size 64;
include mime.types;
default_type application/octet-stream;

sendfile on;

keepalive_timeout 65;

#gzip on;

server {
listen 443 ssl;
server_name wechat.ruiyeclub.cn;

ssl_certificate 绝对路径/key/fullchain.pem;
ssl_certificate_key 路径/key/cert.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

server {
listen 80;
server_name wechat.ruiyeclub.cn;

ssl_certificate 绝对路径/key/fullchain.pem;
ssl_certificate_key 路径/key/cert.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}

Nginx常用命令

  • 启动Nginx服务 nginx

  • 停止Nginx服务 nginx -s stop

  • 检测配置文件的正确性 nginx -t

  • 重新加载Nginx配置文件 nginx -s reload

  • 查看Nginx版本信息 nginx -v

  • 平滑停止Nginx服务 nginx -s quit


SpringBoot监听Redis过期key

Posted on 2024-07-25

在SpringBoot项目中配置Redis的过期提醒,通过修改redis.conf或命令行设置notify-keyspace-events,并创建自定义的Redis消息监听器来处理过期事件。

一、开启Redis key过期提醒

  • 方式一:修改redis.conf配置文件
1
2
# 默认 notify-keyspace-events ""
notify-keyspace-events Ex
  • 方式二:命令行开启
1
2
CONFIG SET notify-keyspace-events Ex
CONFIG GET notify-keyspace-events

二、项目导入redis依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

三、配置config配置类

1
2
3
4
5
6
7
8
9
10
@Configuration
public class RedisListenerConfig {

@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}

四、配置监听代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Slf4j
@Component
public class KeyExpiredListener extends KeyExpirationEventMessageListener {

public KeyExpiredListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}

@Override
public void onMessage(Message message, byte[] pattern) {
String channel = new String(message.getChannel(), StandardCharsets.UTF_8);
// 过期的key
String key = new String(message.getBody(), StandardCharsets.UTF_8);
log.info("redis key 过期:pattern={},channel={},key={}", new String(pattern), channel, key);
if (key.equals(INVEST_WS_EXPIRED_KEY)) {
// 处理业务逻辑...
}
}
}

Mac上使用homebrew安装nvm

Posted on 2024-07-20

NVM(Node Version Manager)是一个用于在基于Linux系统上安装和管理Node.js的shell脚本。macOS用户可以使用homebrew来安装NVM。

安装Homebrew(如果你还没有安装):

1
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  1. 卸载现有node版本

如果你的系统已经安装了node,请先卸载它。

1
2
brew uninstall --ignore-dependencies node 
brew uninstall --force node
  1. 使用Homebrew安装nvm:
1
brew install nvm
  1. 将nvm初始化脚本添加到你的shell配置文件中。如果你使用的是zsh,那么你需要在你的~/.zshrc文件中添加以下行:
1
2
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
  1. 使更改生效,你可以重新启动你的终端,或者运行以下命令:
1
source ~/.zshrc
  1. 验证nvm安装成功:
1
nvm --version

以上步骤将会在你的macOS系统上安装nvm,并且设置zsh使其能够识别nvm命令。

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
nvm -v //查看nvm版本
nvm ls //查看本机已经安装node版本
nvm use 切换到指定版本node
nvm ls-remote //列出所有可安装的远程node版本
nvm install stable //安装最新版本
nvm install <version> //安装指定版本
nvm uninstall stable //卸载最新版本
nvm uninstall <version> //卸载指定版本
nvm current //查看当前使用的node版本
npm which [current|<version>] //显示已安装node的安装路径。
nvm cache dir //显示nvm的缓存目录
nvm cache clear //清楚nvm的缓存目录
nvm node_mirror [url] //设置node镜像
nvm npm_mirror [url] //设置npm镜像
nvm on //开启node.js版本管理
nvm off //关闭node.js版本管理


更新npm到最新版本
npm install -g npm@latest

踩坑记录:

终端安装好了nvm和node,但是在vscode打开后无法执行命令,需要在 vi ~/.zshrc加入export PATH="~/.composer/vendor/bin:$PATH"

参考文章:

如何在macOS上安装NVM

Mac下安装nvm后vscode输入node -v不起作用


12…5

  •   GitHub
  •   Ray4j.top
  •   Springboot-Hello
  •    Search
© 2022 — 2025 Cr.    |   
UV PV
TOP