Jasper Ji

开口不在舌头上

0%

上次去省图偶然看到了《WebAssembly 实战》一书,之前就有关注到,于是就借了回来,刚好趁清明假期看看。之前有写过一篇《初试WebAssembly》,本身Rust语言不熟,虽然我买了本《Rust权威指南》,但一直没有什么项目可以练手,基本上没有进展。《WebAssembly 实战》一书是基于C/C++的,相对来说读起来障碍不大。实际我也跑了一个例子试了下,当然如果真拿C/C++来写Web应用的话,估计会很奔溃了。接着我又看了好几个关于WebAssembly的视频演讲,发现有了新的想法。

推出WebAssembly这个东西主要是因为现有的优化已经无法满足性能的进一步提升了,语言肯定不能大改了,JS这么用的广。记得早些年使用Flash的时候,那会是在嵌入式上跑AS2,性能的问题真的是让我当时无语。后来又推出了AS3性能又大幅的提升,但是很长一段时间,我们公司的引擎没有升级,所以我基本上还是用AS2。虽然现在的Web开发没有像当年那样,毕竟开放的环境还是不一样。回到正题,如果单纯的写WebAssembly的话,好像也没有这个必要,而且据说和JS的调用开销不小,所以到底什么时候用,是个问题。反过来想要是哪天整个的Web可以大部分都用WebAssembly来写的话,那就好了,不过目前还不能直接操作Dom,这是一个很大的问题,理论和JS是相互调用的,我看到Rust有个web_sys的库,可以操作dom,不过我想应该也是自己实现的吧。目前看到几个Rust的例子,是直接用WebAssembly来写整个的Web应用的,比如Yew这个Rust的框架允许你构建基于WebAssembly的应用。另外微软的Blazor,允许使用C#来编写基于WebAssembly的单页应用。还有Go的Vugu。

所以如果和JS混着用,那么实际上是把WebAssembly作为一个计算密集型的一个解决方案吧,实际开发中大部分的Web应用都是些轻客户端,主要还是界面相关的操作了,其实大部分情况下很难想到用WebAssembly了,这也是我最早尝试时的感想。但是如果未来解决了类似调DOM的成本比较高的的问题,那么有没有可能Web语言变成Rust为主,为什么是Rust呢?首先WebAssembly本身没有垃圾回收,内存是手动处理了。Rust呢?标榜的是一个没有垃圾回收的安全语言,与C/C++相比实际上是语言层面上处理内存管理的问题。这么一想Rust与WebAssembly真是绝配,当然其他的语言也可以编译成WebAssembly,但对于垃圾回收的语言,是比要实现一个垃圾回收的运行时环境,这样性能上就会有折扣。

总结

想来想去,最终落到Rust这个语言上了,或者说WebAssembly本身的设计这种在底层改变的东西无疑为未来提供了各种改变的可能性,即使不是Rust也许会是其他的语言。C/C++用户可以让现有的库移植到Web上使用,另外Web应用一定是现在这样的轻客户端的类型吗?WebAssembly的引入确实提供另一种可能。另外一定要用JS来写Web应用吗?过去是没有办法,但是底层的改变让未来可以使用统一基于WebAssembly的语言来写Web成为了可能,而不像过去所有新的语言实际上都得编译成JS。基于WebAssembly的框架,有微软这样的大厂,也有基于Go的,某种程度这是一场大厂利好的事,但坏处是当有各种的语言可以写Web时,会不会有点分裂,毕竟只学一个JS,大家共用资源,而用不同的语言有学习成本。

本站14年建立的,那会Octopress确实流行,好多的技术大拿都用,可惜当时只是建了个站,就没有写东西,后来想写东西了,发现大家都不用Octopress了,有人说慢,其实我的电脑上还行。一开始我也没有想着换,Octopress的问题是作者已经不更新了,所以就有一堆的升级的问题,总之对于程序员而言也无所谓,改改还是可以用的,就这样一直坚持到写这篇文章的晚上。

我比较在意代码高亮,上次就把Octopress的代码高亮给改了,不过不完美。其实博客很大程度是我的一些技术的记录了,想想这个,就一时兴起尝试的迁移吧。虽然静态博客框架很多,不过自己最近3年一直有写JS,另外Hexo确实很多人用。这次的迁移可以说相当的顺利。Hexo的文档非常不错,基本上照着来网站就好了。原来想着在Github再建一个项目,后来发现不需要,直接把我旧的网站一覆盖就可以了。

