提到
SaaS,很多人都会立刻想到节约成本、按需付费、即租即用等等这些概念,这说明大部分人对
SaaS 已经有了普遍认知,且开始主动应用 SaaS
软件。然而这只是一些浅层概念。很多人对于一些 SaaS
技术问题还是知之甚少,例如企业在进行 SaaS
企业管理软件选型时,仍不了解“多租户”与“单租户”是什么意思,二者之间的区别更是一头雾水。企业管理者需要明白这两种
SaaS
架构的特点,才能更多地从未来的功能需求、数据安全等方面进行考虑,从而选出适合企业应用的
SaaS 软件。
本文将通过举例,形象深刻解释“SaaS 多租户和单租户有什么分别”。
一、多租户 SaaS 架构
小 A、小 B、小 C
大学毕业后,一起同租了一套三室两厅的房子。三个人都拥有自己独立的房间,且每个房间都有配有一把钥匙,保证三个人独立的空间私密性。如果其他人要进入别人的房间,就需要拥有配套房间的钥匙进行开锁。而客厅、餐厅、厨房等属于公共区域,三人共同享有这些资源。
这里小 A、小 B、小 C 就属于应用 SaaS
多租户解决方案的企业实体。应用运行在同一个或同一组服务商(即三个人同租一套房子,厨房、餐厅、客厅 ...
背景
随着互联网、大数据、云计算、人工智能、物联网、区块链等一系列技术创新与行业服务的加速融合,行业产品创新能力正在不断提升,数字化、智能化不断催生新兴的服务模式和新产品,已成为企业数字化转型升级的新方向。
企业用户采购 API
网关作为企业自身数字化转型的一环,为后续持续转型和升级做铺垫,逐步向“全面云化”、“分布式化”、“智能化”、“开放化”的新技术体系演进。云原生
API 网关 Apache APISIX,可以完美的助力企业完成 API
管理和微服务架构转型。此外基于开源 APISIX 还有 k8s Ingress Controller 和
Service Mesh 产品,企业用户后续升级到 Kubernetes
和服务网格,提供统一、顺滑的过渡方案。底层技术栈的统一,极大降低学习、管理维护成本。
同时,在云原生架构下,开源 +
购买商业支持的方式是首选,这不仅仅保证企业自身不被具体商业公司锁定,更重要的是,可以让企业保持快速的技术升级,以便让技术满足产品的迭代,
最终在竞争中取得优势。
APISIX 是 Apache
基金会的顶级项目,同时也在云原生软件基金会(CNCF)的全景 ...
wrk 是一个非常棒的 HTTP 压力测试工具,构建在 Redis、NGINX、Node.js 和
LuaJIT 这几个开源项目的基础之上,充分利用了他们在事件驱动、HTTP
解析、高性能和灵活性方面的优点,并且可以自己写 Lua
脚本来生成测试请求。
虽然 wrk
没有测试案例,并且作者大概一年现身一次来合并代码,但这些并不妨碍我们把
wrk 作为性能测试和 fuzz 测试的首选工具。如果你还在使用多线程的
ab,那么非常值得尝试下 wrk。
下面是 wrk 结果中的延时分布统计部分:
123456789Latency Distribution 50% 1.20ms 75% 595.78ms 90% 899.11ms 99% 1.00s
这个示例是指,50% 的请求在 1.2ms 内完成,90% 的请求在 899 ms
内完成,99% 的请求在 1s 内完成。
我们在使用 wrk 压力测试自己产品的时候,发现 wrk
统计的延时结果中,大部分请求都是几毫秒内完成,但有一小部分请求的延时会超过
100 毫秒。 对于用 OpenResty
构建的系统,出现 ...
Apache APISIX 和 Kong 都是开源的微服务 API
网关,那么在这两者之间,如何去做比较和选择呢?
这两个项目都有完善的文档和测试来覆盖,也有不少的生产用户在使用,所以不用去担心稳定性和它们的可持续发展,本文会从功能和性能这两个最直接和可验证的角度去做下对比。
功能
从 API 网关核心功能点来看,两者均已覆盖:
功能
Apache APISIX
KONG
动态上游
支持
支持
动态路由
支持
支持
健康检查和熔断器
支持
支持
动态 SSL 证书
支持
支持
七层和四层代理
支持
支持
分布式追踪
支持
支持
自定义插件
支持
支持
REST API
支持
支持
CLI
支持
支持
更详细的比较:
功能
Apache APISIX
KONG
项目归属
Apache 软件基金会
Kong Inc.
技术架构
Nginx + etcd
Nginx + postgres
交流渠道
微信群、QQ 群、邮件列表、GitHub、meetup
GitHub、论坛、freenode
单核 QPS (开启限流和 prometheus 插件)
18000
1700
平均延迟
0.2 毫 ...
Apache APISIX 是一个很年轻的项目,2019 年 6 月份开源,7 月份加入到
CNCF 全景图,10 月份进入 Apache 孵化器,所以我会和大家分享一下 APISIX
是如何从 0 到 1,进入 Apache 孵化器的。
Apache APISIX 现在有 17 个 committer,分别来自 16
家不同的公司,是一个非常社区化的项目。每个 committer
有一票,决定版本的发布、选举新的 committer 和 PPMC
等比较重大的事情。
Apache Way
Apache Way 是大家都比较熟悉的概念:社区大于代码。烂代码可以改,Apache
的导师并不会指导你怎么写出更高水平的代码,他们更关心的是社区是否在健康的发展,只要有一个好的社区,烂代码一定会有更高水平的人进行重构,变成更好的代码。所以只要社区在,那这个项目就能够一直存活下去,这在
Apache 是最重要的。
邮件列表优先是另一个重要的点,没有在邮件列表中出现过的,就当做不存在。这在中国其实是一个非常大的挑战,大家在文化上和习惯上都不太喜欢用邮件:第一是时间不够及时,可能发一封邮件后隔
1-2 ...
wctype.h
wctype.h 提供 ctype.h 里面函数的宽字符版本。
宽字符类型判断函数
下面函数判断宽字符的类型。
iswalnum() 测试宽字符是否为字母数字
iswalpha() 测试宽字符是否为字母
iswblank() 测试这是否是一个宽空白字符
iswcntrl() 测试这是否是一个宽控制字符。
iswdigit() 测试这个宽字符是否是数字
iswgraph() 测试宽字符是否是可打印的非空格字符
iswlower() 测试宽字符是否为小写
iswprint() 测试宽字符是否可打印
iswpunct() 测试宽字符是否为标点符号
iswspace() 测试宽字符是否为空格
iswupper() 测试宽字符是否为大写
iswxdigit() 测试宽字符是否为十六进制数字
wctype(),iswctype()
iswctype()是上一节各种宽字符类型判断函数的通用版本,必须与wctype()配合使用。
1int iswctype(wint_t wc, wctype_t desc);
iswctype()接受两个参数,第一个参数是一个需要判断类型的宽字 ...
wchar.h
宽字符使用两个或四个字节表示一个字符,导致 C
语言常规的字符处理函数都会失效。wchar.h
定义了许多宽字符专用的处理函数。
类型别名和宏
wchar.h 定义了一个类型别名 wint_t,表示宽字符对应整数值。
wchar.h 还定义了一个宏 WEOF,表示文件结束字符 EOF 的宽字符版。
btowc(),wctob()
btowc()将单字节字符转换为宽字符,wctob()将宽字符转换为单字节字符。
12wint_t btowc(int c);int wctob(wint_t c);
btowc()返回一个宽字符。如果参数是
EOF,或转换失败,则返回 WEOF。
wctob()返回一个单字节字符。如果参数是
WEOF,或者参数宽字符无法对应单个的单字节字符,则返回 EOF。
下面是用法示例。
123456789wint_t wc = btowc('B'); // 输出宽字符 Bwprintf(L"Wide character: %lc\n", wc);unsigned char c = wctob(wc);// 输出 ...
time.h
time_t
time_t 是一个表示时间的类型别名,可以视为国际标准时
UTC。它可能是浮点数,也可能是整数,Unix 系统一般是整数。
许多系统上,time_t 表示自时间纪元(time epoch)以来的秒数。Unix
的时间纪元是国际标准时 UTC 的1970年1月1日的零分零秒。time_t
如果为负数,则表示时间纪元之前的时间。
time_t
一般是32位或64位整数类型的别名,具体类型取决于当前系统。如果是32位带符号整数,time_t
可以表示的时间到 2038年1月19日03:14:07 UTC
为止;如果是32位无符号整数,则表示到2106年。如果是64位带符号整数,可以表示-2930亿年到+2930亿年的时间范围。
struct tm
struct tm
是一个数据结构,用来保存时间的各个组成部分,比如小时、分钟、秒、日、月、年等。下面是它的结构。
1234567891011struct tm { int tm_sec; // 秒数 [0, 60] int tm_min; // 分钟 [0, 59] int tm_hour ...
string.h
string.h主要定义了字符串处理函数和内存操作函数。
字符串处理函数
以下字符串处理函数,详见《字符串》一章。
strcpy():复制字符串。
strncpy():复制字符串,有长度限制。
strcat():连接两个字符串。
strncat():连接两个字符串,有长度限制。
strcmp():比较两个字符串。
strncmp():比较两个字符串,有长度限制。
strlen():返回字符串的字节数。
strchr(),strrchr()
strchr()和strrchr()都用于在字符串中查找指定字符。不同之处是,strchr()从字符串开头开始查找,strrchr()从字符串结尾开始查找,函数名里面多出来的那个r表示
reverse(反向)。
12char* strchr(char* str, int c);char* strrchr(char *str, int c);
它们都接受两个参数,第一个参数是字符串指针,第二个参数是所要查找的字符。
一旦找到该字符,它们就会停止查找,并返回指向该字符的指针。如果没有找到,则返回
NULL。
下面是一个例子。
12 ...
stdio.h
stdio.h是 C 语言的标准 I/O
库,用于读取和写入文件,也用于控制台的输入和输出。
标准 I/O 函数
以下函数用于控制台的输入和输出。
printf():输出到控制台,详见《基本语法》一章。
scanf():从控制台读取输入,详见《I/O 函数》一章。
getchar():从控制台读取一个字符,详见《I/O 函数》一章。
putchar():向控制台写入一个字符,详见《I/O 函数》一章。
gets():从控制台读取整行输入(已废除),详见《I/O 函数》一章。
puts():向控制台写入一个字符串,详见《I/O 函数》一章。
文件操作函数
以下函数用于文件操作,详见《文件操作》一章。
fopen():打开文件。
fclose():关闭文件。
freopen():打开一个新文件,关联一个已经打开的文件指针。
fprintf():输出到文件。
fscanf():从文件读取数据。
getc():从文件读取一个字符。
fgetc():从文件读取一个字符。
putc():向文件写入一个字符。
fputc():向文件写入一个字符。
fgets():从文件读取整行 ...
