执子之手

与子偕老


  • 首页

  • 分类

  • 归档

  • 标签

  • 关于

  • 搜索
close

无损扩容Linux磁盘分区容量

时间: 2022-12-01   |   分类: 运维     |   评论:  0    |   访问: 0

1. 背景

公司有台虚拟机,当初安装的时候给的磁盘容量偏小(80G),最近频繁报磁盘空间不足。因为上面跑了比较重要的服务,没有办法重装,只好考虑如何扩容。物理机上面的空闲空间还比较多,通过虚拟机管理软件修改了虚拟机的配置,很容易的把虚拟磁盘容量调大了,调整到了215G。

虚拟磁盘调整后,就需要在Linux系统中进行扩容操作。扩容主要有两步工作要做:

  1. 调整分区大小:将新增的空间添加到分区内容;需要用到工具parted;
  2. 调整文件系统大小:分区容量扩大后,使用resize2fs命令将文件系统扩容到整个磁盘容量。

备注:当时分区的时候没有选择LVM管理,如果使用LVM管理可以通过lvextend命令进行分区的扩容,具体方法参考附录中的链接。

阅读全文 »

奇怪现象:两个Consumer消费同一个分区(Partition)

时间: 2022-05-27   |   分类: 开发     |   评论:  0    |   访问: 0

最近生产上碰到一个奇怪的问题,现场人员反馈Kafka工作不正常。经过开发人员检查,发现一个奇怪的现象:线上两台服务器竟然在同时消费一个Kafka Topic中的一个分区(Partition)。

1. 背景

我们的程序要实现的功能是这样的:系统会定时扫描库存表,根据库存情况决定是否要执行出库操作。之前是采用定时任务处理,执行策略是1分钟一次,为了防止多台服务器并发执行,使用Quartz集群模式确保定时任务只在一台服务器上执行。最近客户提出需求,某些时候客户希望响应更及时一些,譬如某项请求到达的时候,就要立即检查库存并决定是否需要出库。因此,开发人员对系统进行了调整,改为使用Kafka Consumer来触发扫描库存动作;定时任务和接口处同时负责发送触发库存扫描的消息。

相关的代码如下:

Consumer用来处理扫描库存的功能:

 1public class LibraryOutboundTriggerConsumer {
 2    private final OutboundService outboundService;
 3    private final BoxInfoService boxInfoService;
 4
 5    @KafkaListener(topics = "${fwm.core.topic.library-outbound-trigger}")
 6    public void consume(ConsumerRecord<String, String> record) {
 7        log.info("\n\n");
 8        log.info("=====================开始执行出库扫描=====================");
 9        if (boxInfoService.hasBoxUpdateTask()) {
10            log.info("=====================存在料箱更新任务,执行出库扫描结束=====================");
11            return;
12        }
13        Stopwatch stopwatch = Stopwatch.createStarted();
14        try {
15            boxInfoService.startOutboundTask(90);
16            outboundService.outboundTaskScan();
17        } finally {
18            boxInfoService.stopOutboundTask();
19        }
20
21        log.info("=====================执行出库扫描结束,总耗时{}ms=====================", stopwatch.elapsed(TimeUnit.MILLISECONDS));
22    }
23}
阅读全文 »

Flex布局添加滚动条需要注意的规则

时间: 2022-03-02   |   分类: 开发     |   评论:  0    |   访问: 0

好久不写前端代码了,有些生疏了。最近用Electron写了一个客户端程序,碰到了Flex布局添加滚动条的问题,耗费了不少时间,所以总结一下要点:

  1. 根据滚动条的方向,确定好父元素的flex-flow方向: 如果要设置水平滚动条,那么父元素的flex-flow要设置为row;如果要设置纵向滚动条,那么父元素的flex-flow要设置为column。
  2. 元素本身flex设置为1;
  3. 滚动方向的大小(宽度或者高度)设置为0,非滚动方向大小设置为100%或者一个你喜欢的宽度;
  4. 如果元素本身还有子元素,需要特别注意子元素的高度需要设置为100%。如果没有设置,则会导致子元素本身的高度不受限制,从而撑爆了元素本身。

特别需要注意的就是第4点:布局的时候经常使用到el-row/el-col,其最后生成的html代码就会出现嵌套的div组合,是一个典型的父子结构。这时就要注意在el-col上设置相应的高度为100%,否则就会出现撑爆了的结果。

下面是最终的代码,相关要点添加了注释:

阅读全文 »

RSA证书格式

时间: 2021-11-26   |   分类: 开发     |   评论:  0    |   访问: 0

