JoyLau's Blog

JoyLau 的技术学习与思考

背景

有时服务器断电后再开机启动需要启动一些服务,除了正常的 rc 命令可以实现外,之前我常用的是 systemctl service, 今天发现 crontab 的 reboot 标签也可以实现

使用

crontab -e

1
2
3
4
# 启动后 120 秒启动 canal adapter
@reboot sleep 120; cd /data/msmp-service/canal/canal.adapter-1.1.5/bin && sh restart.sh

@reboot sleep 600; cd /data/gateway && sh handler.sh restart

保存后即可生效

一般情况下,我会 sleep 一段时间再启动服务,因为要等其他 systemd 服务启动完成,比如数据库服务

查看证书有效期

kubeadm alpha certs check-expiration

更新证书,如果是HA集群模式,所有master需要执行

kubeadm alpha certs renew all

证书过期kubectl命令无法使用

cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config

查看 kubectl 命令是否可用

如果不可用的话,使用下面命令重启 kube-apiserver, kube-controller-manager, kube-scheduler、etcd

docker ps | grep -v pause | grep -E "etcd|scheduler|controller|apiserver" | awk '{print $1}' | awk '{print "docker","restart",$1}' | bash

脚本

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
92
93
94
95
96
97
98
99
100
101
102
103
104
/* 
* typora插入图片调用此脚本,上传图片到 MinIO
*/

const path = require('path')
// minio for node.js
const Minio = require('minio')
const { promises } = require('fs')

const endPoint = "xxxx"
const port = xxxx
const accessKey = "xxxx"
const secretKey = "xxxx"
const bucketName = "typora"
const filePath = new Date().getFullYear() + "-" + (new Date().getMonth() + 1) + "/" + new Date().getDate()


