SeaweedFS使用 Last updated: 2022-09-22 15:19:12

之所以使用SeaweedFS,原因其实也很简单,看下面的主流产品对照表:

名称 开源协议 开发语言 star数量 官网地址 分布式 图片缩略图 TTL 加密 支持Unix-like 支持Windows 其他信息
SeaweedFS Apache 2.0 Golang 15.4k seaweedfs 2014年创立,新一代文件系统
HDFS Apache 2.0 Java 12.9k hadoop × × × Apache旗下的重型武器,但已显老旧,是Hadoop一部分,需要安装Hadoop才能使用,是上一代程序员们的最爱。
GlusterFS LGPL 3.0 C 3.8k glusterfs × × × × 号称一分钟就可以部署起来的一套文件系统
Ceph GPL v2.0、LGPL v2.1、LGPL v3.0等多重协议 C++ 3.8k ceph × × × 对Unix-like系统支持的很好,只支持Windows Server 2019和2016
MooseFS GPL v2.0 C 1.3k moosefs × × × × 号称支持PB级数据
MinIO是 AGPL v3.0、MinIO Commercial License Golang 35.4k minio 有挺有很不错的UI管理台,不要在你的产品中集成它的mc,否则你就得开源
FastDFS GPL v3.0 C 8.2k fastdfs × × × × 国内用的人挺多的,据说还是个中国人开发的

前后左右看了一圈,只能是SeaweedFS了。

SeaweedFS简介

SeaweedFS是一个分布式文件存储系统,基于Apache 2.0协议开源(可以基于其上开发商业闭源软件)。

Seaweed似乎可以翻译为海藻。但是请注意,这个当年的《蜗居》没什么关系。

SeaweedFS官方号称能够存储数十亿个文件,而且能够非常快速的存取。

SeaweedFS有两个服务器组成,一个是Master服务器,主要职责是管理文件卷,另外一个是卷服务器,主要用于存储文件元数据。这大大减轻了Master服务器的并发压力,因为这使得只需要一个磁盘进行读操作,另一个磁盘去完成写操作。

SeaweedFS的官方地址:SeaweedFS

SeaweedFS特性

  1. 可配置的复制级别
  2. 自动主服务器故障转移,即:没有单点故障
  3. 自动对文件进行gzip压缩,当然,压缩情况依赖于文件的具体类型
  4. 自动压实存储,即:删除或更新的文件空出来的磁盘空间会及时回收
  5. 自动TTL,即:自动过期机制
  6. 支持多磁盘存储空间向总存储空间添加,即:将零散空闲的磁盘空间聚集起来做成FS
  7. 添加删除服务器不会导致数据重新负载均衡,当然,管理员可以手动触发此操作
  8. 图片缩略图
  9. 支持为文件设置ETag、Accept-Range、Last-Modified等信息
  10. 可以在内存模式、存储模式、只读模式之间切换以达到性能最大化的要求
  11. 支持对可写卷和只读卷进行再平衡
  12. 可定义多个存储层和磁盘类型,以达到平衡性能和成本的目的
  13. 支持扩展第三方云存储让数据回暖
  14. 为热存储而实现的可擦除代码使得感知机架机制(Rack-Aware 10.4)能够降低存储成本并提高可用性

文件功能特性

  1. 文件服务器,通过HTTP协议访问文件和目录
  2. 文件TTL,文件的元数据和文件的实体数据都支持自动过期机制
  3. 通过FUSE直接访问存储在磁盘上的本地文件
  4. 同步复制功能,HA高可用
  5. 异步单路或多路复制以提升集群的可用性
  6. 支持S3
  7. 支持从Hadoop、Spark、Flink上访问文件甚至直接运行HBase
  8. 异步复制到云,使用专业化的手段异步复制到S3、Google Cloud、Azure、BackBlaze
  9. WebDAV,访问Mac和Windows或移动设备上的映射驱动器
  10. 支持加密存储,使用AES256-GCM加密
  11. 支持大文件,据说支持TB级
  12. 将通过云存储驱动挂载到本地集群中的方式,可以实现数据快速回写到云存储中
  13. 对挂载到本地的云存储中的对象进行远程操作, 对于上一点来说是可选的

