使用nvm管理node多版本(安装、卸载nvm,配置环境变量,更换npm淘宝镜像)

前言
基于 windows环境 使用nvm安装多版本nodejs, 此文章作为记录,并对
参考文章 做些补充
注意: 如果电脑上已经安装了任意node版本,需要将其相关文件及环境变量清理干净后再安装nvm, 保证电脑内没有任何nodejs的残留
一、卸载node
如果已经安装了node,那么在安装nvm之前,需要先卸载node,如果没有安装可以直接跳过这一步到下一步了。
删除前可查当前使用的node版本,方便后续决定使用哪个版本的node。

控制面板 -> 卸载程序 -> 卸载nodejs

为了确保彻底删除node,看下node安装目录中还有没有node文件夹,有的话一起删除。
删除以下文件夹(如果存在的话)

C:\Program Files (x86)\Nodejs
C:\Program Files\Nodejs
C:\Users{User}\AppData\Roaming\npm
C:\Users{User}\AppData\Roaming\npm-cache
删除C:\Users\用户名 下的 .npmrc文件以及 .yarnrc 文件
环境变量中npm、node的所有相关统统删掉

二、nvm是什么?
nvm(node.js version management),是一个nodejs的版本管理工具。nvm和n都是node.js版本管理工具,为了解决node.js 各种版本存在不兼容现象 可以通过它可以安装和切换不同版本的node.js。【可同时在一个环境中安装多个node.js版本(和配套的npm)】

三、nvm安装
1.官网下载 nvm 包
https://github.com/coreybutler/nvm-windows/releases
选最新版本进入即可

  1. 安装nvm-setup.exe

上面nvm和nodejs默认安装地址都是C盘,我们最好换成其他的盘,我是换成D盘。
并且注意安装路径的文件夹名称不要出现中文,空格等,否则后期npm使用的时候会出现符号格式不正确问题。

  1. 配置路径和下载镜像
    安装完 nvm 后来配置一下下载源
    找到nvm安装路径 -> 找到setting.txt文件 -> 将下面文本覆盖上去
    txt 代码解读复制代码root: D:\nvm
    path: D:\nodejs
    node_mirror: https://npmmirror.com/mirrors/node/
    npm_mirror: https://npmmirror.com/mirrors/npm/

第一行是 nvm 安装路径
第二行是 nodejs 路径
第三行是 node 下载镜像
第四行是 npm 下载镜像

  1. 检查安装是否完成
    win+R,调用cmd,输入nvm,如下图则表示安装成功

四、 使用nvm安装node
管理员身份运行终端, 先查询可使用版本号, 终端输入nvm list available, LST代表稳定版本

安装指定node版本

shell 代码解读复制代码nvm install 20.13.1

安装完成后输入use命令指定使用版本

shell 代码解读复制代码nvm use 20.13.1

use完成后可以分别输入命令行 node -v 和 npm -v,检验是否安装成功

nvm list 查看已安装nodejs版本, * 号表示正在使用

删除某nodejs版本

shell 代码解读复制代码nvm uninstall node版本号 //例如:nvm uninstall 16.14.0)即可删除对应版本

五、修改npm默认镜像源为淘宝镜像
shell 代码解读复制代码npm config set registry https://registry.npmmirror.com/

检查是否设置成功, 应该返回 registry.npmmirror.com/
shell 代码解读复制代码npm config get registry

六、环境变量配置

  1. 新建目录

为了防止nvm切换node版本之后全局安装的包无法使用,我们直接在nvm目录下创建"node_cache"和"node_global"文件夹

打开命令行工具, 输入下面两句指令

shell 代码解读复制代码npm config set prefix "D:\nvm\node_global"
npm config set cache "D:\nvm\node_cache"

想查看是否设置成功使用
shell 代码解读复制代码npm config get prefix
npm config get cache

  1. 设置环境变量
    我的电脑右键 -> 属性 -> 高级系统设置 -> 系统属性(高级) -> 环境变量
    如果环境变量未正确配置,输入node -v 会报错,系统将无法正确识别"node"命令。
    需要我们设置的地方有两个:

系统环境变量新增NODE_PATH变量
用户变量修改path变量

在[系统环境变量]新建环境变量NODE_PATH值为D:\nvm\node_global\node_modules

修改[用户变量]中的path变量

另外, 在下载完nvm后, 系统环境变量和用户环境变量会默认配置好NVM_HOME和NVM_SYMLINK

点击确定后配置完成

七、测试安装全局模块
在cmd窗口中输入以下指令全局安装http-server模块, 安装成功就表示环境变量配置成功
sheel 代码解读复制代码npm install http-server -g

八、测试切换node版本全局模块是否存在

当前node版本运行 http-server

切换版本后重新运行

测试完成,可以看到切换node版本后全局模块依然可以使用

SQLServer索引碎片

索引碎片会显著影响查询性能,特别是在高并发和大数据量的环境下。以下是索引碎片对查询性能的具体影响以及解决方案。

索引碎片对查询性能的影响

  1. 增加I/O操作

    • 外部碎片:当索引页在物理存储上不连续时,查询需要访问更多的磁盘块。这增加了I/O操作的次数,导致查询速度变慢。
    • 内部碎片:当数据页中有大量空闲空间时,每个数据页能存储的行数减少,导致需要读取更多的页才能获取所需数据。
  2. 缓存命中率降低

    • 外部碎片:由于数据页不连续,导致更多的数据页需要频繁读取,从而增加了缓存(如SQL Server Buffer Pool)的压力。
    • 内部碎片:数据页存储效率降低,需要更多的缓存空间来存储相同数量的数据,从而减少了缓存命中率。
  3. 查询响应时间增加

    • 扫描操作:当执行全表扫描或索引扫描时,碎片化的索引会导致更多的页面读取,从而增加查询响应时间。
    • 查找操作:即使是基于索引的查找操作,碎片化的索引也会增加随机I/O操作,导致响应时间增加。

检测索引碎片

使用SQL Server提供的动态管理视图来检测索引碎片。

查询索引碎片信息

SELECT
    OBJECT_NAME(A.[OBJECT_ID]) AS [TableName],
    A.[index_id],
    B.[name] AS [IndexName],
    A.[avg_fragmentation_in_percent],
    A.[page_count]
FROM
    sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') AS A
    JOIN sys.indexes AS B ON A.[OBJECT_ID] = B.[OBJECT_ID] AND A.index_id = B.index_id
WHERE
    A.[avg_fragmentation_in_percent] > 10
ORDER BY
    A.[avg_fragmentation_in_percent] DESC;

解决索引碎片问题

根据索引碎片的严重程度,可以选择重组索引或重建索引。

重组索引(REORGANIZE)

适用于碎片率在10%-30%的情况。重组索引是一个轻量级操作,只对外部碎片进行处理,并保持索引在线状态。

ALTER INDEX [IndexName] ON [TableName] REORGANIZE;

重建索引(REBUILD)

适用于碎片率大于30%的情况。重建索引是一个重度操作,会彻底重新创建索引,包括内部和外部碎片。可以选择在线或离线重建索引。

离线重建索引

ALTER INDEX [IndexName] ON [TableName] REBUILD;

在线重建索引(SQL Server企业版支持):

ALTER INDEX [IndexName] ON [TableName] REBUILD WITH (ONLINE = ON);

自动维护索引

为了确保索引保持良好的性能,可以设置自动维护索引的计划任务。

使用维护计划

SQL Server 提供了维护计划向导,可以方便地设置定期重组或重建索引的任务。

自定义脚本

可以创建SQL Server代理作业,使用T-SQL脚本定期检查并修复索引碎片。