// 解析参数, 获取图片的路径,有可能是多张图片
const parseArgv = () => {
const imageList = process.argv.slice(2).map(u => path.resolve(u))
console.info("选择的文件列表:", imageList)
return imageList
}
// 永久地址的策略
const policy = () => {
return {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"*"
]
},
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket",
"s3:ListBucketMultipartUploads"
],
"Resource": [
"arn:aws:s3:::" + bucketName
]
},
{
"Effect": "Allow",
"Principal": {
"AWS": [
"*"
]
},
"Action": [
"s3:ListMultipartUploadParts",
"s3:PutObject",
"s3:AbortMultipartUpload",
"s3:DeleteObject",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::" + bucketName + "/*"
]
}
]
}
}

// 入口
const uploadImageFile = async (imageList = []) => {
// 创建连接
const minioClient = new Minio.Client({
endPoint: endPoint,
port: port,
useSSL: false,
accessKey: accessKey,
secretKey: secretKey
})
// 判断桶是否存在
minioClient.bucketExists(bucketName, function (err, exists) {
if (!exists) {
// 创建桶
minioClient.makeBucket(bucketName, '', function (err) {
if (err) throw err
// 设置桶策略
minioClient.setBucketPolicy(bucketName, JSON.stringify(policy()), function (err) {
if (err) throw err
})
})
}
// 开始上传图片
imageList.map(image => {
// 图片重命名
const name = `${Date.now()}${path.extname(image)}`
// 将图片上传到 bucket 上
minioClient.fPutObject(bucketName, filePath + "/" + name, image, {}, function(info) {
const url = `http://${endPoint}:${port}/${bucketName}/${filePath}/${name}`
// Typora会提取脚本的输出作为地址,将markdown上图片链接替换掉
console.log(url)
})
})
})
}

// 执行脚本
uploadImageFile(parseArgv())

在该脚本目录下执行
npm intsall minio

配置

在脚本中配置 MinIO 服务端的配置项

在 Typora 进行如下配置

image-20220318152717467

该脚本支持

  • 自动创建 bucket
  • 多文件批量上传

导出主库全部数据

mysqldump -A -F --single-transaction --master-data=1 > /tmp/full.sql

-A: 导出全部数据
-F: 同参数–flush-logs, dump 前生成新的 bin log 日志
–master-data=1:参数会在 sql 中打印出 binlog 的信息

例如:
CHANGE MASTER TO MASTER_LOG_FILE='binlog.000248', MASTER_LOG_POS=156;

当指定为 2 时,改行为注释的情况,为 1 时不注释
这时就相当于改变了从主库读取 binlog 的文件和位置信息,
之后将导出的数据导入从库

mysql -p < /tmp/full.sql

耐心的等待

完成后查看从节点的信息:

show slave status;

主要看 Master_Log_File 和 Read_Master_Log_Pos 的数据是否和上面的一致

此时再开启主从同步

start slave ;

完成;

查看信息

使用 choose 标签

1
2
3
4
5
6
7
8
<choose>
<when test="isReSend">
and (info.batchId is not null)
</when>
<otherwise>
and (info.batchId = '' or info.batchId is null)
</otherwise>
</choose>

或者

1
2
3
4
5
6
7
8
<choose>
<when test="isReSend==true">
and (info.batchId is not null)
</when>
<otherwise>
and (info.batchId = '' or info.batchId is null)
</otherwise>
</choose>

按照晚上的教程,配置了
JAVA_TOOL_OPTIONS=”-Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8”
和 LANG=C.UTF-8

这些都没有解决问题

问题解决

主要问题是主节点配置连接从节点的账号 jenkins 没有初始化环境变量
查看从节点的系统信息,可以看到 file.encoding 是 ASNI 编码
解决办法就是新建一个用户使用 -d 指定 home 目录,

useradd -d /home/jenkins jenkins

目的是为了生成 .bashrc .bash_logout .bash_profile 三个文件,将这 3 个文件拷贝到 Jenkins 的home 目录下并授权, 就解决了
再去看从节点的 file.encoding 已经变成 UTF-8 了

使用 @ConfigurationProperties(prefix = "xxxx") 注解配置类

在 Nacos 配置中心里修改相应的配置会自动的刷新属性(配置类上不需要注解 @RefreshScope)

还可以通过发送 POST 请求手动刷新 /actuator/refresh 配置

修改保存后会发现日志打印出如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
2021-09-29 01:02:22.081 INFO [etc-gateway,,] 2664 --- [xxx_6101] c.a.n.client.config.impl.ClientWorker : [fixed-xxxx_6101] [polling-resp] config changed. dataId=etc-gateway.yaml, group=DEFAULT_GROUP
2021-09-29 01:02:22.081 INFO [etc-gateway,,] 2664 --- [xxx_6101] c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[etc-gateway.yaml+DEFAULT_GROUP]
2021-09-29 01:02:22.129 INFO [etc-gateway,,] 2664 --- [xxx_6101] c.a.n.client.config.impl.ClientWorker : [fixed-xxx_6101] [data-received] dataId=etc-gateway.yaml, group=DEFAULT_GROUP, tenant=null, md5=5b9beb32de2d18493f8f840ecdabc9d5, content=spring:
application:
name: etc-gateway
profiles:
include: base
cloud:
gateway:
..., type=yaml

2021-09-29 01:02:23.891 INFO [etc-gateway,,] 2664 --- [xxx_6101] o.s.c.e.event.RefreshEventListener : Refresh keys changed: [swagger.production]

这里记录我遇到的坑:
控制台打印:

1
2
3
4
2021-09-29 01:06:18.896 INFO [etc-gateway,,] 3640 --- [xxx_6101] c.a.nacos.client.config.impl.CacheData : [fixed-xxx_6101] [notify-context] dataId=etc-gateway.yaml, group=DEFAULT_GROUP, md5=4c20b06be83314e17467d3f41d821094
2021-09-29 01:06:19.293 WARN [etc-gateway,,] 3640 --- [xxx_6101] c.a.c.n.c.NacosPropertySourceBuilder : Ignore the empty nacos configuration and get it based on dataId[null.yaml] & group[DEFAULT_GROUP]
2021-09-29 01:06:19.329 WARN [etc-gateway,,] 3640 --- [xxx_6101] c.a.c.n.c.NacosPropertySourceBuilder : Ignore the empty nacos configuration and get it based on dataId[null-base.yaml] & group[DEFAULT_GROUP]

这里说明没有正确读到 application.name
在 bootstrap.yml 配置文件里正确配置

1
2
3
spring:
application:
name: etc-gateway

即可

我这里 bootstrap.yml 配置时多个项目公用的,可以配置环境变量 -Dspring.application.name=etc-gateway

配置 https:

1
2
3
4
5
6
7
8
listen       80 ssl;
ssl_certificate /etc/nginx/conf.d/epark.ahhtk.com.pem;
ssl_certificate_key /etc/nginx/conf.d/epark.ahhtk.com.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
#表示使用的加密套件的类型。
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #表示使用的TLS协议的类型。
ssl_prefer_server_ciphers on;

正常情况下使用 80 和 443 端口实现 http 自动跳转 https 的话配置:

1
2
3
4
5
6
7
8
server {
listen 80;
server_name yourdomain.com; #需要将yourdomain.com替换成证书绑定的域名。
rewrite ^(.*)$ https://$host$1; #将所有HTTP请求通过rewrite指令重定向到HTTPS。
location / {
index index.html index.htm;
}
}

如果不是正常的端口的话,注释掉上面的 rewrite 配置,新增如下配置即可

error_page 497 301 https://$http_host$request_uri;

0%