0%

目录

redis-token缓存
jwt跟redis存token的区别
redis相关知识
推荐

redis-token缓存

  • redis.js创建

    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
    const redis = require("redis");

    // Redis 链接的配置内容
    const client = redis.createClient({
    socket: {
    host: '192.168.64.2', // Redis 服务器地址
    port: 6379, // Redis 端口
    },
    password: '123456' // Redis 密码
    });

    // 连接到 Redis
    client.connect()
    .then(() => {
    console.log('Connected to Redis');
    })
    .catch((err) => {
    console.error('Redis connection failed:', err);
    });

    // 处理连接错误
    client.on("error", (err) => {
    console.error('Redis error:', err);
    });

    // 定义 Redis 操作方法
    const redisOps = {
    // 创建值
    set: async (key, value, expiration = null) => {
    try {
    value = JSON.stringify(value);
    if (Number.isInteger(expiration) && expiration > 0) {
    // 如果设置了有效时间并且是整数,使用 SETEX 命令
    await client.setEx(key, expiration, value);
    } else {
    // 否则直接使用 SET 命令
    await client.set(key, value);
    }
    console.log(`Key "${key}" set successfully with expiration: ${expiration || 'no expiration'}`);
    } catch (err) {
    console.error('Error setting value:', err);
    }
    },

    // 删除值
    del: async (key) => {
    try {
    await client.del(key);
    console.log(`Key "${key}" deleted successfully`);
    } catch (err) {
    console.error('Error deleting key:', err);
    }
    },

    // 获取值
    get: async (key) => {
    const result = await client.get(key);
    console.log('99999=', result)
    try {
    return result; // 尝试解析为 JSON
    } catch (error) {
    // 如果不是 JSON 格式,直接返回原始值
    console.warn(`Warning: Value for key "${key}" is not JSON formatted.`);
    return result;
    }
    },

    // 获取键的 TTL
    ttl: async (key) => {
    try {
    const timeLeft = await client.ttl(key);
    console.log(`Key "${key}" has TTL: ${timeLeft}`);
    return timeLeft;
    } catch (err) {
    console.error('Error getting TTL:', err);
    return err;
    }
    },
    };

    module.exports = redisOps;

  • redis的使用

1
2
3
4
5
6
const redisOps = require("./redis.js");
const moment = require('moment-timezone');

let token = jwt.sign({ id: user.userid, username: user.username }, secretKey, { expiresIn: '1h' });

await redisOps.set(user.userid.toString(), token, 60 * 60)
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
//token校验
const verifyToken = async (ctx, next) => {
const userid = ctx.headers['cookie'];
const match = userid.match(/userid=(\d+)/);
const userId = match ? match[1] : null;

if (!userId) {
ctx.status = 401;
console.log('No token provided');
ctx.body = { message: 'No token provided' };
return;
}

try {
const startTime = moment(); // 记录开始时间
const getuserid = await redisOps.get(userId)
const endTime = moment(); // 记录结束时间
const duration = moment.duration(endTime.diff(startTime)); // 计算持续时间

console.log(`Request completed in ${duration.asMilliseconds()} ms`); // 以毫秒为单位输出耗时
if(getuserid){
await next();
}else {
throw err;
}

} catch (err) {
console.log('Token verification failed:', err.message);
ctx.status = 401;
ctx.body = { message: 'Failed to authenticate token' };
}
};

jwt跟redis存token的区别

维度 JWT Redis
性能 - 无需查询数据库或访问外部存储,验证速度较快
- 适用于简单的身份验证场景
- 需要与 Redis 服务器进行通信,可能会有网络延迟
- 适用于复杂的会话管理和存储需求

redis相关知识

  • redis本质上是一个key-value类型的内存数据库,性能最快的key-value数据库。

  • 正常情况是把数据存储在数据库 ,数据库把数据存在磁盘。但越上层的存储器存储效率越高,内存位于磁盘之上。而redis是一款基于内存的存储系统,数据都存在内存里,所以从redis读取数据会比从数据库读取要快。

  • 内存有限,存储不了太多数据。出现故障时,用主从复制、哨兵法。集群就是一套完整的redis多机解决方案。他有效解决了单机redis的所有问题。当你在集群中为某个节点配置从机的时候,主从节点间同步就是主从复制。主节点挂掉之后,从节点的选取,内部逻辑与哨兵机制相似。

  • 支持发布/订阅模式,可以作为一个简单而高效的轻量级消息代理,用于实现消息队列、实时通知等。

使用 Docker 安装 ELK Stack(ElasticSearch、Logstash、Kibana)

建议在 Docker 上安装,资源占用少。以下安装版本统一为 8.12.2,建议保持一致避免冲突。

目录

1、安装 ElasticSearch
2、安装 Logstash
3、安装 Kibana
推荐


1、安装 ElasticSearch

  • 拉取镜像:
1
docker pull elasticsearch:8.12.2
  • 启动容器:
1
docker run --name some-elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -d elasticsearch:8.12.2
  • 进入容器内部:
1
sudo docker exec -u 0 -it some-elasticsearch bash
  • 重启容器:
1
docker restart some-elasticsearch

2、安装 Logstash

  • 拉取镜像:
1
docker pull docker.elastic.co/logstash/logstash:8.12.2
  • 启动容器:
1
sudo docker run -it -p 5044:5044 -p 9600:9600 --name logstash -v /usr/share/logstash/piplines:/usr/share/logstash/config --privileged=true docker.elastic.co/logstash/logstash:8.12.2 /bin/bash
  • 使用 scp 命令将本机下载好的 jar 包(MySQL Connector)上传至虚拟机:
1
scp "/Users/Downloads/logstash-8.12.2/mysql-connector-j-8.4.0.jar" 用户名@虚拟机IP:/home
  • 再将 jar 包从虚拟机移动到 logstash 容器中:
1
docker cp ./mysql-connector-j-8.4.0.jar logstash:/usr/share/logstash
  • 进入容器内部:
1
docker exec -u 0 -it logstash bash

3、安装 Kibana

  • 拉取镜像:
1
docker pull kibana:8.12.2
  • 启动容器:
1
docker run --name some-kibana -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -d elasticsearch:8.12.2
  • 进入容器:
1
docker exec -u 0 -it some-kibana bash

附:安装 Docker、Portainer 及相关命令

1
2
3
4
5
6
7
8
9
10
11
12
sudo apt update
sudo apt install docker.io docker-compose
docker -v
sudo systemctl start docker

sudo docker search portainer
docker pull portainer/portainer
sudo docker pull portainer/portainer
sudo docker run -d --name portainerUI -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer

sudo docker start portainerUI
sudo passwd root

前端项目 GitLab CI/CD 持续集成部署指南(Mac 环境)

概要

在日常开发过程中,我们经常需要将打包后的 dist 包手动发送给后端部署,效率低且容易出错。CI(Continuous Integration,持续集成)可以自动化这一过程,本文将介绍如何通过 GitLab CI 实现持续集成部署。


一、安装 GitLab Runner

请参考官方文档:GitLab Runner 安装指南


二、本地注册 Runner

  1. 打开你的 GitLab 项目页面,进入 Settings → CI/CD,展开 Runners 部分。
  2. 记住显示的 URLtoken,用于后续注册。

执行注册命令

1
gitlab-runner register

按照提示依次输入以下信息:

  • GitLab CI Coordinator URL: https://gitlab.com
  • GitLab CI Token: xxx(从项目中复制)
  • Tags: my-tag,another-tag(自定义)
  • Description: my-runner(自定义)
  • Executor: shell(Mac 上建议选择 shell)

注册完成后,回到 GitLab CI/CD 设置页面,可看到 Runner 状态为绿色,说明已成功运行。如果不是绿色,请执行以下命令启动 Runner 服务:

1
gitlab-runner run

三、编写 .gitlab-ci.yml 文件并提交

将以下内容保存为 .gitlab-ci.yml,并 push 到 GitLab:

1
2
3
4
5
6
7
8
9
10
11
stages:
- deploy

deploy_to_test:
stage: deploy
script:
- yarn
- rm -rf dist/
- yarn build
- ls -l -t ./dist/
- rsync -avz ./dist/ root@xxx.xx.xx.xxx:/dist
  • 这段 CI 脚本会自动打包项目,并使用 rsyncdist 目录部署到远程服务器。

四、通过 Docker 实现 CI(可选)

如果需要通过 Docker 实现更完整的 CI/CD 流程,继续以下步骤:

1. 安装 Docker(Mac)

1
brew install --cask docker

2. 拉取 GitLab 镜像

1
docker pull drud/gitlab-ce:v0.29.1

3. 创建 GitLab 容器

1
docker run -d -p 8443:443 -p 8090:80 -p 8022:22 --restart always --name gitlab drud/gitlab-ce:v0.29.1

说明:

  • -p 8443:443:映射 HTTPS 端口
  • -p 8090:80:映射 HTTP 端口
  • -p 8022:22:映射 SSH 端口
  • --restart always:容器崩溃或主机重启时自动恢复
  • --name gitlab:容器命名为 gitlab

访问地址:

1
http://localhost:8090/

五、Docker 模式下的 .gitlab-ci.yml 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
variables:
TEST_NAME: "tips"
OUT_PORT: "8081"
IN_PORT: "8081"

stages:
- deploy

deploy_to_test:
stage: deploy
before_script:
- if [ $(docker ps -aq --filter name=$CI_PROJECT_NAME) ]; then docker rm -f $CI_PROJECT_NAME; fi
script:
- docker build -f Dockerfile -t $TEST_NAME:latest .
- docker run -d -p $OUT_PORT:$IN_PORT --name $TEST_NAME $TEST_NAME:latest

部署成功后,在 GitLab 的 CI/CD Pipelines 页面可看到构建过程,在 Containers 页面会生成新容器,点击对应端口即可访问部署后的页面。