CREATE PROCEDURE RebuildReorganizeIndexes
AS
BEGIN
    DECLARE @TableName NVARCHAR(128);
    DECLARE @IndexName NVARCHAR(128);
    DECLARE @Fragmentation FLOAT;
    DECLARE @SQL NVARCHAR(MAX);

    DECLARE IndexCursor CURSOR FOR
    SELECT
        OBJECT_NAME(A.[OBJECT_ID]) AS [TableName],
        B.[name] AS [IndexName],
        A.[avg_fragmentation_in_percent]
    FROM
        sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') AS A
        JOIN sys.indexes AS B ON A.[OBJECT_ID] = B.[OBJECT_ID] AND A.index_id = B.index_id
    WHERE
        A.[avg_fragmentation_in_percent] > 10
    ORDER BY
        A.[avg_fragmentation_in_percent] DESC;

    OPEN IndexCursor;
    FETCH NEXT FROM IndexCursor INTO @TableName, @IndexName, @Fragmentation;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF @Fragmentation > 30
            SET @SQL = 'ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REBUILD;';
        ELSE
            SET @SQL = 'ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REORGANIZE;';

        EXEC sp_executesql @SQL;

        FETCH NEXT FROM IndexCursor INTO @TableName, @IndexName, @Fragmentation;
    END

    CLOSE IndexCursor;
    DEALLOCATE IndexCursor;
END;

示例操作流程

假设你需要在插入40万条数据之后处理索引碎片,以下是一个建议的操作流程:

  1. TRUNCATE TABLE

    TRUNCATE TABLE TargetTable;
  2. 插入数据

    DECLARE @BatchSize INT = 10000;
    DECLARE @InsertedRows INT = 0;
    WHILE @InsertedRows < 400000
    BEGIN
    INSERT INTO TargetTable (columns)
    SELECT TOP (@BatchSize) columns FROM SourceTable
    WHERE condition;
    
    SET @InsertedRows = @InsertedRows + @@ROWCOUNT;
    END
  3. 检测并重组或重建索引

    
    -- 检查索引碎片
    SELECT
    OBJECT_NAME(A.[OBJECT_ID]) AS [TableName],
    A.[index_id],
    B.[name] AS [IndexName],
    A.[avg_fragmentation_in_percent],
    A.[page_count]
    FROM
    sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') AS A
    JOIN sys.indexes AS B ON A.[OBJECT_ID] = B.[OBJECT_ID] AND A.index_id = B.index_id
    WHERE
    A.[avg_fragmentation_in_percent] > 10
    ORDER BY
    A.[avg_fragmentation_in_percent] DESC;

-- 重组或重建索引
DECLARE @TableName NVARCHAR(128);
DECLARE @IndexName NVARCHAR(128);
DECLARE @Fragmentation FLOAT;
DECLARE @SQL NVARCHAR(MAX);

DECLARE IndexCursor CURSOR FOR
SELECT
OBJECT_NAME(A.[OBJECT_ID]) AS [TableName],
B.[name] AS [IndexName],
A.[avg_fragmentation_in_percent]
FROM
sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') AS A
JOIN sys.indexes AS B ON A.[OBJECT_ID] = B.[OBJECT_ID] AND A.index_id = B.index_id
WHERE
A.[avg_fragmentation_in_percent] > 10
ORDER BY
A.[avg_fragmentation_in_percent] DESC;

OPEN IndexCursor;
FETCH NEXT FROM IndexCursor INTO @TableName, @IndexName, @Fragmentation;

WHILE @@FETCH_STATUS = 0
BEGIN
IF @Fragmentation > 30
SET @SQL = 'ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REBUILD;';
ELSE
SET @SQL = 'ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REORGANIZE;';

EXEC sp_executesql @SQL;

FETCH NEXT FROM IndexCursor INTO @TableName, @IndexName, @Fragmentation;

END

CLOSE IndexCursor;
DEALLOCATE IndexCursor;



### 总结

索引碎片会显著影响查询性能,通过定期检测和修复索引碎片,可以提升数据库的查询性能。重组索引和重建索引是常用的解决方法。合理安排索引维护任务,并自动化这些任务,有助于保持索引的高效状态,确保数据库查询性能的稳定和优化。

Jenkins 中配置 GitLab

