FastDFS基于Docker部署storage映射IP问题汇总
整理了一整套关于FastDFS相关的资料,关注公众号:程序新视界,回复“011”获得完整版PDF文档。
在某些操作系统下,比如MacOS下,基于Docker部署之后,使用客户端连接进行上传或下载文件时,会出现类似can’t create connection to 172.17.0.1:23000或connect time out这样的异常。
原因
引起该异常在主要原因就是同一服务器下的storage注册到tracker时注册的是容器的内网ip,此时客户端进行访问很显然无法成功。
上图解释了整个过程中ip的注册和使用情况。
正常情况容器启动时已经把storage.conf的配置文件里面的tracker_server地址替换为FASTDFS_IPADDR=192.168.1.98参数的地址,也就是说storage是连接到tracker server 的地址是192.168.1.98:22122,按道理storage注册到tracker server的地址应该也是192.168.1.98。
进入容器查看tracker server的信息。
[root@localhost ~]# docker exec -it test-fast /bin/bash
[root@854ce848546a /]
# /usr/bin/fdfs_monitor /etc/fdfs/storage.conf
可以看出tracker server记录到storage的地址是docker0 虚拟网卡(172.17.0.1)的地址。
解决方案
这里汇集了网络上大多数解决方案,可根据具体情况进行尝试。
操作系统
该问题出现的主要核心因素之一便是storage和tracker在同一台服务器内。如果有条件,将storage和tracker放置在两台服务器,问题就可以解决。
同时,也不是所有的在同一台服务器内就会出现这种情况。有的Linux操作系统并不会出现,而本人验证MacOS系统是会出现这种情况的。
所以,如果有可能,放置于两台服务,基本上就可以解决大部分问题。这个方案是从根源删解决。
配置iptables
通过iptables的转发功能,比如,数据达到172.17.0.2的22122端口记录的源地址是172.17.0.1,我们只需要修改iptables的NAT表规则,所有转发到172.12.0.2:22122的数据,源地址修改为宿主主机的地址:192.168.1.98,这样storage注册到tracker server时,tracker server获取到storage的ip地址为192.168.1.88 而不是网关地址172.17.0.1。
iptables -t nat -A POSTROUTING -p tcp -m tcp --dport 22122 -d 172.17.0.2 -j SNAT --to 192.168.1.98
这种解决方案适用于Linux操作系统,而针对MacOS系统是无效的。因为MacOS下并不存在iptables。
docker网络映射
如果是Linux操作系统,还可以在启动docker容器时使用–network=host来进行映射。启动示例如下:
docker run -d --network=host --name tracker -v /Users/zzs/develop/temp/tracker:/var/fdfs delron/fastdfs tracker
如果容器使用’host’网络驱动,意味着容器共享宿主机网络栈,双方在网络名称空间并没有隔离。在容器中可以看到host的所有网卡,并且连hostname也是host的。
使用Docker host的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,则可以选择host网络。不便之处就是要考虑端口冲突问题,Docker host上已经使用的端口就不能再用了。
而这种解决方案适用于Linux操作系统。由于MacOS不支持–network=host模式,所以该解决方案在MacOS下无效。
双IP
在FastDFS 6.0版本以后支持双IP配置,也就是针对storage_ids.conf进行配置。笔者对该种方案的实践并没有成功,而且需要升级FastDFS。
v6.0新增特性说明如下:支持双IP,一个内网IP,一个外网IP,支持NAT方式的内网和外网双IP,解决跨机房或混合云部署问题。
连接规则:
- storage连接storage server,优先尝试连接内网IP,失败了再尝试连接外网IP。
- client向tracker server获取storage server IP,tracker server采用规则如下:外网过来的请求,返回外网IP;内网过来的请求,返回内网IP。
Client临时解决
如果你只是在使用测试环境,也就是说storage只有一台服务,对应一个ip,此时可在使用fastdfs-client的时候进行指定storage server的ip信息,而不采用tracker返回的。
Java版本可打包官方提供的client,然后通过pom依赖引入:
<dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</artifactId> <version>1.29-SNAPSHOT</version> </dependency>
官网的client源码地址如下:https://github.com/happyfish100/fastdfs-client-java
由于官网的client源码在命名规范,异常,日志,配置文件等方面有不少问题,个人从官网fork一个版本之后,进行优化升级的版本也可参考使用,后期逐步升级:https://github.com/secbr/fastdfs-client-plus
引入依赖之后,初始化client时,设置storage的ip的部分代码示例如下:
private static TrackerClient trackerClient; private static TrackerServer trackerServer; private static StorageServer storageServer; private static StorageClient1 storageClient; static { try { ClientGlobal.init(CONF_FILE); trackerClient = new TrackerClient(); trackerServer = trackerClient.getTrackerServer(); // storage server非线程安全,如非必须,不建议使用storage server // 因为本人测试环境通过docker不会,无法正确获取storageServer的地址信息,因此进行初始化配置 storageServer = new StorageServer("127.0.0.1", 23000, 0); storageClient = new StorageClient1(trackerServer, storageServer); System.out.println("初始化配置信息:" + ClientGlobal.configInfo()); } catch (Exception e) { logger.error("初始化FastDFSClient异常", e); } }
正常情况下创建StorageClient1时并不需要传递storageServer,也就是storageServer为null,但如果需要临时解决该问题,则可在此处传递指定的ip地址。
这种方案不建议在生产中使用,否则storage无法横向扩展。
如果想采用此方案又想确保storage的横向扩展,可针对StorageServer的ip采用反向代理(比如采用Nginx),然后通过反向代理来分发具体的storage请求,但这同样的每次新增storage都需要修改反向代理配置,无法达到tracker的调度作用。
参考文章:
https://www.cnblogs.com/zzsdream/p/11199374.html
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接
本文链接:https://choupangxia.com/2020/07/29/fastdfs-docker-storage-ip-mapping/