使用的主题是NexT,我比较喜欢简洁的,这个主题的文档也非常不错,很快就搞定了,看着焕然一新的博客,Octopress已成过去时了。

我安装的是13.0.4的版本,20年安装的,当时也没有想到要升级,觉得小团队用。但是自从去年被病毒入侵后,在反反复复的杀病毒后,病毒还是不断的重来,严重的影响了开发。

Gitlab的升级不能直接跨版本升级,需要一步步的来。可以参考官方升级路线。我的版本是13.0.4,官方的路线13.0.14 -> 13.1.11 -> 13.8.8 -> 13.12.15 -> 14.0.12 -> latest 14.Y.Z,我原来想着是不是需要先升级到13.0.14,按一般的管理,最后这个应该是布丁版本了,实际是直接升级13.1.11就可以了,装完后再安装13.8.8,以此类推。

Gitlab的各个版本的镜像地址清华大学开源软件镜像站,速度还是非常给力。

总结

对于Gitlab这类软件,还是要定期升级的,不然就版本的漏洞导致的瘫痪实在是划不来。

起因

Windows上中毒已经习以为常,但是Linux中毒,之前没有遇到过。之前写过一篇《记Gitlab一次故障》,当时以为Gitlab服务器就好了,后来发现还是会时不时的就访问不了,CPU还是占的满满的,想着是不是要降低Gitlab的配置,最后把配置降低后,CPU还是满满的,我一度想换个Gitlab类似的东西,直到我发现即使把Gitlab停止后,依旧有两个Git的用户的程序把CPU占的满满的。其中一个叫kthreaddk的,隐约的感觉到好像中毒了,一搜发现这是一个挖矿的木马程序。

把进程Kill掉后,发现过一会又启动了。看来还是要深度清理了,参考《挖矿木马kthreaddk清理》这篇文章后,终于把这个木马清理了。主要是安装Gitlab时会创建一个git的用户,而木马程序就是这个用户下运行的,定时任务也是在这个用户下。遇到的主要问题是我不知道git用户的密码,不过这个可以用root账号来修改。

修改Git用户密码

1
sudo passwd git # 这个是修改用户密码,用户密码密码无法查看,即使你是管理员。

清理木马

1
2
3
4
5
6
7
8
9
10
11
su git # 切换到git用户

crontab -l # 查看定时任务

sudo /etc/init.d/cron stop # 停掉定时程序

kill -9 进程ID 进程ID # 这个木马会有两个进程

crontab -r # 移除定时任务

sudo /etc/init.d/cron start # 重启定时任务

总结

整个Gillab的故障中我一直没有想到中毒的问题,而上次出现故障时,我发现Gitlab账户多了一个管理员的用户,遂即就把这个用户给禁用了,这就已经是一个预兆了。通过这次事件,也算是给上了一课,之前也有使用top这个命令,但从来没有过深入的理解。另外开源的这些软件的漏洞的问题,也是值得关注的,搞不好就有被利用的可能性。

消息队列这个东西一直有关注,RabbitMQ相关的东西书籍也入手了,也跑过简单的例子,不过一直没有上。一开始使用的是Spring Boot集成RabbitMQ的方案,因为用的是Spring Cloud的微服务解决方案,发现Spring Cloud Stream这个东西,用这个的好处就是这是一个高层次的实现,可以支持RabbitMQ和Kafka,所以后续切换也方便。

Source、Sink、Processor

这三个是Spring Cloud Stream自带的,Source用来发送消息、Sink用来接收消息,Processor集成了二者。最初的构想是一个微服务生产消息,另一个微服务消费这些消息,我一开始用的是@EnableBinding(value = {Processor.class})注解,这样话等于我要同时处理生产和消费的东西。如果只是实现我最初的构想的话,只需要绑定Source或者Sink其中一个就好。

总结

Spring Cloud Stream网上的资料并不多,一开始上手有点难。

参考

Spring Cloud 系列之 Spring Cloud Stream

消息驱动微服务框架Spring Cloud Stream使用详解2(基本用法)
这个文章广告比较多

Gitlab部署后一年多基本没出问题,最近一次提交突然失败,后台也登不上去了,显示502错误页面。用top命令确实发现CPU飙升,满负荷运行,怎么办呢?

重启

