通过上一篇文章,我们了解了fastdfs 的安装,文章的最后遗留了 fastdfs 可能遇到的问题,接下来会详细探讨下这些问题,并给出相应的解决方案
先了解下 fastdfs 的上传过程
java集成fastdfs-client上传文件到服务器
client 上传过程中,先获取到可用的storage 的ip和端口,这里获取到的ip和端口是fastdfs 服务器上 storage 配置文件中设置的ip 地址和端口
其中 tracker_server 的ip设置 如果是内网 那么client获取到的storage ip 为内网
如果设置的是外网那么获取到的storage ip 为外网
1、fastdfs 部署与外网服务器,其配置使用的是外网,非内网Client 可以上传了 但会出现同组内 Storage 文件 不同步
由上可知 当 其配置使用的是外网 那么不管 client 部署在内网 还是外网 都是可以上传文件了,这样线下的测试环境也是可以上传文件了
但是当我们 查看Storage和Tracker是否在通信 时
/usr/bin/fdfs_monitor /etc/fdfs/storage.conf
会发现
同组间storage 的文件同步出现了问题
last_synced_timestamp = 2019-07-17 16:32:31 (never synced)
这是因为 同组间的storage 在文件同步时 会获取内网ip对应的storage,但是这里设置的是外网ip地址,所以同步时会 报错 (报错信息这边没有贴出来) 大概意思 就是 :
获取不到 ip(内网):端口 对应的storage
然而我们想要的是 设置的是外网,同步时获取的也是外网,这个目前还不知道有没有相关的配置项可以设置,那么如果想改的话就只能改源码了,可行性不大(不建议),所以我们会想着将设置的ip 设为内网,这样的话就能够获取到 可用的 storage 了,那么同组间的同步就没有问题了
如果fastdfs 部署与外网服务器,其配置使用的是内网,那么 非内网Client 无法上传
由上,当配置的ip 为内网时 文件同步问题解决了,
这时 client 在上传文件时:
- 同局域网内 client 上传,没有任何问题
- 非局域网,如(线下测试环境),获取到的storage 为 内网地址是无法上传的
下面提供一种解决方案
client 上传时 将获取到的内网 storage ip 替换成相应的外网ip
解决步骤
1 在配置文件中加入
fastdfs.inner_out_net=内网ip:外网ip,内网ip:外网ip
这里是storage 的地址,多个storage 用逗号隔开
格式 内网:外网,内网:外网
2 修改 fastdfs-client-java jar 中的 ClientGlobal
package org.csource.fastdfs;
import org.csource.common.IniFileReader;
import org.csource.common.MyException;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.*;
/**
* Global variables
*
* @author Happy Fish / YuQing
* @version Version 1.11
*/
public class ClientGlobal {
public static final String CONF_KEY_CONNECT_TIMEOUT = "connect_timeout";
public static final String CONF_KEY_NETWORK_TIMEOUT = "network_timeout";
public static final String CONF_KEY_CHARSET = "charset";
public static final String CONF_KEY_HTTP_ANTI_STEAL_TOKEN = "http.anti_steal_token";
public static final String CONF_KEY_HTTP_SECRET_KEY = "http.secret_key";
public static final String CONF_KEY_HTTP_TRACKER_HTTP_PORT = "http.tracker_http_port";
public static final String CONF_KEY_TRACKER_SERVER = "tracker_server";
public static final String PROP_KEY_CONNECT_TIMEOUT_IN_SECONDS = "fastdfs.connect_timeout_in_seconds";
public static final String PROP_KEY_NETWORK_TIMEOUT_IN_SECONDS = "fastdfs.network_timeout_in_seconds";
public static final String PROP_KEY_CHARSET = "fastdfs.charset";
public static final String PROP_KEY_HTTP_ANTI_STEAL_TOKEN = "fastdfs.http_anti_steal_token";
public static final String PROP_KEY_HTTP_SECRET_KEY = "fastdfs.http_secret_key";
public static final String PROP_KEY_HTTP_TRACKER_HTTP_PORT = "fastdfs.http_tracker_http_port";
public static final String PROP_KEY_TRACKER_SERVERS = "fastdfs.tracker_servers";
public static final String PROP_KEY_INNER_OUT_NET = "fastdfs.inner_out_net";
public static final int DEFAULT_CONNECT_TIMEOUT = 5; //second
public static final int DEFAULT_NETWORK_TIMEOUT = 30; //second
public static final String DEFAULT_CHARSET = "UTF-8";
public static final boolean DEFAULT_HTTP_ANTI_STEAL_TOKEN = false;
public static final String DEFAULT_HTTP_SECRET_KEY = "FastDFS1234567890";
public static final int DEFAULT_HTTP_TRACKER_HTTP_PORT = 80;
public static int g_connect_timeout = DEFAULT_CONNECT_TIMEOUT * 1000; //millisecond
public static int g_network_timeout = DEFAULT_NETWORK_TIMEOUT * 1000; //millisecond
public static String g_charset = DEFAULT_CHARSET;
public static boolean g_anti_steal_token = DEFAULT_HTTP_ANTI_STEAL_TOKEN; //if anti-steal token
public static String g_secret_key = DEFAULT_HTTP_SECRET_KEY; //generage token secret key
public static int g_tracker_http_port = DEFAULT_HTTP_TRACKER_HTTP_PORT;
public static TrackerGroup g_tracker_group;
public static Map<String,String> InnerOutNet;
private ClientGlobal() {
}
/**
* load global variables
*
* @param conf_filename config filename
*/
public static void init(String conf_filename) throws IOException, MyException {
IniFileReader iniReader;
String[] szTrackerServers;
String[] parts;
iniReader = new IniFileReader(conf_filename);
g_connect_timeout = iniReader.getIntValue("connect_timeout", DEFAULT_CONNECT_TIMEOUT);
if (g_connect_timeout < 0) {
g_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
}
g_connect_timeout *= 1000; //millisecond
g_network_timeout = iniReader.getIntValue("network_timeout", DEFAULT_NETWORK_TIMEOUT);
if (g_network_timeout < 0) {
g_network_timeout = DEFAULT_NETWORK_TIMEOUT;
}
g_network_timeout *= 1000; //millisecond
g_charset = iniReader.getStrValue("charset");
if (g_charset == null || g_charset.length() == 0) {
g_charset = "ISO8859-1";
}
szTrackerServers = iniReader.getValues("tracker_server");
if (szTrackerServers == null) {
throw new MyException("item \"tracker_server\" in " + conf_filename + " not found");
}
InetSocketAddress[] tracker_servers = new InetSocketAddress[szTrackerServers.length];
for (int i = 0; i < szTrackerServers.length; i++) {
parts = szTrackerServers[i].split("\\:", 2);
if (parts.length != 2) {
throw new MyException("the value of item \"tracker_server\" is invalid, the correct format is host:port");
}
tracker_servers[i] = new InetSocketAddress(parts[0].trim(), Integer.parseInt(parts[1].trim()));
}
g_tracker_group = new TrackerGroup(tracker_servers);
g_tracker_http_port = iniReader.getIntValue("http.tracker_http_port", 80);
g_anti_steal_token = iniReader.getBoolValue("http.anti_steal_token", false);
if (g_anti_steal_token) {
g_secret_key = iniReader.getStrValue("http.secret_key");
}
String[] storyInnerOutNet = iniReader.getValues("fastdfs.inner_out_net");
if(storyInnerOutNet!=null){
if(InnerOutNet==null){
InnerOutNet = new HashMap<String,String>();
}
for (int i = 0; i < storyInnerOutNet.length; i++) {
String innerOutNet = storyInnerOutNet[i];
String key = innerOutNet.split(":")[0];
String value = innerOutNet.split(":")[1];
InnerOutNet.put(key,value);
}
}
}
public static String getChangeInnerToOutNet(String innerNet){
if(InnerOutNet!=null){
if(InnerOutNet.containsKey(innerNet)){
return InnerOutNet.get(innerNet);
}
}
return innerNet;
}
/**
* load from properties file
*
* @param propsFilePath properties file path, eg:
* "fastdfs-client.properties"
* "config/fastdfs-client.properties"
* "/opt/fastdfs-client.properties"
* "C:\\Users\\James\\config\\fastdfs-client.properties"
* properties文件至少包含一个配置项 fastdfs.tracker_servers 例如:
* fastdfs.tracker_servers = 10.0.11.245:22122,10.0.11.246:22122
* server的IP和端口用冒号':'分隔
* server之间用逗号','分隔
*/
public static void initByProperties(String propsFilePath) throws IOException, MyException {
Properties props = new Properties();
InputStream in = IniFileReader.loadFromOsFileSystemOrClasspathAsStream(propsFilePath);
if (in != null) {
props.load(in);
}
initByProperties(props);
}
public static void initByProperties(Properties props) throws IOException, MyException {
String trackerServersConf = props.getProperty(PROP_KEY_TRACKER_SERVERS);
if (trackerServersConf == null || trackerServersConf.trim().length() == 0) {
throw new MyException(String.format("configure item %s is required", PROP_KEY_TRACKER_SERVERS));
}
initByTrackers(trackerServersConf.trim());
String connectTimeoutInSecondsConf = props.getProperty(PROP_KEY_CONNECT_TIMEOUT_IN_SECONDS);
String networkTimeoutInSecondsConf = props.getProperty(PROP_KEY_NETWORK_TIMEOUT_IN_SECONDS);
String charsetConf = props.getProperty(PROP_KEY_CHARSET);
String httpAntiStealTokenConf = props.getProperty(PROP_KEY_HTTP_ANTI_STEAL_TOKEN);
String httpSecretKeyConf = props.getProperty(PROP_KEY_HTTP_SECRET_KEY);
String httpTrackerHttpPortConf = props.getProperty(PROP_KEY_HTTP_TRACKER_HTTP_PORT);
String innerOutNet = props.getProperty(PROP_KEY_INNER_OUT_NET);
if (connectTimeoutInSecondsConf != null && connectTimeoutInSecondsConf.trim().length() != 0) {
g_connect_timeout = Integer.parseInt(connectTimeoutInSecondsConf.trim()) * 1000;
}
if (networkTimeoutInSecondsConf != null && networkTimeoutInSecondsConf.trim().length() != 0) {
g_network_timeout = Integer.parseInt(networkTimeoutInSecondsConf.trim()) * 1000;
}
if (charsetConf != null && charsetConf.trim().length() != 0) {
g_charset = charsetConf.trim();
}
if (httpAntiStealTokenConf != null && httpAntiStealTokenConf.trim().length() != 0) {
g_anti_steal_token = Boolean.parseBoolean(httpAntiStealTokenConf);
}
if (httpSecretKeyConf != null && httpSecretKeyConf.trim().length() != 0) {
g_secret_key = httpSecretKeyConf.trim();
}
if (httpTrackerHttpPortConf != null && httpTrackerHttpPortConf.trim().length() != 0) {
g_tracker_http_port = Integer.parseInt(httpTrackerHttpPortConf);
}
initStoryInnerOutNet(innerOutNet.trim());
}
public static void initStoryInnerOutNet(String innerOutNetString){
if(innerOutNetString!=null&&!"".equals(innerOutNetString)){
String[] storyInnerOutNet = innerOutNetString.split(",");
if(storyInnerOutNet!=null){
if(InnerOutNet==null){
InnerOutNet = new HashMap<String,String>();
}
for (int i = 0; i < storyInnerOutNet.length; i++) {
String innerOutNet = storyInnerOutNet[i];
String key = innerOutNet.split(":")[0];
String value = innerOutNet.split(":")[1];
InnerOutNet.put(key,value);
}
}
}
}
/**
* load from properties file
*
* @param trackerServers 例如:"10.0.11.245:22122,10.0.11.246:22122"
* server的IP和端口用冒号':'分隔
* server之间用逗号','分隔
*/
public static void initByTrackers(String trackerServers) throws IOException, MyException {
List<InetSocketAddress> list = new ArrayList();
String spr1 = ",";
String spr2 = ":";
String[] arr1 = trackerServers.trim().split(spr1);
for (String addrStr : arr1) {
String[] arr2 = addrStr.trim().split(spr2);
String host = arr2[0].trim();
int port = Integer.parseInt(arr2[1].trim());
list.add(new InetSocketAddress(host, port));
}
InetSocketAddress[] trackerAddresses = list.toArray(new InetSocketAddress[list.size()]);
initByTrackers(trackerAddresses);
}
public static void initByTrackers(InetSocketAddress[] trackerAddresses) throws IOException, MyException {
g_tracker_group = new TrackerGroup(trackerAddresses);
}
/**
* construct Socket object
*
* @param ip_addr ip address or hostname
* @param port port number
* @return connected Socket object
*/
public static Socket getSocket(String ip_addr, int port) throws IOException {
Socket sock = new Socket();
sock.setSoTimeout(ClientGlobal.g_network_timeout);
sock.connect(new InetSocketAddress(ip_addr, port), ClientGlobal.g_connect_timeout);
return sock;
}
/**
* construct Socket object
*
* @param addr InetSocketAddress object, including ip address and port
* @return connected Socket object
*/
public static Socket getSocket(InetSocketAddress addr) throws IOException {
Socket sock = new Socket();
sock.setSoTimeout(ClientGlobal.g_network_timeout);
sock.connect(addr, ClientGlobal.g_connect_timeout);
return sock;
}
public static int getG_connect_timeout() {
return g_connect_timeout;
}
public static void setG_connect_timeout(int connect_timeout) {
ClientGlobal.g_connect_timeout = connect_timeout;
}
public static int getG_network_timeout() {
return g_network_timeout;
}
public static void setG_network_timeout(int network_timeout) {
ClientGlobal.g_network_timeout = network_timeout;
}
public static String getG_charset() {
return g_charset;
}
public static void setG_charset(String charset) {
ClientGlobal.g_charset = charset;
}
public static int getG_tracker_http_port() {
return g_tracker_http_port;
}
public static void setG_tracker_http_port(int tracker_http_port) {
ClientGlobal.g_tracker_http_port = tracker_http_port;
}
public static boolean getG_anti_steal_token() {
return g_anti_steal_token;
}
public static boolean isG_anti_steal_token() {
return g_anti_steal_token;
}
public static void setG_anti_steal_token(boolean anti_steal_token) {
ClientGlobal.g_anti_steal_token = anti_steal_token;
}
public static String getG_secret_key() {
return g_secret_key;
}
public static void setG_secret_key(String secret_key) {
ClientGlobal.g_secret_key = secret_key;
}
public static TrackerGroup getG_tracker_group() {
return g_tracker_group;
}
public static void setG_tracker_group(TrackerGroup tracker_group) {
ClientGlobal.g_tracker_group = tracker_group;
}
public static String configInfo() {
String trackerServers = "";
if (g_tracker_group != null) {
InetSocketAddress[] trackerAddresses = g_tracker_group.tracker_servers;
for (InetSocketAddress inetSocketAddress : trackerAddresses) {
if(trackerServers.length() > 0) trackerServers += ",";
trackerServers += inetSocketAddress.toString().substring(1);
}
}
return "{"
+ "\n g_connect_timeout(ms) = " + g_connect_timeout
+ "\n g_network_timeout(ms) = " + g_network_timeout
+ "\n g_charset = " + g_charset
+ "\n g_anti_steal_token = " + g_anti_steal_token
+ "\n g_secret_key = " + g_secret_key
+ "\n g_tracker_http_port = " + g_tracker_http_port
+ "\n trackerServers = " + trackerServers
+ "\n}";
}
}
添加了内外网的相互转化
/**
* Copyright (C) 2008 Happy Fish / YuQing
* <p>
* FastDFS Java Client may be copied only under the terms of the GNU Lesser
* General Public License (LGPL).
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
*/
package org.csource.fastdfs;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Arrays;
/**
* Tracker client
*
* @author Happy Fish / YuQing
* @version Version 1.19
*/
public class TrackerClient {
protected TrackerGroup tracker_group;
protected byte errno;
/**
* constructor with global tracker group
*/
public TrackerClient() {
this.tracker_group = ClientGlobal.g_tracker_group;
}
/**
* constructor with specified tracker group
*
* @param tracker_group the tracker group object
*/
public TrackerClient(TrackerGroup tracker_group) {
this.tracker_group = tracker_group;
}
/**
* get the error code of last call
*
* @return the error code of last call
*/
public byte getErrorCode() {
return this.errno;
}
/**
* get a connection to tracker server
*
* @return tracker server Socket object, return null if fail
*/
public TrackerServer getConnection() throws IOException {
return this.tracker_group.getConnection();
}
/**
* query storage server to upload file
*
* @param trackerServer the tracker server
* @return storage server Socket object, return null if fail
*/
public StorageServer getStoreStorage(TrackerServer trackerServer) throws IOException {
final String groupName = null;
return this.getStoreStorage(trackerServer, groupName);
}
/**
* query storage server to upload file
*
* @param trackerServer the tracker server
* @param groupName the group name to upload file to, can be empty
* @return storage server object, return null if fail
*/
public StorageServer getStoreStorage(TrackerServer trackerServer, String groupName) throws IOException {
byte[] header;
String ip_addr;
int port;
byte cmd;
int out_len;
boolean bNewConnection;
byte store_path;
Socket trackerSocket;
if (trackerServer == null) {
trackerServer = getConnection();
if (trackerServer == null) {
return null;
}
bNewConnection = true;
} else {
bNewConnection = false;
}
trackerSocket = trackerServer.getSocket();
OutputStream out = trackerSocket.getOutputStream();
try {
if (groupName == null || groupName.length() == 0) {
cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE;
out_len = 0;
} else {
cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ONE;
out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
}
header = ProtoCommon.packHeader(cmd, out_len, (byte) 0);
out.write(header);
if (groupName != null && groupName.length() > 0) {
byte[] bGroupName;
byte[] bs;
int group_len;
bs = groupName.getBytes(ClientGlobal.g_charset);
bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];
if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) {
group_len = bs.length;
} else {
group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
}
Arrays.fill(bGroupName, (byte) 0);
System.arraycopy(bs, 0, bGroupName, 0, group_len);
out.write(bGroupName);
}
ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
ProtoCommon.TRACKER_PROTO_CMD_RESP,
ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN);
this.errno = pkgInfo.errno;
if (pkgInfo.errno != 0) {
return null;
}
ip_addr = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim();
port = (int) ProtoCommon.buff2long(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN
+ ProtoCommon.FDFS_IPADDR_SIZE - 1);
store_path = pkgInfo.body[ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN - 1];
ip_addr = ClientGlobal.getChangeInnerToOutNet(ip_addr);
return new StorageServer(ip_addr, port, store_path);
} catch (IOException ex) {
if (!bNewConnection) {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
throw ex;
} finally {
if (bNewConnection) {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
}
}
/**
* query storage servers to upload file
*
* @param trackerServer the tracker server
* @param groupName the group name to upload file to, can be empty
* @return storage servers, return null if fail
*/
public StorageServer[] getStoreStorages(TrackerServer trackerServer, String groupName) throws IOException {
byte[] header;
String ip_addr;
int port;
byte cmd;
int out_len;
boolean bNewConnection;
Socket trackerSocket;
if (trackerServer == null) {
trackerServer = getConnection();
if (trackerServer == null) {
return null;
}
bNewConnection = true;
} else {
bNewConnection = false;
}
trackerSocket = trackerServer.getSocket();
OutputStream out = trackerSocket.getOutputStream();
try {
if (groupName == null || groupName.length() == 0) {
cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ALL;
out_len = 0;
} else {
cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ALL;
out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
}
header = ProtoCommon.packHeader(cmd, out_len, (byte) 0);
out.write(header);
if (groupName != null && groupName.length() > 0) {
byte[] bGroupName;
byte[] bs;
int group_len;
bs = groupName.getBytes(ClientGlobal.g_charset);
bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];
if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) {
group_len = bs.length;
} else {
group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
}
Arrays.fill(bGroupName, (byte) 0);
System.arraycopy(bs, 0, bGroupName, 0, group_len);
out.write(bGroupName);
}
ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
this.errno = pkgInfo.errno;
if (pkgInfo.errno != 0) {
return null;
}
if (pkgInfo.body.length < ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN) {
this.errno = ProtoCommon.ERR_NO_EINVAL;
return null;
}
int ipPortLen = pkgInfo.body.length - (ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + 1);
final int recordLength = ProtoCommon.FDFS_IPADDR_SIZE - 1 + ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE;
if (ipPortLen % recordLength != 0) {
this.errno = ProtoCommon.ERR_NO_EINVAL;
return null;
}
int serverCount = ipPortLen / recordLength;
if (serverCount > 16) {
this.errno = ProtoCommon.ERR_NO_ENOSPC;
return null;
}
StorageServer[] results = new StorageServer[serverCount];
byte store_path = pkgInfo.body[pkgInfo.body.length - 1];
int offset = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
for (int i = 0; i < serverCount; i++) {
ip_addr = new String(pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim();
offset += ProtoCommon.FDFS_IPADDR_SIZE - 1;
port = (int) ProtoCommon.buff2long(pkgInfo.body, offset);
offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE;
ip_addr = ClientGlobal.getChangeInnerToOutNet(ip_addr);
results[i] = new StorageServer(ip_addr, port, store_path);
}
return results;
} catch (IOException ex) {
if (!bNewConnection) {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
throw ex;
} finally {
if (bNewConnection) {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
}
}
/**
* query storage server to download file
*
* @param trackerServer the tracker server
* @param groupName the group name of storage server
* @param filename filename on storage server
* @return storage server Socket object, return null if fail
*/
public StorageServer getFetchStorage(TrackerServer trackerServer,
String groupName, String filename) throws IOException {
ServerInfo[] servers = this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE,
groupName, filename);
if (servers == null) {
return null;
} else {
return new StorageServer(servers[0].getIpAddr(), servers[0].getPort(), 0);
}
}
/**
* query storage server to update file (delete file or set meta data)
*
* @param trackerServer the tracker server
* @param groupName the group name of storage server
* @param filename filename on storage server
* @return storage server Socket object, return null if fail
*/
public StorageServer getUpdateStorage(TrackerServer trackerServer,
String groupName, String filename) throws IOException {
ServerInfo[] servers = this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE,
groupName, filename);
if (servers == null) {
return null;
} else {
return new StorageServer(servers[0].getIpAddr(), servers[0].getPort(), 0);
}
}
/**
* get storage servers to download file
*
* @param trackerServer the tracker server
* @param groupName the group name of storage server
* @param filename filename on storage server
* @return storage servers, return null if fail
*/
public ServerInfo[] getFetchStorages(TrackerServer trackerServer,
String groupName, String filename) throws IOException {
return this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL,
groupName, filename);
}
/**
* query storage server to download file
*
* @param trackerServer the tracker server
* @param cmd command code, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE or
* ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE
* @param groupName the group name of storage server
* @param filename filename on storage server
* @return storage server Socket object, return null if fail
*/
protected ServerInfo[] getStorages(TrackerServer trackerServer,
byte cmd, String groupName, String filename) throws IOException {
byte[] header;
byte[] bFileName;
byte[] bGroupName;
byte[] bs;
int len;
String ip_addr;
int port;
boolean bNewConnection;
Socket trackerSocket;
if (trackerServer == null) {
trackerServer = getConnection();
if (trackerServer == null) {
return null;
}
bNewConnection = true;
} else {
bNewConnection = false;
}
trackerSocket = trackerServer.getSocket();
OutputStream out = trackerSocket.getOutputStream();
try {
bs = groupName.getBytes(ClientGlobal.g_charset);
bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];
bFileName = filename.getBytes(ClientGlobal.g_charset);
if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) {
len = bs.length;
} else {
len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
}
Arrays.fill(bGroupName, (byte) 0);
System.arraycopy(bs, 0, bGroupName, 0, len);
header = ProtoCommon.packHeader(cmd, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + bFileName.length, (byte) 0);
byte[] wholePkg = new byte[header.length + bGroupName.length + bFileName.length];
System.arraycopy(header, 0, wholePkg, 0, header.length);
System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length);
System.arraycopy(bFileName, 0, wholePkg, header.length + bGroupName.length, bFileName.length);
out.write(wholePkg);
ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
this.errno = pkgInfo.errno;
if (pkgInfo.errno != 0) {
return null;
}
if (pkgInfo.body.length < ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) {
throw new IOException("Invalid body length: " + pkgInfo.body.length);
}
if ((pkgInfo.body.length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) % (ProtoCommon.FDFS_IPADDR_SIZE - 1) != 0) {
throw new IOException("Invalid body length: " + pkgInfo.body.length);
}
int server_count = 1 + (pkgInfo.body.length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) / (ProtoCommon.FDFS_IPADDR_SIZE - 1);
ip_addr = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim();
int offset = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ProtoCommon.FDFS_IPADDR_SIZE - 1;
port = (int) ProtoCommon.buff2long(pkgInfo.body, offset);
offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE;
ServerInfo[] servers = new ServerInfo[server_count];
ip_addr = ClientGlobal.getChangeInnerToOutNet(ip_addr);
servers[0] = new ServerInfo(ip_addr, port);
for (int i = 1; i < server_count; i++) {
servers[i] = new ServerInfo(new String(pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(), port);
offset += ProtoCommon.FDFS_IPADDR_SIZE - 1;
}
return servers;
} catch (IOException ex) {
if (!bNewConnection) {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
throw ex;
} finally {
if (bNewConnection) {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
}
}
/**
* query storage server to download file
*
* @param trackerServer the tracker server
* @param file_id the file id(including group name and filename)
* @return storage server Socket object, return null if fail
*/
public StorageServer getFetchStorage1(TrackerServer trackerServer, String file_id) throws IOException {
String[] parts = new String[2];
this.errno = StorageClient1.split_file_id(file_id, parts);
if (this.errno != 0) {
return null;
}
return this.getFetchStorage(trackerServer, parts[0], parts[1]);
}
/**
* get storage servers to download file
*
* @param trackerServer the tracker server
* @param file_id the file id(including group name and filename)
* @return storage servers, return null if fail
*/
public ServerInfo[] getFetchStorages1(TrackerServer trackerServer, String file_id) throws IOException {
String[] parts = new String[2];
this.errno = StorageClient1.split_file_id(file_id, parts);
if (this.errno != 0) {
return null;
}
return this.getFetchStorages(trackerServer, parts[0], parts[1]);
}
/**
* list groups
*
* @param trackerServer the tracker server
* @return group stat array, return null if fail
*/
public StructGroupStat[] listGroups(TrackerServer trackerServer) throws IOException {
byte[] header;
String ip_addr;
int port;
byte cmd;
int out_len;
boolean bNewConnection;
byte store_path;
Socket trackerSocket;
if (trackerServer == null) {
trackerServer = getConnection();
if (trackerServer == null) {
return null;
}
bNewConnection = true;
} else {
bNewConnection = false;
}
trackerSocket = trackerServer.getSocket();
OutputStream out = trackerSocket.getOutputStream();
try {
header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_GROUP, 0, (byte) 0);
out.write(header);
ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
this.errno = pkgInfo.errno;
if (pkgInfo.errno != 0) {
return null;
}
ProtoStructDecoder<StructGroupStat> decoder = new ProtoStructDecoder<StructGroupStat>();
return decoder.decode(pkgInfo.body, StructGroupStat.class, StructGroupStat.getFieldsTotalSize());
} catch (IOException ex) {
if (!bNewConnection) {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
throw ex;
} catch (Exception ex) {
ex.printStackTrace();
this.errno = ProtoCommon.ERR_NO_EINVAL;
return null;
} finally {
if (bNewConnection) {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
}
}
/**
* query storage server stat info of the group
*
* @param trackerServer the tracker server
* @param groupName the group name of storage server
* @return storage server stat array, return null if fail
*/
public StructStorageStat[] listStorages(TrackerServer trackerServer, String groupName) throws IOException {
final String storageIpAddr = null;
return this.listStorages(trackerServer, groupName, storageIpAddr);
}
/**
* query storage server stat info of the group
*
* @param trackerServer the tracker server
* @param groupName the group name of storage server
* @param storageIpAddr the storage server ip address, can be null or empty
* @return storage server stat array, return null if fail
*/
public StructStorageStat[] listStorages(TrackerServer trackerServer,
String groupName, String storageIpAddr) throws IOException {
byte[] header;
byte[] bGroupName;
byte[] bs;
int len;
boolean bNewConnection;
Socket trackerSocket;
if (trackerServer == null) {
trackerServer = getConnection();
if (trackerServer == null) {
return null;
}
bNewConnection = true;
} else {
bNewConnection = false;
}
trackerSocket = trackerServer.getSocket();
OutputStream out = trackerSocket.getOutputStream();
try {
bs = groupName.getBytes(ClientGlobal.g_charset);
bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];
if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) {
len = bs.length;
} else {
len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
}
Arrays.fill(bGroupName, (byte) 0);
System.arraycopy(bs, 0, bGroupName, 0, len);
int ipAddrLen;
byte[] bIpAddr;
if (storageIpAddr != null && storageIpAddr.length() > 0) {
bIpAddr = storageIpAddr.getBytes(ClientGlobal.g_charset);
if (bIpAddr.length < ProtoCommon.FDFS_IPADDR_SIZE) {
ipAddrLen = bIpAddr.length;
} else {
ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1;
}
} else {
bIpAddr = null;
ipAddrLen = 0;
}
header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_STORAGE, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte) 0);
byte[] wholePkg = new byte[header.length + bGroupName.length + ipAddrLen];
System.arraycopy(header, 0, wholePkg, 0, header.length);
System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length);
if (ipAddrLen > 0) {
System.arraycopy(bIpAddr, 0, wholePkg, header.length + bGroupName.length, ipAddrLen);
}
out.write(wholePkg);
ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
this.errno = pkgInfo.errno;
if (pkgInfo.errno != 0) {
return null;
}
ProtoStructDecoder<StructStorageStat> decoder = new ProtoStructDecoder<StructStorageStat>();
return decoder.decode(pkgInfo.body, StructStorageStat.class, StructStorageStat.getFieldsTotalSize());
} catch (IOException ex) {
if (!bNewConnection) {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
throw ex;
} catch (Exception ex) {
ex.printStackTrace();
this.errno = ProtoCommon.ERR_NO_EINVAL;
return null;
} finally {
if (bNewConnection) {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
}
}
/**
* delete a storage server from the tracker server
*
* @param trackerServer the connected tracker server
* @param groupName the group name of storage server
* @param storageIpAddr the storage server ip address
* @return true for success, false for fail
*/
private boolean deleteStorage(TrackerServer trackerServer,
String groupName, String storageIpAddr) throws IOException {
byte[] header;
byte[] bGroupName;
byte[] bs;
int len;
Socket trackerSocket;
trackerSocket = trackerServer.getSocket();
OutputStream out = trackerSocket.getOutputStream();
bs = groupName.getBytes(ClientGlobal.g_charset);
bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];
if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) {
len = bs.length;
} else {
len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
}
Arrays.fill(bGroupName, (byte) 0);
System.arraycopy(bs, 0, bGroupName, 0, len);
int ipAddrLen;
byte[] bIpAddr = storageIpAddr.getBytes(ClientGlobal.g_charset);
if (bIpAddr.length < ProtoCommon.FDFS_IPADDR_SIZE) {
ipAddrLen = bIpAddr.length;
} else {
ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1;
}
header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_DELETE_STORAGE, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte) 0);
byte[] wholePkg = new byte[header.length + bGroupName.length + ipAddrLen];
System.arraycopy(header, 0, wholePkg, 0, header.length);
System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length);
System.arraycopy(bIpAddr, 0, wholePkg, header.length + bGroupName.length, ipAddrLen);
out.write(wholePkg);
ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(),
ProtoCommon.TRACKER_PROTO_CMD_RESP, 0);
this.errno = pkgInfo.errno;
return pkgInfo.errno == 0;
}
/**
* delete a storage server from the global FastDFS cluster
*
* @param groupName the group name of storage server
* @param storageIpAddr the storage server ip address
* @return true for success, false for fail
*/
public boolean deleteStorage(String groupName, String storageIpAddr) throws IOException {
return this.deleteStorage(ClientGlobal.g_tracker_group, groupName, storageIpAddr);
}
/**
* delete a storage server from the FastDFS cluster
*
* @param trackerGroup the tracker server group
* @param groupName the group name of storage server
* @param storageIpAddr the storage server ip address
* @return true for success, false for fail
*/
public boolean deleteStorage(TrackerGroup trackerGroup,
String groupName, String storageIpAddr) throws IOException {
int serverIndex;
int notFoundCount;
TrackerServer trackerServer;
notFoundCount = 0;
for (serverIndex = 0; serverIndex < trackerGroup.tracker_servers.length; serverIndex++) {
try {
trackerServer = trackerGroup.getConnection(serverIndex);
} catch (IOException ex) {
ex.printStackTrace(System.err);
this.errno = ProtoCommon.ECONNREFUSED;
return false;
}
try {
StructStorageStat[] storageStats = listStorages(trackerServer, groupName, storageIpAddr);
if (storageStats == null) {
if (this.errno == ProtoCommon.ERR_NO_ENOENT) {
notFoundCount++;
} else {
return false;
}
} else if (storageStats.length == 0) {
notFoundCount++;
} else if (storageStats[0].getStatus() == ProtoCommon.FDFS_STORAGE_STATUS_ONLINE ||
storageStats[0].getStatus() == ProtoCommon.FDFS_STORAGE_STATUS_ACTIVE) {
this.errno = ProtoCommon.ERR_NO_EBUSY;
return false;
}
} finally {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
}
if (notFoundCount == trackerGroup.tracker_servers.length) {
this.errno = ProtoCommon.ERR_NO_ENOENT;
return false;
}
notFoundCount = 0;
for (serverIndex = 0; serverIndex < trackerGroup.tracker_servers.length; serverIndex++) {
try {
trackerServer = trackerGroup.getConnection(serverIndex);
} catch (IOException ex) {
System.err.println("connect to server " + trackerGroup.tracker_servers[serverIndex].getAddress().getHostAddress() + ":" + trackerGroup.tracker_servers[serverIndex].getPort() + " fail");
ex.printStackTrace(System.err);
this.errno = ProtoCommon.ECONNREFUSED;
return false;
}
try {
if (!this.deleteStorage(trackerServer, groupName, storageIpAddr)) {
if (this.errno != 0) {
if (this.errno == ProtoCommon.ERR_NO_ENOENT) {
notFoundCount++;
} else if (this.errno != ProtoCommon.ERR_NO_EALREADY) {
return false;
}
}
}
} finally {
try {
trackerServer.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
}
}
if (notFoundCount == trackerGroup.tracker_servers.length) {
this.errno = ProtoCommon.ERR_NO_ENOENT;
return false;
}
if (this.errno == ProtoCommon.ERR_NO_ENOENT) {
this.errno = 0;
}
return this.errno == 0;
}
}
此处在获取storage 时 内网转化成外网
到此fastdfs的 问题解决,若还有别的问题,请联系!!!