要在 Jenkins 中配置 GitLab 并指定 branch 代码,你需要完成以下步骤:

  1. 安装 GitLab 插件:

    • 进入 Jenkins 的管理界面,点击“Manage Jenkins”。
    • 点击“Manage Plugins”。
    • 在“Available”选项卡中搜索“GitLab Plugin”,勾选后点击“Install without restart”。
  2. 配置 GitLab 服务器:

    • 回到“Manage Jenkins”,点击“Configure System”。
    • 滚动到“GitLab”部分,点击“GitLab connections...”
    • 添加 GitLab 服务器的 URL 和 API Token。可以通过 GitLab 的“User Settings” > “Access Tokens”生成 API Token。
    • 测试连接是否成功。
  3. 创建 Jenkins 任务:

    • 在 Jenkins 主界面,点击“New Item”。
    • 输入任务名称,选择“Freestyle project”或“Pipeline”。
    • 点击“OK”创建任务。
  4. 配置任务的 GitLab 仓库:

    • 在任务配置页面,找到“Source Code Management”部分。
    • 选择“Git”。
    • 在“Repository URL”中输入 GitLab 仓库的 URL。例如:https://gitlab.com/username/repo.git
    • 在“Credentials”中添加之前配置的 GitLab 凭据。
  5. 指定分支:

    • 在“Branch Specifier (blank for 'any')”中输入你想要构建的分支名称,例如:*/main*/feature-branch
  6. 设置构建触发器:

    • 在“Build Triggers”部分,你可以选择如何触发构建。
    • 可以选择“GitLab hook trigger for GITScm polling”来使 GitLab Webhook 触发构建。
    • 也可以使用“Poll SCM”选项,根据时间间隔进行轮询。
  7. 配置 Webhook:

    • 登录 GitLab,进入对应的项目。
    • 点击左侧菜单中的“Settings”,然后选择“Webhooks”。
    • 在“URL”中输入 Jenkins 的 URL,例如:http://your-jenkins-server/gitlab/build_now/
    • 在触发器部分,勾选“Push events”和“Merge Request events”。
    • 点击“Add Webhook”。
  8. 保存并运行:

    • 完成上述配置后,点击“Save”保存任务配置。
    • 可以手动点击“Build Now”来测试配置是否成功。

如果配置正确,当你向指定的 branch 推送代码或创建合并请求时,Jenkins 应该会自动触发构建。

CentOS 上配置多个 SSH 端口

在 CentOS 上配置监控多个 SSH 端口,可以使用以下步骤:

  1. 修改 SSH 配置文件:

    • 编辑 /etc/ssh/sshd_config 文件以允许 SSH 服务监听多个端口。例如,如果你想让 SSH 服务监听 22 和 2222 端口,可以添加以下行:
      Port 22
      Port 2222
    • 保存并关闭文件。
  2. 重启 SSH 服务:

    • 使更改生效,重启 SSH 服务:
      sudo systemctl restart sshd
  3. 确保防火墙允许这些端口:

    • 使用 firewalld 管理防火墙规则,确保防火墙允许新的 SSH 端口。
    • 例如,允许 22 和 2222 端口:
      sudo firewall-cmd --permanent --add-port=22/tcp
      sudo firewall-cmd --permanent --add-port=2222/tcp
      sudo firewall-cmd --reload
  4. 安装监控工具:

    • 你可以使用 NagiosZabbixPrometheus 等监控工具来监控这些端口。
    • 这里我们以 Nagios 为例。首先,安装 NagiosNagios Plugins
      sudo yum install epel-release -y
      sudo yum install nagios nagios-plugins-all nagios-plugins-nrpe nrpe -y
  5. 配置 Nagios 服务:

    • 编辑 /etc/nagios/nagios.cfg 文件,确保包含配置目录:
      cfg_dir=/etc/nagios/conf.d
    • 创建一个新的配置文件来监控 SSH 端口,例如 /etc/nagios/conf.d/ssh_ports.cfg
      sudo nano /etc/nagios/conf.d/ssh_ports.cfg
  6. 在配置文件中添加服务检查:

    • 添加以下内容来监控端口 22 和 2222:
      
      define service {
      use generic-service
      host_name localhost
      service_description SSH Port 22
      check_command check_tcp!22
      }