重启可能是最实用的方法吧,于是我第一步就先重启,刚一开始还能访问下,但很快就不行了,发现CUP还是很高。

升级

后来发现好像是Gitlab漏洞的问题,于是就像想着赶紧升级到最新的版本吧。一顿猛操作,就把版本升级到最新的版本了,但还是无法访问,CPU还是占用很高。

日志

使用gitlab-ctl start后并没有哪个是异常的,然后使用gitlab-ctl status,也是没有看出问题。最后决定查看日志吧,其实这个应该是最先想到的,可是每次都有点滞后。

1
2
3
/var/log/gitlab/gitlab-rails/production.log # Gitlab日志目录

gitlab-ctl tail # 也可以用这个查询

发现是数据库连接的问题,最新版本和我原来的数据是不同的版本,无法直接升级。

版本

我之前安装的Gitlab是什么版本?原来也没有太注意。但这个很重要,我最后是通过备份文件的后缀知道我原来安装的版本的,我根据Postgres报错信息,定位到了原来的Postgres是11,但是发现Gitlab12和13版本,我先选择的12,是可以访问了,但是项目点进去后项目显示不存在。

1
2
3
cat /opt/gitlab/embedded/service/gitlab-rails/VERSION # 比较靠谱
网址/help # 这个也可以查,但是网站502时不行。
sudo gitlab-rake gitlab:env:info # 这个方法,我第一次使用的时候,因为有个报错所以也不行。

备份

我已经有点想放弃了,干脆重装或者换个Gitlab类似的东西。可作为一个技术,还是决定再试下。网上说要恢复备份,好在Gitlab有一个默认备份,大概是7天备份一次,还好我最近一直没有提交过。我决定恢复备份,结果发现版本不对,备份的后缀有一个版本号,是13.0.4,而我装的是12。于是又下载重装了版本。

1
/var/opt/gitlab/backups # 默认备份路径

重装后实际上还不能访问,需要恢复备份。

1
gitlab-rake gitlab:backup:restore BACKUP=需要恢复的版本名称 # _gitlab_backup.tar 之前的所有。

最后成功运行。

问题点

执行gitlab-ctl reconfigure报错

1
2
3
PG::ConnectionBad: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket “/var/opt/gitlab/postgresql/.s.PGSQL.5432”?

解决方案

1
2
3
4
5
sudo gitlab-ctl stop # 停止gitlab
sudo chmod 755 /var/opt/gitlab/postgresql
sudo systemctl restart gitlab-runsvdir
sudo gitlab-ctl reconfigure
sudo gitlab-ctl restart

总结

应该解决问题,而不是轻易的重装。

  1. 出现故障不要轻易的跨版本升级,比如Postgres的版本就有点频繁,而Gitlab也好像喜欢用最新的版本。
  2. 一定要记住当前的版本
  3. 备份
  4. 出现问题先看日志
  5. 机器配置,我的机子是单核4G的理论上是可以的,CPU占用率在50%上下,内存占有率也是在50%左右,实际上是可以运行的。

参考

Gitlab官方包中心
gitlab安装、备份、恢复、升级、内存消耗问题

移动市场发展缓慢

经过十年的发展,移动市场的机会似乎越来越少了。我也从iOS开发者,转做服务端开发了。iPhone是越来越贵了,我的6s已经扛过了第五个年头了。随着个人开发技能的提高,我现在反而喜欢纯粹的Linux手机。不过这类手机太少了,淘宝上购买的PinePhone自从6月中旬购买后,到现在也没有到货,只能寄希望于国庆后了。

移动设备的性能已经高过了需求,有些东西正在朝着另外一些方向转移,比如物联网。不过我观察了半天感觉这块市场太碎了,不好插手。

乙川弘文

十年间乔布斯相关的书籍出版不少,即使连给乔布斯做过寿司的老板也出书了,可是关于乙川弘文的书籍却没有出版,早期确实是没有的,不过后来有人根据他生前的录音整理了一本关于他的书籍《Kobun, Sesshin Talks》,后来16年出版后叫《Embracing Mind》。不过这么些年过去了,此书的中文版一直没有面世,我买过此书的英文版,大略的读了一遍,觉得这是一本跟《禅者的初心》不太一样的书籍,对于打坐修行的人来说是非常有参考价值,从去年开始我就利用机器翻译加人工校对的形式在整理此书,最近终于把剩余的给全部弄完了。已经放到了GitHub上《Kobun, Sesshin Talks》,喜欢的可以去看看,欢迎共同完善。