Seaweed部署

Seaweed分为Master服务器和卷服务器。它是一种分布式文件存储系统,有多种集群部署方式。本例中,我们使用下面的部署拓扑图: Seaweed部署拓扑图

使用入门

启动Master服务器

./weed master

启动卷服务器

./week volumn -dir="/data/dir1" -max=5 -mserver="192.168.0.1:9333" -port=8080
./week volumn -dir="/data/dir2" -max=10 -mserver="192.168.0.1:9333" -port=8081

如果条件允许,你可以将Master服务器、各卷服务器分别部署在不同的服务器上,至少部署时指向到不同的磁盘上,就能实现性能最大化。

文件操作

上传文件

先发一个请求,获得一个文件ID(fid):

> curl http://localhost:9333/dir/assign
{"count":1,"fid":"3,01637037d6","url":"127.0.0.1:8080","publicUrl":"localhost:8080"}

再发送一个基于HTTP协议的multi-part的POST请求上传文件(请求的URL后面要加上文件ID):

curl -F file=@/home/chris/myphoto.jpg http://127.0.0.1:8080/3,01637037d6
{"name":"myphoto.jpg","size":43234,"eTag":"1cc0118e"}

删除文件

> curl -X DELETE http://127.0.0.1:8080/3,01637037d6

💡 说明: 此处的示例中返回的文件ID(fid)是3,01637037d63是存储文件的所在卷,逗号后面的01是文件的Key,再后面的637037d6是文件的cookie: - 存储文件的卷ID(此处是3),是一个32位的无符号整数 - 文件的Key(此处是01)是一个64位的无符号整数,以16进制形式返回 - 文件的cookie(此处是637037d6)是一个32位的无符号整数,以16进制形式返回 使用这些,是为了防止URL猜测。你可以以<volume id, file key, file cookie>的元组形式保存和使用这些数据,也可以统一存储为一个字符串去使用,如果要以字符串存储和使用,需要8+1+16+8=33个字节,所以在数据库中定义一个char(33)型的字段就够用了。

获取文件

首先,根据卷ID获得卷信息:

> curl http://localhost:9333/dir/lookup?volumeId=3
{"volumeId":"3","locations":[{"publicUrl":"localhost:8080","url":"localhost:8080"}]}

现在,就可以使用URL访问文件了:

http://localhost:8080/3,01637037d6.jpg

💡 说明: 1. 第一步查询卷ID时可能会返回多个卷(这表明文件存储在多个卷上),但是通常卷不会移动,所以你可以不必每次都来获取,你可以在你自己的业务系统中第一步请求的卷信息。 2. 第二步请求文件时,URL后面的.jpg是你加上去的(回顾一下前面上传文件时得到的文件ID是3,01637037d6,并没有.jpg),你加上去了,返回时就会再返回来,这样你就可以灵活便捷地指定文件类型了。

还可以以一种美化了的URL的形式获取文件:

http://localhost:8080/3/01637037d6/my_preferred_name.jpg
http://localhost:8080/3/01637037d6.jpg
http://localhost:8080/3,01637037d6.jpg
http://localhost:8080/3/01637037d6
http://localhost:8080/3,01637037d6

还可以通过在URL上传递参数实现对图片文件获取缩略图(这个功能是非常有用的):

http://localhost:8080/3/01637037d6.jpg?height=200&width=200
http://localhost:8080/3/01637037d6.jpg?height=200&width=200&mode=fit
http://localhost:8080/3/01637037d6.jpg?height=200&width=200&mode=fill

高级特性

文件自动过期(TTL)机制

假定我们想要上传一个文件,让它3分钟内有效,如前所述,先获取文件ID:

curl http://localhost:9333/dir/assign?ttl=3m
{"count":1,"fid":"5,01637037d6","url":"127.0.0.1:8080","publicUrl":"localhost:8080"}

现在,用这个文件ID上传一个文件:

curl -F "file=@./main.go" http://127.0.0.1:8080/5,01637037d6?ttl=3m