define service {
use generic-service
host_name localhost
service_description SSH Port 2222
check_command check_tcp!2222
}


7. **重启 Nagios 服务:**
- 保存文件后,重启 Nagios 服务:
```bash
sudo systemctl restart nagios
  1. 访问 Nagios Web 界面:
    • 确保 Apache HTTP Server 正在运行:
      sudo systemctl start httpd
      sudo systemctl enable httpd
    • 访问 Nagios Web 界面,通常为 http://your-server-ip/nagios。默认用户名是 nagiosadmin,密码是在安装过程中设置的。

通过以上步骤,你就可以在 CentOS 上配置和监控多个 SSH 端口。

在php8 中+/-优先级高于php连接符,需要用括号来强制分隔

使用 strtotime() 时,使用了+ 号报错。错误信息为

The behavior of unparenthesized expressions containing both '.' and '+'/'-' will change in PHP 8: '+'/'-' will take a higher precedence
strtotime( "+" . $i-$week .' days', $time)
应该修改为
strtotime( "+" . ($i-$week) .' days', $time)

在php8 中+/-的优先及要高于php 连接符。所以这里使用括号来强制分隔避免意想不到的问题。

php向redis list一次性lPush多个值

php redis扩展没有介绍向list中一次性push多个值的用法,但其实lPush和rPush是支持push多个值的,文档中有介绍

lPush - Prepend one or multiple values to a list

rPush - Append one or multiple values to a list

用法也很简单,看示例代码:

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->del('foo');
var_dump($redis->lPush('foo', 'aaaa', 'bbbb', 'cccc', 'dddd'));
print_r($redis->lRange('foo', 0, -1));

运行结果:

int(4)
Array
(
[0] => dddd
[1] => cccc
[2] => bbbb
[3] => aaaa
)

但更多时候我们是希望lPush一个数组,但lPush不支持直接传入数组,但我们可以使用以下两种方式来实现:

    1. 利用 call_user_func_array 可以使用数组来当参数列表的特性:

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->del('foo');
var_dump(call_user_func_array([$redis, 'lPush'], ['foo', '1111', '2222', '3333', '4444']));
print_r($redis->lRange('foo', 0, -1));

执行结果

int(4)
Array
(
[0] => 4444
[1] => 3333
[2] => 2222
[3] => 1111
)

2. 使用 php5.6+ 支持的可变参数,在数组前加 '...' 实现把数组当作函数的参数列表You can also use ... when calling functions to unpack an array or Traversable variable or literal into the argument list:

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->del('foo');
var_dump($redis->lPush('foo', ...['AAAA111', 'BBBB222', 'CCCC333', 'DDDD444']));
print_r($redis->lRange('foo', 0, -1));

运行返回

int(4)
Array
(
[0] => DDDD444
[1] => CCCC333
[2] => BBBB222
[3] => AAAA111
)

 

一般推荐第二种方式

Java URIBuilder的使用记录

import org.apache.http.client.utils.URIBuilder;

URIBuilder uriBuilder = new URIBuilder(location);

uriBuilder.setParameters  添加参数,会覆盖重复的

uriBuilder.addParameters 添加参数,不会覆盖重复的

uriBuilder.build() 会将拼接好的接口地址输出

和PHP  http_build_query有异曲同工之妙

openssl生成RSA格式的公私钥,并转为pkcs8格式

第一步:生成私钥,这里我们指定私钥的长度为2048

openssl genrsa -out private.pem 2048

第二步:根据私钥生成对应的公钥:

openssl rsa -in private.pem -outform PEM -pubout -out public.pem

第三步:私钥转化成pkcs8格式,【这一步非必须,只是程序解析起来方便】,尖括号的意思是:将转化好的私钥写到private_pkcs8.pem文件里

openssl pkcs8 -topk8 -inform PEM -in private.pem -outform PEM -nocrypt > private_pkcs8.pem