整理了一整套关于FastDFS相关的资料,关注公众号:程序新视界,回复“011”获得完整版PDF文档。

在某些操作系统下,比如MacOS下,基于Docker部署之后,使用客户端连接进行上传或下载文件时,会出现类似can’t create connection to 172.17.0.1:23000或connect time out这样的异常。

原因

引起该异常在主要原因就是同一服务器下的storage注册到tracker时注册的是容器的内网ip,此时客户端进行访问很显然无法成功。

FastDFS

上图解释了整个过程中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

FastDFS

可以看出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,解决跨机房或混合云部署问题。

连接规则:

  1. storage连接storage server,优先尝试连接内网IP,失败了再尝试连接外网IP。
  2. 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



FastDFS基于Docker部署storage映射IP问题汇总插图2

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:https://choupangxia.com/2020/07/29/fastdfs-docker-storage-ip-mapping/