/*
* Copyright (c) 2013, OpenCloudDB/MyCAT and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software;Designed and Developed mainly by many Chinese
* opensource volunteers. you can redistribute it and/or modify it under the
* terms of the GNU General Public License version 2 only, as published by the
* Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Any questions about this component can be directed to it's project Web address
* https://code.google.com/p/opencloudb/.
*
*/
package com.talent.balance.mapping;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.talent.balance.conf.BackendConf;
import com.talent.balance.conf.BackendServerConf;
import com.talent.balance.frontend.ext.FrontendExt;
import com.talent.nio.api.Nio;
import com.talent.nio.communicate.ChannelContext;
import com.talent.nio.utils.NetUtils;
/**
*
* @filename: com.talent.balance.mapping.Mapping
* @copyright: Copyright (c)2010
* @company: talent
* @author: 谭耀武
* @version: 1.0
* @create time: 2013年12月23日 上午11:55:40
* @record
* <table cellPadding="3" cellSpacing="0" style="width:600px">
* <thead style="font-weight:bold;background-color:#e3e197">
* <tr> <td>date</td> <td>author</td> <td>version</td> <td>description</td></tr>
* </thead>
* <tbody style="background-color:#ffffeb">
* <tr><td>2013年12月23日</td> <td>谭耀武</td> <td>1.0</td> <td>create</td></tr>
* </tbody>
* </table>
*/
public class Mapping
{
@SuppressWarnings("unused")
private static Logger log = LoggerFactory.getLogger(Mapping.class);
/**
* key: frontendChannelContext; value: 后端BackendServer对象
*/
private static Map<ChannelContext, BackendServerConf> frontChannelcontextAndBackserverMap = new HashMap<ChannelContext, BackendServerConf>();
/**
*
* @param frontendChannelContext
*/
public static void remove(ChannelContext frontendChannelContext)
{
frontChannelcontextAndBackserverMap.remove(frontendChannelContext);
}
/**
* 根据frontendChannelContext找到后端的BackendServer对象
* @param frontip
* @return
*/
public static BackendServerConf getBackendServer(ChannelContext frontendChannelContext)
{
// String frontip = frontendChannelContext.getRemoteNode().getIp();
BackendServerConf backendServer = frontChannelcontextAndBackserverMap.get(frontendChannelContext);
if (backendServer == null)
{
backendServer = assignServer();
frontChannelcontextAndBackserverMap.put(frontendChannelContext, backendServer);
} else
{
ChannelContext backendChannelContext = FrontendExt.getBackend(frontendChannelContext);
if (!backendChannelContext.isAppOn())
{
if (!NetUtils.isConnectable(backendServer.getIp(), backendServer.getPort()))
{
Nio.getInstance().removeConnection(backendChannelContext, "not connectable");
backendServer = assignServer();
frontChannelcontextAndBackserverMap.put(frontendChannelContext, backendServer);
}
}
}
return backendServer;
}
/**
* 为前端分配后端服务器
* @param frontip
* @return
*/
private static BackendServerConf assignServer()
{
BackendServerConf[] servers = BackendConf.getInstance().getServers();
Arrays.sort(servers, new Comparator<BackendServerConf>()
{
@Override
public int compare(BackendServerConf o1, BackendServerConf o2)
{
if (o1.isConnectable() && !o2.isConnectable())
{
return -1;
} else if (o2.isConnectable() && !o1.isConnectable())
{
return 1;
} else if (!o2.isConnectable() && !o1.isConnectable())
{
return 0;
}
float s1 = (o1.getStat().getReceivedBytes() + o1.getStat().getSentBytes()) / o1.getWeight();
float s2 = (o2.getStat().getReceivedBytes() + o2.getStat().getSentBytes()) / o2.getWeight();
return (int) (s1 - s2);
}
});
for (BackendServerConf server : servers)
{
// boolean isConnectable = NetUtils.isConnectable(server.getIp(), server.getPort());
if (server.isConnectable())
{
return server;
}
}
throw new RuntimeException("no server for use");
// int index = assignServerIndex(frontip, servers.length);
//
// BackendServerConf server = servers[index];
// BackendServerConf ret = null;
// for (int i = 0; i < servers.length; i++)
// {
// // boolean isConnectable = NetUtils.isConnectable(server.getIp(), server.getPort());
// if (server.isConnectable())
// {
// ret = server;
// break;
// } else
// {
// index = next(index, servers.length);
// server = servers[index];
// continue;
// }
// }
//
// if (ret != null)
// {
// return ret;
// } else
// {
// throw new RuntimeException("no server for user");
// }
}
/**
*
* @param frontip 形如:"192.168.0.23"
* @param count 整数范围(1-n)
* @return
*/
private static int assignServerIndex(String frontip, int count)
{
int hashCode = frontip.hashCode();
return Math.abs(hashCode % count);
}
/**
*
* @param currIndex
* @param count
* @return
*/
private static int next(int currIndex, int count)
{
int _currIndex = currIndex + 1;
if (_currIndex > (count - 1))
{
_currIndex = 0;
}
return _currIndex;
}
/**
*
*/
public Mapping()
{
}
/**
* @param args
*/
public static void main(String[] args)
{
BackendServerConf b1 = new BackendServerConf();
BackendServerConf b2 = new BackendServerConf();
BackendServerConf b3 = new BackendServerConf();
BackendServerConf b4 = new BackendServerConf();
b1.setIp("1");
b2.setIp("2");
b3.setIp("3");
b4.setIp("4");
b1.setWeight(1);
b2.setWeight(9);
b3.setWeight(5);
b4.setWeight(8);
b1.getStat().setReceivedBytes(1000);
b2.getStat().setReceivedBytes(1000);
b3.getStat().setReceivedBytes(1000);
b4.getStat().setReceivedBytes(1000);
b4.setConnectable(false);
b2.setConnectable(false);
BackendServerConf[] servers = new BackendServerConf[] { b1, b2, b3, b4 };
Arrays.sort(servers, new Comparator<BackendServerConf>()
{
@Override
public int compare(BackendServerConf o1, BackendServerConf o2)
{
if (o1.isConnectable() && !o2.isConnectable())
{
return -1;
} else if (o2.isConnectable() && !o1.isConnectable())
{
return 1;
} else if (!o2.isConnectable() && !o1.isConnectable())
{
return 0;
}
float s1 = (o1.getStat().getReceivedBytes() + o1.getStat().getSentBytes()) / o1.getWeight();
float s2 = (o2.getStat().getReceivedBytes() + o2.getStat().getSentBytes()) / o2.getWeight();
return (int) (s1 - s2);
}
});
int d = assignServerIndex("125.23.23.23", 5);
System.out.println("125.23.23.23".hashCode());
for (int i = 1; i < 1000; i++)
{
d = assignServerIndex("125.23.23.23", i);
System.out.println(d);
}
}
}