💡 说明: 1. 在有效期内,使用获取文件的方式请求时,会返回文件内容,如果在有效期之外了,会返回404(Not Found)并提示文件已丢失。 2. 您可能已经注意到两次请求都传了ttl=3m这个时间参数,第一次获取文件ID时传ttl=3m是让Master服务器选择匹配的卷,第二次上传文件时传ttl=3m是将这个过期时间和文件一起写入服务器保存起来。这种机制有一个好处是可以更加灵活的微调文件的TTL,同时减少卷的TTL变化量,最终简化了管理TTL卷。 3. 这些情况对你来说没有什么影响,它们也不一定要完全相同,只要第二次的时间大于第一次的时间就可以了。 4. 支持的TTL格式示例:3m(3分钟)、4h(4小时)、5d(5天)、6w(6周)、7M(7个月)、8y(8年)。

额外的技术细节(仅供了解):

  1. TTL似乎很容易实现,因为如果时间超过了TTL,Seaweed只需要报告文件不存在了即可。但是,真正的困难是从过期的文件中有效地回收磁盘空间,类似于JVM内存垃圾收集,这是一项精致的工作,并进行了许多人的努力。
  2. 最开始分配文件ID时,Master将会去寻找与TTL相匹配的卷,如果找到了,就直接返回,如果没找到,会先自动创建。
  3. 卷服务器会记录文件的过期时间,如果文件过期了,会报告文件不存在。
  4. 文件存入带有TTL的卷中后,如果该卷过期了,卷中的所有文件就都消失了。
  5. 如果试图将文件写入一个已经因为TTL过期而不存在的卷,将会报告404(Not Found),所以,请对文件上传操作的HTTP协议层状态进行判断,以确保结果是符合预期的。
  6. 卷服务器会追踪每个卷的最大过期时间,如果过期了,将不会再向Master服务器报告卷过期信息。
  7. 卷服务器如果发现卷过期之后又过了总过期时间的10%,或者已经过了10分钟,就会彻底删除该卷。
  8. 在生产环境下,如果TTL很长又有很多的文件使用这些过期时间,请注意分配好你的磁盘空间以防止出现磁盘满的错误,因为这些长时间不过期的却又带着过期时间的卷将会一直占用着磁盘空间。
  9. 建议不要将带和TTL和卷和不带TTL的卷混合部署在一个集群中,这是因为Master服务器默认指定集群中最大大小为30GB。
  10. 我们可以为每个TTL都指定一个最大配置,只不过这样做会比较麻烦,也许在以后我们会碰到这方面的强烈需求,到时候我们再进行优化。

其他补充

存取速度、数据热度,它们之间通常是有关联的,一般情况下是这样的:

NVME       > SATA SSD > Fast HDD >  Slow HDD > Cloud
Critical   > Hot      > Less Hot >  Warm     > Cold

从左往右,第一行是存储类型的速度由快到慢排列,第二行是数据状态排列。我们可以在启动Seaweed时通过命令行参数去设置。

其他内容正在研究中,有新的进展了再来补充。

nps内网穿透 Last updated: 2022-11-13 20:05:51

nps简介

1. 简介

一款轻量级、高性能、功能强大的内网穿透代理服务器。支持tcp、udp、socks5、http等几乎所有流量转发,可用来访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析、内网socks5代理等等……,并带有功能强大的web管理端。

nps是使用Golang语言开发的。源代码在这里:nps的Github地址

我们最常用的,就是用来做内网调试。请看下面的图: 内网穿透示意图.jpg

按照这张图的流程,当我们在我的计算机上向远程接口发起请求的时候,正常情况下,直达的请求,发出请求之后,远程服务返回接口响应,这一次请求就完成了。但是有许多业务它不是这样的简单的动作流程。例如: - 支付业务,你向远端发起请求之后,远程会在适当的时机回调你的接口,告诉你它的执行结果。换句话说,这个过程是异步的,你并不会立即得到结果。比如微信支付、支付宝支付,都是这样的。 - 认证登录业务,你向远程发起请求之后,传给远端一些数据,远端回调你的接口,告诉你认证成功了并登录进入你的系统。换句话说,这个过程是由多个步骤组成的,你完成远端接口的请求只是第一步,远程服务回调你的服务是第二步,第二步完成了,整个流程才结束。比如微信扫码登录你的网站。

