公司大量使用微服务框架 go-micro,但框架作者已不再维护低版本(新版本已经商业化),只能自己动手了。

起因是我用 Go 1.16 编译,启动报错:

panic: qtls.ConnectionState not compatible with tls.ConnectionState

goroutine 1 [running]:
github.com/lucas-clemente/quic-go/internal/handshake.init.0()
        /go/pkg/mod/github.com/lucas-clemente/quic-go@v0.12.1/internal/handshake/unsafe.go:17 +0x118

阅读全文

先说八字流派

八字流派特别多。

不管是事业,还是婚姻感情,看法也不尽相同。我听说过的就有以下几种:

  • 格局:八字用神,专求月令;也有看月令透干的流派。
  • 盲派:铁口直断,根据四柱八字形象、干支组合等断大事件,出口往往戳中痛点。
  • 旺衰:以日干旺衰为核心,追求五行平衡,旺了,克泄;衰了,帮扶。主要分《滴天髓》派和新派。滴天髓派多体现在断语上,而新派更多倾向于公式化(一个土二个木各种占比计算之类)。
  • 禄命:听过,但没有见过。以年命为主看纳音和神煞。

这几种流派我们不讨论孰优孰劣,涉及的东西太多,了解甚浅,不好评价。但我觉得,格局很好用。

成大格者成大事。

阅读全文

最后更新时间 2021-07-04.

本文整理自2ccc盒子iny的帖子 → 链接到原贴
破解 → 链接

一、绿色版介绍

  • 绿色版为完全版,没做任何的精简,也没有做任何的改动!
  • 绿色版不含任何破解,仅供研究,24 小时后请自行删除,如需继续使用 RAD Studio,请购买正版。

二、绿色版文件包说明

绿色版共包含 4 个文件包,分别为:

  • [必选] dotnetfx45_full_x86_x64.exe:Microsoft .NET Framework 4.5
  • [必选] RAD Studio 10.4.2 绿色版.7z:基础包
  • [必选] RAD Studio 10.4 Green 1.4.rar:绿化程序
  • [可选] RAD Studio 10.4.2 PlatformSDKs.7z:Android SDK、Android NDK

阅读全文

传统部署的坑:

1202 年了,如果你连 Docker 都不知道是什么,我建议买一本书看看——或者谷歌一下,博客已经写烂了。

为什么有这篇文章,是因为我在真正做容器化改造的时候,发现公司生产环境存在大量的坑:

  • 传统虚拟机部署,基本依赖克隆或者手工编译。由于人力原因,SRE 历来单传,编译出来的 PHP、扩展等二进制版本不一致;
  • 项目开发人员痛苦不堪——他没办法模拟出接近于线上一致的环境(碰不到摸不着,各种扩展版本都要自己去编译);
  • 新人入职都会灵魂拷问你一句——我怎么把线上的代码跑起来?
  • ……

用什么 Linux 发行版?

Ubuntu 应该是全球用户量最多的发行版了,嗯我说的是桌面这一块,折腾过的人都知道,出问题的时候开机会有 “检测到系统错误” 的提示,另外,网上提供的配置或者各种疑难杂症,改了不一定能生效,而且你还不确定改了会不会影响到别的,反正我是不敢用的哈哈(Manjaro 真香)。

阅读全文

阅读本文大约需要 2.9 分钟。

曾经的我是一名艺术生,如今是一名程序员。

聊起画画,相信很多人都有疑惑:同样都是画人物,为什么我画不像,或者说我根本就不知道怎么下手。

阅读全文

阅读本文大约需要 40 分钟。

上一篇文章 《大白话讲讲 Go 语言的 sync.Map(一)》 讲到 entry 数据结构,原因是 Go 语言标准库的 map 不是线程安全的,通过加一层抽象回避这个问题。

当一个 key 被删除的时候,比如李四销户了,以前要撕掉小账本,现在可以在大账本上写 expunged,

对,什么也不写也是 OK 的。也就是说,