1. TL;DR

  • # -----BEGIN CERTIFICATE----- 开头的是证书。
  • # -----BEGIN RSA PRIVATE KEY----- 开头是遵循的PKCS#1规范,其内容只是一个RSA私钥。它本质上只是来自PKCS#8的关键对象,但前面没有版本或算法标识符。
  • # -----BEGIN PRIVATE KEY----- 开头遵循的是PKCS#8规范,并指示密钥类型包含在密钥数据本身中。
阅读全文 »

Jenkins工作空间页面崩溃问题解决

时间: 2021-10-22   |   分类: 运维     |   评论:  0    |   访问: 0

1. 问题

最近发现一个问题:在 Jenkins 中打开某些项目的工作空间(WorkSpace)的时候,页面会崩溃,显示如下的错误信息:

查看 Jenkins 日志发现如下错误信息,提示的是路径无效错误(InvalidPathException),该目录应该是中文名字,猜测是编码转换出了错误。

2. 解决

由于是使用 Docker 运行的 Jenkins,登录进 Jenkins 容器内部,查看对应的目录:

发现在容器内部看到的目录就是乱码了。而在外部环境可以正常显示目录:

阅读全文 »

Vue进行条件编译发布

时间: 2021-09-24   |   分类: 开发     |   评论:  0    |   访问: 0

最近碰到一个问题:公司新申请了一个公众号,这个新公众号的功能与之前一个公众号功能基本一致,只是两个公众号的用户协议有些区别,所以就会公用一份代码。现在需要解决发布的问题,需要确保发布到两个不同公众号的页面是正确的,不同公众号的用户看到正确的用户协议。

经过上网查找方案,发现 Vue 脚手架中提供的 vue-cli-service 内置了类似的功能,可以用来实现类似功能,这里简单说一下其涉及到的改动要点,更多细节可以参考vue-cli的文档模式和环境变量。

阅读全文 »

MySQL如何保存emoji字符

时间: 2021-07-22   |   分类: 开发     |   评论:  0    |   访问: 0

1. 问题

1.1 发现问题

最近生产环境日志中报了一个异常:

 12021-07-11 20:54:41.632 ERROR 26289 --- [XNIO-1 task-11] c.e.t.s.t.mp.WxMpMessageRouterService    :
 2### Error updating database.  Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\xA6\x84' for column 'NICK_NAME' at row 1
 3### The error may exist in com/eveus/tap/account/mapper/AccountMapper.java (best guess)
 4### The error may involve com.eveus.tap.account.mapper.AccountMapper.insert-Inline
 5### The error occurred while setting parameters
 6### SQL: INSERT INTO tap_account  ( open_id, avatar, nick_name, country, province, city, gender, secret,         status, IS_DISABLED,     is_subscribe, create_time, update_time )  VALUES
 7  ( ?, ?, ?, ?, ?, ?, ?, ?,         ?, ?,     ?, ?, ? )
 8### Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\xA6\x84' for column 'NICK_NAME' at row 1
 9; uncategorized SQLException; SQL state [HY000]; error code [1366]; Incorrect string value: '\xF0\x9F\xA6\x84' for column 'NICK_NAME' at row 1; nested exception is java.sql.SQLException:
10 Incorrect string value: '\xF0\x9F\xA6\x84' for column 'NICK_NAME' at row 1
11
12org.springframework.jdbc.UncategorizedSQLException:
13### Error updating database.  Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\xA6\x84' for column 'NICK_NAME' at row 1
14### The error may exist in com/eveus/tap/account/mapper/AccountMapper.java (best guess)
15### The error may involve com.eveus.tap.account.mapper.AccountMapper.insert-Inline
16### The error occurred while setting parameters
17### SQL: INSERT INTO tap_account  ( open_id, avatar, nick_name, country, province, city, gender, secret,         status, IS_DISABLED,     is_subscribe, create_time, update_time )  VALUES
18  ( ?, ?, ?, ?, ?, ?, ?, ?,         ?, ?,     ?, ?, ? )
19### Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\xA6\x84' for column 'NICK_NAME' at row 1
20; uncategorized SQLException; SQL state [HY000]; error code [1366]; Incorrect string value: '\xF0\x9F\xA6\x84' for column 'NICK_NAME' at row 1; nested exception is java.sql.SQLException:
21 Incorrect string value: '\xF0\x9F\xA6\x84' for column 'NICK_NAME' at row 1
22        at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:89)
23        at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
24        at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
25        at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:88)
26        at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:440)
27        at com.sun.proxy.$Proxy134.insert(Unknown Source)
28        at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:271)
29        at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:60)
30        at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:96)
31        at com.sun.proxy.$Proxy186.insert(Unknown Source)
32        at com.baomidou.mybatisplus.extension.service.IService.save(IService.java:59)
33        at com.eveus.tap.account.service.impl.AccountServiceImpl.addAccount(AccountServiceImpl.java:151)
34        at com.eveus.tap.account.service.impl.AccountServiceImpl.ensureLoad(AccountServiceImpl.java:226)
35        at com.eveus.tap.account.service.impl.AccountServiceImpl$$FastClassBySpringCGLIB$$34fe95c8.invoke(<generated>)
36        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
37        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)
38        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
39        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
40        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
41        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
42        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
43        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
44        at com.eveus.tap.account.service.impl.AccountServiceImpl$$EnhancerBySpringCGLIB$$cbb1e26b.ensureLoad(<generated>)
45        at com.eveus.tap.server.taxer.mp.handler.SubscribeHandler.handle(SubscribeHandler.java:54)
46        at me.chanjar.weixin.mp.api.WxMpMessageRouterRule.service(WxMpMessageRouterRule.java:226)
47        at me.chanjar.weixin.mp.api.WxMpMessageRouter.route(WxMpMessageRouter.java:203)
48        at me.chanjar.weixin.mp.api.WxMpMessageRouter.route(WxMpMessageRouter.java:154)
49        at me.chanjar.weixin.mp.api.WxMpMessageRouter.route(WxMpMessageRouter.java:233)