最近养了只NY11的金渐层妹妹,大概已经半个多月了,谈谈一些感受。

猫毛和灰尘,戴森吸尘器

猫毛无处不在,关键会有一些比较小的绒毛很容易飞在空气中,搞不好就回吸进去,所以也能理解有些人猫过敏。灰尘弥漫,猫经常会发疯似得满屋子狂奔,床底平时不太打扫得到,很容易被猫带出来,养猫后灰尘感觉弥漫在空气一样。面对这两个问题,我狠心买了个戴森吸尘器V10,首先这个确实可以把地板上散落的猫毛和灰尘以及一些杂质给收集起来,另外对于椅子上的猫毛也能清理,但还是有照顾不到的地方,总的来说解决一些问题。

危险

防止猫触发水龙头,一般的水龙不太会有问题,不过类似面盆之类的水龙头只需要简单的抬起和按下,这类水龙头会有隐患。

对于猫咪感兴趣但有危险的行为,一定要在发现的第一时间采取行动,猫是属于好奇心很重的那种。

寄养

短暂的几天其实倒还好,但是如果出差之类的,在这个疫情大背景下,确实有万一被隔离的潜在风险,所以作为单身人士而言最好把猫寄养了。寄养确实也贵,有些是全包,有些要求自带猫粮或者猫粮和猫砂都需要带,另外有些会要求必须是打了疫苗的、绝育的等。所以找一家合适的家养猫的确实也不容易。

公猫还是母猫?

我一开始以为公猫发情后会乱尿,所以选择了母猫。但实际上母猫也会乱尿,这是一位养母猫的朋友亲身经历。公猫会发腮,这会给颜值加分,如果比较看重颜值的话,还是要先考虑公猫。有人说母猫可以繁殖,所以价格会更贵一点,我没有发现,更多的是看颜值了。如果真的要繁育猫,首先也得找好的种公也是要花钱的,另外生下来能不能卖出去并卖上一个价也是一个问题,母猫绝育也比较麻烦,更有风险。

猫不在多,而在于健康。最近发现猫开始呕吐,那天还蛮严重的,因为一直喂罐头的缘故,可能加了诱食剂,后来自己好了。

过年的时候,送去寄养结果就又呕吐了,最后专门到医院打针,后来想想环境的变动也会猫有一定的影响。

疫苗

关于疫苗,买猫的时候,老板说打了一针的疫苗,但也没有疫苗本,所以又重新从第一针开打。就像现在每天要扫码一样,疫苗也是你的猫咪在社会上流通的通行证,寄养也好、做绝育都需要有疫苗本。

目前我的猫已经打了三针了以及狂犬疫苗。

配种

去年底的时候,猫突然开始发情了,不过就是每隔2周会发情一次,刚开始还能接受,后来确实有点烦,今年4月底的时候差不多猫也有一岁了,于是我就考虑给配种下,一来至少2个月不会再发情了,而来也能收获下一窝可爱的小猫。借配的公猫在闲鱼上物色了好几个,最后选中了一个,第二天就把母猫送了过去,那边承诺配三次。可能我送过去的时候已经是发情第三天的时候,接回猫后没有多久猫又开始发情了,应该是没有配上。于是第一时间联系借配的,把猫又送了过去,直接放了一周,那人以为我不要猫了,这次似乎成功了,他也给我发了好几配猫的视频。后面的日子,猫咩确实没有再发情了,渐渐的开始没有之前那么好动,现在已经距离接回有一个多月了,猫的肚子明显变大了,也更加的不愿意动,饭量也比原来的大了很多,而且相当的能睡。预计6月底应该会生,期待一下。

我找的这个是专门配猫的,养了好几只公猫,其中有两只金渐层,一只是11色的,另一只是12色,11色的便宜800块钱,因为我的本身是11色,如果再配11色,大概率出的猫会有黑的可能性,所以选的12色,12色的1500,最后搞价到1400。因为小猫还没有出生,不能完全的判断这次的效果。另外配猫的时间点,不能过急,第一次完全是因为假期,而猫也开始发情了,急匆匆的找了一个,又急匆匆的送了过去,而那会已经是发情的第三天了,加上猫过去需要适应,所以第一次没有配成功也算合理,第二次就成功了,所以时间点上一定不能急,如果母猫已经快发情完了,那就等下一次。