对于这样的业务场景,如果我们的程序还在开发阶段,运行在我们的办公电脑上,远程服务就不能回调我了,因为我在内网,只拥有一个192.168.x.x开头的这样的内网私有IP。这个时候,nps这种能够实现内网穿透的工具,作用就很大了,对照上面这张图,简单的介绍一下原理: 1. 在我的云服务器ECS上,部署一套nps软件的服务器端,启动并运行它 2. 向互联网开放我的云服务器ECS上nps服务 3. 在我的办公计算机上安装一套nps软件的客户端,配置好并运行它 4. 此时,上图中的红色带圈的数字标识的4个步骤就完全打通了

具体做法我们继续往下看。

下载安装

2. 下载安装

nps有自己的官网地址:nps官网地址 但官网是使用文档,而且有完整的中文文档,这是非常不错的。在这里我们帮您省去逐项啃文档的麻烦,直接告诉你快速上手。 在Github的Release页面,https://github.com/ehang-io/nps/releases ,就可以下载相应的软件包了。

2.1 下载安装服务器端

本例中,我的服务器是CentOS,所以我的下载链接是https://github.com/ehang-io/nps/releases/download/v0.26.10/linux_amd64_server.tar.gz 下载之后,解压到/opt/nps目录下,然后在这个目录下执行./nps install指令,就可以完成安装。

2.2 下载安装客户端

客户端的安装更简单,下载解压即可,我的客户端是Windows电脑,所以我的下载链接是https://github.com/ehang-io/nps/releases/download/v0.26.10/windows_amd64_client.tar.gz ,如果你用的是Mac OS X,那么你的下载链接应该是https://github.com/ehang-io/nps/releases/download/v0.26.10/darwin_amd64_client.tar.gz

服务器端配置

3. 服务器端配置

服务器端安装好之后,要修改的配置项在文件/etc/nps/conf/nps.conf中,在这个配置文件中,我们主要配置以下几项内容:

3.1 运行模式配置

  • 运行模式,配置项:runmode,默认值dev,我们改成pro

3.1 配置IP和端口

  • http代理端口,配置项:http_proxy_port,默认值80,通常我们服务器上的80端口都已经占用了,或者不方便直接开放,我们在这里改为10080
  • https代理端口,配置项:https_proxy_port,默认值443,通常我们服务器上的443端口已经占用了,或者不方便直接开放,我们在这里改为10443
  • 桥接代理端口,配置项:bridge_port,默认值8024,这个端口我的服务器上空闲着,可以用,就不改了

3.2 配置Web管理端

  • Web管理端账号,配置项:web_username,默认值admin,不修改了
  • Web管理端密码,配置项:web_password,默认值123,太简单了,我这里修改一下,使用了一个相对复杂一点的密码,在这里就不公开展示了
  • Web管理端使用的端口,配置项:web_port,默认值8080,我的服务器上8080这个端口被占用了,我修改一下,使用18080

上述内容修改完成之后,执行指令nps reload即可立即生效,如果发现没能生效,那就先执行nps stop退出服务,再运行nps start启起来即可。

3.3 其他配置

nps还支持其他配置,如SSH、P2P、SOCKS5等,我们暂时用不到,就不配了,有需要的同学可以自行研究。

Web管理端配置

4. Web管理端

服务器端配置好了之后,就可以启动起来了,之后使用IP+端口进入: nps_首页.jpg

在登录页面输入账号和密码即可进入。

🎈Github上有一波大神,发现nps更新不够及时,就fork出了一个新项目,https://github.com/yisier/nps 基于此项目增加了一系列的优化,比如登录的时候除了账号密码,还需要验证码,大家有兴趣也可以自行研究。

创建客户端

进入Web管理端之后,点击左侧的客户端,再点击新增按钮,即可创建客户端,如下图所示: nps_新增客户端.jpg

