注意,以下的信息仅截止于2024年1月26,后续可能会有变化。 以下顺序不代表排名。
下面的内容主要是免费的一些云服务资源,具体有:
- 计算资源
- Serverless函数
- 容器
- 数据
- KV
- Redis
- MySQL
- MongoDB
- Kafka
注意,以下的信息仅截止于2024年1月26,后续可能会有变化。 以下顺序不代表排名。
下面的内容主要是免费的一些云服务资源,具体有:
起因是这样的,Code Review的时候看到了下面这段Golang的代码:
package main
import "fmt"
func download() error {
fmt.Println("download")
return fmt.Errorf("download error")
}
func main() {
times := 3
var tryDownload func() error
tryDownload = func() error {
if times == 0 {
return fmt.Errorf("exceed max times")
}
err := download()
if err == nil {
return nil
}
times--
return tryDownload()
}
tryDownload()
fmt.Println("last times", times)
}
大致意思是尝试下载三次。
由于被Golang的闭包坑过,所以当时给的Code Review的意见是改成for loop
的方式,避免闭包捕获可能导致的问题。
CGO是Go程序调用C库的一套机制,可以使Go语言能够站在C/C++的肩膀上。比如Go调用Tensorflow,也就是使用了CGO来实现的。很多语言都支持对C库的调用,一般称为FFI(Foreign Function Interface)。这里需要注意一下,一般的Python、Lua等语言调用C函数的时候,是通过函数签名找到函数的地址,然后直接调用对应的函数。而CGO会先生成中间文件,然后再一起编译调用。这里不具体展开了,总之只需要知道CGO比一般的FFI多了一层中间的步骤。在程序出错的时候,能理解调用栈的关系即可。参考 CGO 和 CGO 性能之谜。
package main
/*
CGO的标准写法:
1. 先用注释的方式写入,单行注释和多行注释都支持
1.1 编译器环境变量
1.1.1 CFLAGS: C编译选项
1.1.2 CXXFLAGS: C++编译选项
1.1.3 CPPFLAGS: C和C++共有的编译选项
1.1.4 FFLAGS: Fortran编译选项
1.1.4 LDFLAGS: 链接选项(不区分C和C++)
1.2 C代码
2. import "C",相当于将所有的C函数放入虚拟的package C。之后通过`C.xxx`的方式来调用。需要紧跟注释之后。
*/
/*
#cgo LDFLAGS: -lm
#include <math.h>
double my_sqrt(double x) {
return sqrt(x);
}
*/
import "C" // CGO的标准写法,相当于将C函数放入包`C`中
import "fmt"
func main() {
a := 100
fmt.Printf("sqrt(%v) = %v\n", a, C.my_sqrt(C.double(a))) // 调用上面自定义的函数
fmt.Printf("sqrt(%v) = %v\n", a, C.sqrt(C.double(a))) // 调用系统库函数(上述的m)
}
// Output:
// sqrt(100) = 10
// sqrt(100) = 10
通过上述的例子,我们可以看出,CGO可以调用C的库函数,也可以执行注释中的C代码的函数。一般注释中的C代码都是比较简短的。
接下来要介绍C和Go之间的数据是如何传递的。
Read More...本文主要是在看《Inside the C++ Object Model》的时候,想通过案例的方式加深一下理解。
首先,由于编译器有内存对齐的优化,比如:
#include <iostream>
class WithAlign {
int a;
char b;
};
#pragma pack(push, 1)
class WithoutAlign {
int a;
char b;
};
#pragma pack(pop)
int main() {
std::cout << "WithAlign: " << sizeof(WithAlign) << std::endl;
std::cout << "WithoutAlign: " << sizeof(WithoutAlign) << std::endl;
}
// Output:
// WithAlign: 8
// WithoutAlign: 5
内存对齐的类大小为8(按int 4字节对齐),未对齐的为5(int + char)。这里为了更容易理解,全部默认使用1字节对齐。
注意,本文中的内容均仅在自己的机器的Docker容器中做测试,环境为:64位 ubuntu 16.04, gcc 5.5。
# lsb_release -a
Distributor ID: Ubuntu
Description: Ubuntu 16.04.7 LTS
Release: 16.04
Codename: xenial
# uname -a
Linux 06f25c7abffd 5.15.49-linuxkit #1 SMP Tue Sep 13 07:51:46 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
# gcc --version
gcc (Ubuntu 5.5.0-12ubuntu1~16.04) 5.5.0 20171010
引用《深度探索C++对象模型》这本书中的话:
有两个概念可以解释C++对象模型:
这里主要介绍服务端架构工作中的一些常见的概念和指标,在我们部署、上线等运维工作时,方便排查问题,以及交流时的语义一致。
一般在谈论服务和调用关系的时候,我们会使用上游和下游来表示服务间的相关依赖。但是对于上下游的定义,会视情况而定的。
Stack Overflow上有个相同的问题:definition - Upstream / downstream terminology used backwards? (E.g. nginx) - Stack Overflow
Read More...为什么IDL的介绍也放在这里呢?一方面是我想不到放哪里,另一方面是之前说到,“架构”即“设计”,那么IDL、RPC框架也算是设计的一部分。不合理的选型在后续维护上会带来不小的麻烦。
本文主要介绍我用过的一些IDL,并结合真实案例,分析他们的优劣。
Read More...本来是打算写一篇介绍我目前工作中有意思的设计的博客,写着写着发现设计的知识点还是有点多的,因此这里单独增加一栏,用来不断的更新相关的内容。
由于工作的变化,我从图像算法和框架,转向了服务端架构。做服务端架构,相较于算法和sdk框架,有着挺大的区别。而适应这一变化,确实需要花费挺长的时间,也学习到很多。
服务端的概念很多,很难在一本书上找到所有的答案,平时也只能自己多问多摸索。
这里总结了一下日常遇到的有意思的概念和技巧,希望耐心看完本文的你能够更快速的理解服务端的概念和开发过程。不至于在入职时每次讨论都一脸懵逼。
另外,我会在各部分的章节中,插入一些工作中遇到的真实案例。事实上,由于这些案例太过有意思,让我忍不住分享出来,所以才有了本文。(本文的目录也是根据这些案例归纳出来的。)
Read More...本文主要是《Redis设计与实现》的第一部分的总结,内容为数据结构和对象。这里类比了C++ STL中的数据结构,便于理解。
Redis是使用C语言编写的,C语言本身没有复杂的数据结构。因此Redis自己实现了一套底层的数据结构,这些数据结构作为工具被Redis的其他模块使用。
Read More...