本来想在虚拟机上安装TDengine试试,经过一番折腾后发现磁盘容量不足,当时创建虚拟机时选择的是8G,这就尴尬了,最后还是一番折腾后终于扩容成功。

VirtualBox

先关闭虚拟机,在虚拟机运行目录下执行。

1
VBoxManage modifyhd /Users/jasperji/VirtualBox\ VMs/centos8/centos8.vdi --resize 15360 

这里我把容量扩展为15G,记住路径中空格的问题。

CentOS

查看磁盘容量情况

1
df -h

操作分区,选项n,创建新分区。

1
fdisk /dev/sda

创建PV(物理卷)

1
pvcreate /dev/sda3

扩展到卷组,我们vgdisplay命令查看一下自己所在的卷组:

1
pvdisplay

看到VG Name是cl,所以进一步扩展到卷组:

1
vgextend cl /dev/sda3

扩展到逻辑分区,使用lvextend(logical volume extend逻辑卷扩展)

1
lvextend /dev/cl/root /dev/sda3

我们df -h查看一下文件系统的磁盘空间占用情况:

1
df -h

这里我们发现磁盘没有按照预期的扩容,因为我们没有刷新逻辑分区的容量。

于是,刷新逻辑分区的容量,使用xfs_growfs(同步文件系统)命令,注意上面的Mounted on是挂载点,这里我们的挂载点就是根目录:

1
xfs_growfs /

最后就扩容成功了。

总结

其实之前阿里云正式服务器的时候,也记得有挂载过当时购买的云硬盘。不过时间久了,当时也没有记录一些东西,也就忘了。

参考

CentOS8扩容
VirtualBox虚拟机硬盘扩容及LVM命令介绍
VirtualBox文件系统已满–磁盘扩容

Java字节码只是简单的了解,感觉缺乏深入的了解,特写此篇记录下。

准备一个HelloWorld的测试类。

1
2
3
4
5
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}

编译生成HelloWorld.class文件

1
javac HelloWorld.java

我们使用javap命令来查看class文件

1
javap -v HelloWorld.class

输出结果

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
Classfile /Users/jasperji/eclipse-workspace/maventest/src/main/java/com/jasper/ji/maven/test/HelloWorld.class
Last modified 2021-9-8; size 452 bytes
MD5 checksum 1f346aeb85559b06180507b8838406dd
Compiled from "HelloWorld.java"
public class com.jasper.ji.maven.test.HelloWorld
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #6.#15 // java/lang/Object."<init>":()V
#2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #18 // Hello, World!
#4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #21 // com/jasper/ji/maven/test/HelloWorld
#6 = Class #22 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 main
#12 = Utf8 ([Ljava/lang/String;)V
#13 = Utf8 SourceFile
#14 = Utf8 HelloWorld.java
#15 = NameAndType #7:#8 // "<init>":()V
#16 = Class #23 // java/lang/System
#17 = NameAndType #24:#25 // out:Ljava/io/PrintStream;
#18 = Utf8 Hello, World!
#19 = Class #26 // java/io/PrintStream
#20 = NameAndType #27:#28 // println:(Ljava/lang/String;)V
#21 = Utf8 com/jasper/ji/maven/test/HelloWorld
#22 = Utf8 java/lang/Object
#23 = Utf8 java/lang/System
#24 = Utf8 out
#25 = Utf8 Ljava/io/PrintStream;
#26 = Utf8 java/io/PrintStream
#27 = Utf8 println
#28 = Utf8 (Ljava/lang/String;)V
{
public com.jasper.ji.maven.test.HelloWorld();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello, World!
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 5: 0
line 6: 8
}
SourceFile: "HelloWorld.java"

另外也可以直接查看二进制,这里使用hexdump。

1
hexdump HelloWorld.class

不过感觉还是javap提供的这个比较人性化,更好的阅读。

总结

字节码作为一种中间形式,Java可以编译成字节码,Scala也可以编译成字节码,但是从语言层面他们又是不一样的。这个也让我重新再读了下《Java程序员修炼之道》这本书,原来对于书中第三部分JVM上的多语言编程,不是很感冒。但字节码并不是机器码,所以在理解某些问题时最终还是要落到汇编语言级别的。

参考

字节码增强技术探索