字段说明:

  • 备注,就是客户端的描述信息,随意填写
  • Basic认证用户名和密码,别人请求我们的公网IP或域名+端口时,需要输入密码
  • 唯一验证密钥,客户端连接的时候,也要提供同样的密钥,否则就会连接失败,空着,让nps自动生成即可
  • 允许客户端通过配置文件连接,一定要选择是,否则客户端就不能用配置文件了
  • 压缩,选择是,可以节省流量加快网络传输速度,当然,如果外部公有服务连接我们自己的公网IP或域名时走了类似于nginx代理,而代理层已经压缩了,就没必要再压缩了
  • 加密,选择是,可以防止数据泄密

创建隧道

在客户端管理页面,点击隧道,即可打开该客户端的隧道配置,如下图所示(可能因为nps版本不同而略有变化): nps_隧道.jpg

我们想要完成远程服务调用自己的服务器IP或域名+端口并穿透到本机,就要开启TCP协议的隧道,如上图所示配置一下就好了,其中的端口,指的是服务器端的端口。目标也就是本机,在上图中的第2行(ID为238)的记录为例说明,比如我要调试微信支付功能,微信支付功能回调到我的服务器IP 1.2.3.4:10000,然后被nps所接受并转发透传到我本地的开发机器的8686端口,于是一个腾讯的请求就进入了我的开发环境的机器,我就可以继续开发收到用户付款时的回调业务逻辑了。(此处的配置信息仅作示例说明,具体配置时请以你的服务器的IP、端口、以及本机服务程序开启的端口为准)

客户端配置

5. 客户端配置

客户端配置运行有两种,一种是直接在命令行上带上参数启动客户端主程序,另外一种是将客户端要用的参数放在配置文件中保存好,然后主程序不带任何命令行参数直接运行。 两种方式都挺方便的,如果觉得每次都要输入命令行参数比较麻烦, 要么修改配置文件然后直接启动主程序(只需要一次保存即可),或者将启动命令写成一个批处理脚本,然后可双击运行,都很方便。

5.1 客户端带命令行参数运行

在Web管理端中的客户端列表中,找到自己配置好的客户端,该行客户端信息的行首位置有一个加号图标,点击它,就会展示客户端运行的相关信息,将其中的指令复制下来,然后直接开命令行终端(CMD),运行即可。如图所示: nps_运行客户端.jpg

5.2 客户端带配置文件运行

这种方式更简单,到客户端主程序所在目录,然后找到conf目录下npc.conf配置文件,打开该配置文件,填写好服务端的IP或域名和端口(配置项是server_addr),以及在Web管理端生成的vkey密钥(配置项是vkey),再配置目标(tcp块下的target_addr),再配置服务器端口(配置项server_port)保存,然后直接运行npc.exe就可以了。

客户端程序不是nps.exe,而是npc.exe。

5.3 意外错误

但是:许多人(包括我)在运行官方程序生成的标准配置时会碰到以下错误:

PS E:\apps\nps> .\npc.exe
2022/11/08 22:29:35.536 [I] [npc.go:231]  the version of client is 0.26.10, the core versio
n of client is 0.26.0
2022/11/08 22:29:35.558 [I] [control.go:97]  Loading configuration file E:\apps\nps\conf\np
c.conf successfully
2022/11/08 22:29:36.166 [I] [local.go:74]  start local file system, local path /data/nps, s
trip prefix /web/ ,remote port 19008
2022/11/08 22:29:36.197 [N] [control.go:176]  web access login username:user password:1234
2022/11/08 22:29:36.198 [I] [local.go:115]  successful start-up of local tcp monitoring, po
rt 0
2022/11/08 22:29:36.199 [I] [local.go:115]  successful start-up of local tcp monitoring, po
rt 2001
2022/11/08 22:29:36.333 [I] [client.go:72]  Successful connection with server 39.101.78.43:
8024
2022/11/08 22:29:37.197 [N] [local.go:142]  try to connect to the server 1
2022/11/08 22:29:37.374 [E] [control.go:290]  strconv.Atoi: parsing "": invalid syntax
2022/11/08 22:29:37.375 [E] [control.go:310]  strconv.Atoi: parsing "": invalid syntax
2022/11/08 22:29:37.376 [E] [local.go:206]  strconv.Atoi: parsing "": invalid syntax
2022/11/08 22:29:37.378 [N] [local.go:142]  try to connect to the server 2
2022/11/08 22:29:37.379 [E] [control.go:290]  strconv.Atoi: parsing "": invalid syntax
2022/11/08 22:29:37.380 [E] [control.go:310]  strconv.Atoi: parsing "": invalid syntax
2022/11/08 22:29:37.381 [E] [client.go:126]  strconv.Atoi: parsing "": invalid syntax
2022/11/08 22:29:37.609 [E] [control.go:290]  strconv.Atoi: parsing "": invalid syntax
2022/11/08 22:29:37.611 [E] [control.go:310]  strconv.Atoi: parsing "": invalid syntax
2022/11/08 22:29:37.612 [E] [client.go:126]  strconv.Atoi: parsing "": invalid syntax
2022/11/08 22:29:37.611 [E] [local.go:206]  listen udp 192.168.125.4:55540: bind: Only one
usage of each socket address (protocol/network address/port) is normally permitted.
2022/11/08 22:29:37.614 [N] [local.go:142]  try to connect to the server 3
2022/11/08 22:29:37.804 [E] [local.go:206]  listen udp 192.168.125.4:55540: bind: Only one
usage of each socket address (protocol/network address/port) is normally permitted.

错误消息会快速循环滚动,解决办法很简单,将配置文件中的下面的内容

[p2p_ssh]
local_port=2002
password=ssh3
target_addr=123.206.77.88:22

注释掉就可以了(每一行前面加个#号即可)。至于为什么,官方没有明确答复,就说如果出错了,请删除配置文件,似乎不怎么合理,但是不管他了,能用就行,具体信息在这里:https://github.com/ehang-io/nps/issues/688 有兴趣的同学可以再去研究研究。

扩展阅读

6. 扩展阅读

nps是一款非常强大的工具,不仅支持内网穿透,还支持正向代理、反向代理、VPN等等,所以,某些杀毒软件会报毒,但是它是开源软件,大家可以放心使用,没问题的。

frps内网穿透 Last updated: 2022-12-15 21:32:21

简介

frps是比nps更优秀的内网穿透工具。

配置用法

2. 配置

服务器端frps.ini文件配置模板:

[common]
bind_addr = 0.0.0.0
# frps的工作端口,客户端通过此端口访问服务器端
bind_port = 17000
# 密钥,生成一个复杂点的比较好
auto_token = 12345678
# 允许客户端在这个IP端口范围内连接以实现透传,防止客户端随意连端口造成问题或安全隐患
allow_ports = 19000-19100

# 控制台相关配置
dashboard_port = 17500
dashboard_user = admin
dashboard_pwd = my_frp_admin_123!@#

# 附加配置
max_pool_count = 5
max_ports_per_client = 0
enable_prometheus = true
log_file = ./frps.log

客户端frpc.ini配置文件模板:

[common]
# 服务器IP
server_addr = 1.2.3.4
# 服务器上frps的工作端口
server_port = 17000
auto_token = 12345678
tls_enable = true

log_file = ./frpc.log

[ssh]
# 连接方式,这个一般不会变
type = tcp
# 准备透传到本地私有网络中的哪个IP
local_ip = 127.0.0.1
# 准备透传到本地私有网络中的哪个端口
local_port = 8686
# 远程frps给客户端使用的端口,通过此端口实现透传,如果服务器端定义了allow_ports,这个端口要符合要求
remote_port = 19000

补充说明

3. 补充说明

客户端启动时连不上服务器,显示类似于这样的错误日志:

2022/11/17 16:04:21 [W] [service.go:132] login to server failed: EOF

检查客户端的配置文件中有没有tls_enable = true,如果没有,加到common节点下。

程序版本:3.1.3 页面加载:14.916106ms