看错误信息是因为 MySQL 字符编码不正确导致无法保存特殊字符导致的。把字符还原一下,发现 \xF0\x9F\xA6\x84 代表的字符内容是:🦄,是一个 Emoji 字符。

当使用对 utf8 编码的时候,和一般汉字占用3个字节不同,Emoji 字符的编码会比较特殊一点,占用4个字节。而由于历史的原因,MySQL 使用的 utf8 编码最长支持3个字节,如果要保存4个字节的 unicode,则需要使用 utf8mb4 编码。上述错误应该是因此而出。

阅读全文 »

MyBatis Plus中主键生成方式ASSIGN_ID的算法分析

时间: 2021-07-02   |   分类: 开发     |   评论:  0    |   访问: 0

MyBatis Plus 中提供了 ASSIGN_ID 这种方式生成主键,使用起来非常方便,只要在PO上定义一下就可以了,例如:

1public class Order extends Model<Order> {
2
3    @TableId(value = "id", type = IdType.ASSIGN_ID)
4    private Long id;
5
6    //...
7}

这样在保存的时候,MyBatis Plus会负责生成主键值,自动设置到字段id中。 一直好奇这个主键是怎么生成的,抽时间查看了一下源码,特意记录一下。

阅读全文 »

Linux常用命令介绍 05 - unzip

时间: 2021-02-26   |   分类: 运维     |   评论:  0    |   访问: 0

unzip命令可以用来解压zip文件。用法比较简单,但是有些不太常用的命令需要记录一下。

1. 查看文件列表

1unzip -l ShadowHunters.epub
2# 查看更详细信息,包括压缩率等
3unzip -lv ShadowHunters.epub

2. 解压文件

1unzip -d ./temp ShadowHunters.epub

3. 解压一个文件

使用-p命令,将文件内容输出到标准输出,然后使用重定向创建文件:

1unzip -p ShadowHunters.epub ops/xhtml/cover.html > cover.html

4. 更新文件

1zip -u ShadowHunters.epub ops/xhtml/cover.html

如何在Ubuntu上静态编译Golang+GoCV程序

时间: 2020-12-18   |   分类: 开发     |   评论:  0    |   访问: 0

最近做了一个图像增强程序,用到了OpenCV。为了方便发布,我将代码使用Golang+GoCV重写,但是编译的时候发现比较麻烦,特别记录一下,以备后查。 本文对应版本如下:

  • Ubuntu 18.04.5 LTS
  • Golang 1.15.6
  • OpenCV 4.5.0
  • GoCV 0.2.5

1. Golang环境准备

1.1 安装Golang

下载对应的包,然后解压,设置PATH路径即可,不多说了。

1.2 设置GOPATH

使用go get下载的包将下载到$GOPATH目录中。 这里设置成/home/ubuntu/.go。不设置的话将自动设置成~/go目录。

1cd /home/ubuntu/.go
2export GOPATH=/home/ubuntu/.go

1.3 下载GoCV源码

1# 设置代理翻墙,要不然下载不了
2git config --global http.proxy=http://127.0.0.1:12346
3git config --global https.proxy=http://127.0.0.1:12346
4export http_proxy=http://127.0.0.1:12346
5export https_proxy=http://127.0.0.1:12346
6go get -v -u -d gocv.io/x/gocv
阅读全文 »
1 2 3 4 5 6 7 8
Orchidflower

Orchidflower

Do one thing at a time, and do well.

76 日志
6 分类
83 标签
RSS 订阅
GitHub 知乎 OSC 豆瓣
© 2009 - 2022 执子之手
Powered by - Hugo v0.104.3
Theme by - NexT
ICP - 鲁ICP备17006463号-1
0%