entry.p 可能是真正的数据的地址,也可能是 nil,也可能是 expunged。

阅读全文

阅读本文大约需要 4.25 分钟。

程序是枯燥乏味的。

在讲 sync.Map 之前,我们先说说什么是 map(映射)。

我们每个人都有身份证号码,如果我需要从身份证号码查到对应的姓名,用 map 存储是非常合适的。

map[000...001] = 张三
map[000...002] = 李四
...
map[999...993] = 钱五

身份证号码有 18 位,如果要知道 111...002 这个人叫什么名字,没有 map 我只能从 000...001 一个一个往下查找,效率是非常低的。

阅读全文

阅读本文大约需要 3.50 分钟。

趁五一有时间,做个小小的复盘。

4 月 10 日,我当时围绕光环新网写了挺多内容,先回顾一下:

风险:商誉减值、坏账损失风险高、股东人数增多、管理层减持、5G 发展、IDC 建设与上架不及预期、定增不及预期、中美关系影响亚马逊 AWS 业务、市场竞争;

阅读全文

阅读本文大约需要 4.28 分钟。

直到今天,2021 年已经过去了四分之一,有多少人保持正收益?

不得不说,股市真是屠宰场。跌起来毫无人性,却又充满人性:大涨时喜笑颜开,大跌时哀嚎一片。

阅读全文

阅读本文大约需要 5.18 分钟。

本篇文章是命理知识系列的第二篇,第一篇见 命理案例剖析——什么样的人容易遇到渣男


01 释义
————

十二长生(长生、沐浴、冠带、临官、帝旺、衰、病、死、墓、绝、胎、养),是十天干(甲乙丙丁戊己庚辛壬癸)的十二种运势,可以表示人事物的生老病死或兴亡盛衰。

长生,表示新事物的产生。就像刚刚出生的小孩,虽然弱小,但有旺盛的生命力。
含义:出生、生长、起点、发生、苏醒、来源、源泉、哺育等。





阅读全文

阅读本文大约需要 3.47 分钟。

21 世纪了,还信这些?

请务必保持理性,我们不猜测,依易理,重逻辑。我相信绝对有人能看懂,收获颇丰。

看文之前,先默念一遍天干地支,有基础的可以略过。
十天干:
甲乙丙丁戊己庚辛壬癸
十二地支:
子丑寅卯辰巳午未申酉戌亥

这是个女命,初学的看到甲乙丙丁,子丑寅卯肯定不知道从哪下手。

乙☐己甲
☐午亥子






阅读全文

阅读本文大约需要 3.13 分钟。

01

点进来的朋友,有多少人跟我一样,盼望着春节 A 股开市的大红包呢?期望有多大,失望就有多大。

如果你点开文章是冲着代码来的,还真没有,我不荐股,文中出现的字眼均不构成投资意见。

回顾节后的两个交易日,我深刻反思,终究是定力不足,管不住手,检讨一下。

“你永远赚不到超出自己认知范围外的钱,除非靠运气。靠运气赚的钱往往靠实力亏掉。”



阅读全文

nil 是什么?

可以看看官方的描述,在 buildin/buildin.go 里:

// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type

nil 是一个预先声明的标识符,代表指针、通道、函数、接口、哈希表或切片的零值。

OK,回到问题,nil 能比较自己吗?

package main

import "fmt"

func main() {
    fmt.Println(nil == nil)
}

// # command-line-arguments
// ./main.go:6:18: invalid operation: nil == nil (operator == not defined on nil)

没有具体的类型,编译器懵逼了说没办法比较。

slice 什么时候是 nil ?

看看下面的代码:

var slice = []string{}
fmt.Println(slice == nil) // false

type GoSlice struct {
        ptr unsafe.Pointer
    len int
    cap int
}
s := (*GoSlice)(unsafe.Pointer(&a))
s.ptr = nil
fmt.Println(s == nil) // true

神奇,切片底层指针为 nil 的时候,就是一个 nil 切片。map、channel、func 也是类似的。

nil 和 interface 一起使用的坑

继续看代码:

type A interface {}
type a struct {}

func Foo() A {
    var data *a // nil
    return data
}

fmt.Println(Foo() == nil) // false

嗯,坑得体无完肤。很反人类!接口为 nil,必须是类型和值同时为 nil,才能等于 nil,无聊的知识又增加了:)

cURL,熟悉 Linux 的同学,没有人不知道这个命令吧:)

它有非常非常多的参数,我这里就不复制粘贴了,有需要可以 -h 或者谷歌搜索看看。

我从实用性的角度,说下我比较常用的几个参数:

  • -v:啰嗦模式,打印请求头部、响应头部,如果是 https 请求会打印握手信息;
  • -H:包含 HTTP 头部,可多次使用
  • -s:不打印进度条
  • -o:指定输出,如果不想看输出的内容,可以 -o /dev/null 丢弃
  • -k:忽略 https 证书校验
  • -d:用来提交数据
  • -X:指定 HTTP method
  • -w:可以输出连接的时间、服务器处理的时间、请求总时间等

简单的参数组合

curl -v -H 'Host: imlht.com.test' \
     -H 'Content-Type: application/json' \
     -H 'Cookie: uid=123' \
     -s \
     -o /dev/null \
     -X PUT \
     -k \
     -d '{"name": "John"}' https://10.43.1.101/user/123

有几个小细节,我提一下:

-k 可以忽略 https 的证书校验,调试的时候很好用。

比如上面的 imlht.com.test,一般情况下你是没有这个证书的,但是你又想测试 10.43.1.101 的 /user 接口,此时可以直接跳过测接口的内容。

-d 参数默认的 Content-Type 是表单,如果你提交的数据是 JSON,需要像上面一样指定好 JSON 头部。

有些接口会依赖这个头部解析 body 的内容;另外默认的 method 是 POST,这里我用了 -X PUT 指定 method。

有点复杂的 -w 参数

curl -w "\ntime_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_redirect: %{time_redirect}\ntime_pretransfer: %{time_pretransfer}\ntime_starttransfer: %{time_starttransfer}\n--------\ntime_total: %{time_total}\n" https://im.qq.com/
(省略一部分内容)
...
</body>
</html>

time_namelookup: 0.028
time_connect: 0.030
time_appconnect: 0.136
time_redirect: 0.000
time_pretransfer: 0.136
time_starttransfer: 0.296
--------
time_total: 0.436
  • time_namelookup :DNS 解析耗时
  • time_connect :TCP 连接建立耗时,也就是三次握手的时间
  • time_appconnect :SSL/SSH 等上层协议建立连接的时间,比如 connect/handshake 的时间
  • time_redirect :从开始到最后一个请求事务的时间
  • time_pretransfer :从请求开始到响应开始传输的时间
  • time_starttransfer :从请求开始到第一个字节将要传输的时间
  • time_total :这次请求花费的全部时间

根据上面的解释,我们可以得到以下的结论:

  • DNS 解析耗时:28ms
  • TCP 连接时间: pretransfter(136) - namelookup(28) = 108ms
  • 服务器处理时间:starttransfter(296) - pretransfer(136) = 160ms
  • 内容传输时间: total(436) - starttransfer(296) = 140ms

今天向公司申请了一台 Linux 主机,作为平时的开发环境。由于自己并不依赖远程开发(大多数情况下项目都可以本地开发、调试),于是只申请了 4C/8G 的低配机器。

突然好奇的是,这台机器的性能怎么样?磁盘就不测试了,IO 应该和生产环境差不多。先看看 CPU 的信息:

cat /proc/cpuinfo
processor    : 0
vendor_id    : GenuineIntel
cpu family    : 6
model        : 45
model name    : Intel(R) Xeon(R) CPU E5-2650 0 @ 2.00GHz
stepping    : 7
microcode    : 0x71a
cpu MHz        : 1999.999
cache size    : 20480 KB
physical id    : 0
siblings    : 1
core id        : 0
cpu cores    : 1
apicid        : 0
initial apicid    : 0
fpu        : yes
fpu_exception    : yes
cpuid level    : 13
wp        : yes
flags        : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc eagerfpu pni pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx hypervisor lahf_lm ssbd ibrs ibpb stibp tsc_adjust arat md_clear spec_ctrl intel_stibp flush_l1d arch_capabilities
bogomips    : 3999.99
clflush size    : 64
cache_alignment    : 64
address sizes    : 45 bits physical, 48 bits virtual
power management:

E5-2650,2012 年 Q1 生产的,已经是很旧的机器了。

Linux 系统中,bc 命令是一个任意精度的计算器,如果用它计算圆周率,我们可以大概估算出 CPU 的浮点运算性能:

time echo "scale = 5000; 4 * a(1)" | bc -l -q

其中:

  1. time 用来计算执行时间;
  2. scale = 5000,表示精度为 5000,也就是计算圆周率小数点后的 5000 位;
  3. 4 * a(1),这个用来计算圆周率,1 的反正切是 π / 4;
  4. -l 定义使用的标准数学库;-q 不打印正常的 GNU bc 环境信息。

执行结果如下:

real    0m23.992s
user    0m23.983s
sys    0m0.003s

找了台苹果笔记本 Air,i5 的 CPU,耗时 20s,说明我电脑的单核性能比 Linux 的机器还快了一点。

不过,这个方法只适合粗略估算,如果要求精确,需要安装专业的性能测试套件。

坑一:迭代时协程引用索引和值

先看看下面的例子,你知道最终输出的结果是什么吗?

package main

import (
    "fmt"
    "time"
)

func main() {
    var m = []int{1, 3, 5}
    for i, v := range m {
        go func() {
            fmt.Println(i, v)
        }()
    }
    time.Sleep(time.Second)
}

阅读全文

今天遇到线上的一个问题:

我需要批量杀死某台机器的 PHP 进程,该怎么办?

注意,不是 php-fpm,是常驻任务。

如果是一个进程,那就好办了,ps -ef | grep php,找到 PID 然后 kill -9 PID……

那批量怎么搞呢?答案是 awk 命令。

阅读全文

最后更新时间 2021-10-05.

Linux 的命令太多,tcpdump 是一个非常强大的抓包命令。

有时候想看线上发生的一些问题:

  • nginx 有没有客户端连接过来……
  • 客户端连接过来的时候Post 上来的数据对不对……
  • 我的 Redis 实例到底是哪些业务在使用……

tcpdump 作为网络分析神器就派上用场了!

它本身的命令和参数有点多,我也简单记录下一些常用的操作。

网上的资料其实挺多(见文末),

但真的派上用场的,可能也就是我下面列出来的这几个 :)

抓取 eth0 网卡的 80 端口:

tcpdump -nnA 'port 80' -i eth0

阅读全文

公司的开发对生产环境都有普通用户 www 的权限,采用堡垒机登录到生产环境的机器。

默认 supervisor 使用 root 用户启动,开发没有权限直接修改配置和操作 supervisor 管理的进程,所以 supervisor 都采用 www 用户启动就解决问题了。

但是今天操作生产环境的时候,报的错误令人懵逼,SRE 同学折腾了好久,配置来配置去,搞不明白为啥 www 就是启动不了 supervisor !

报错信息是这样的:

[www@**************** ~]$ supervisord -c /etc/supervisord.conf
Error: Cannot open an HTTP server: socket.error reported errno.EACCES (13)
For help, use /usr/bin/supervisord -h

阅读全文

换到一个新的开发环境,蛮多东西要折腾的。特地整理了一下,下次换新电脑也方便。

git:

不使用 rebase,要加上这个设置:

git config --global pull.rebase false

全局配置工作用户名和邮箱,不然会影响到你提交代码:

git config --global user.name  "???"
git config --global user.email "???@???.com"

阅读全文