MemcachedClientKeeper 完成对XMemcached连接的保持,并提供心跳 维护自身状态
- package com.iuwcity.memcached.group;
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import java.util.Map;
- import java.util.concurrent.Callable;
- import java.util.concurrent.Executors;
- import java.util.concurrent.ScheduledExecutorService;
- import java.util.concurrent.TimeUnit;
- import net.rubyeye.xmemcached.XMemcachedClient;
- public class MemcachedClientKeeper {
- public static final String OP_SUC = "0";
- public static final String OP_FAL = "1";
- private XMemcachedClient client;
- private String host;
- private int port;
- private long breathTime = 5;
- private long initalTime = 5;
- private int breathBreakThreshold = 5; //心跳异常允许的次数
- private int breathBreak = 0; //当前心跳异常次数
- private int status = MemcachedGroup.READ_WRITE;
- private int beforeStatus = status;
- private BreathLogic breathLogic = new BreathLogic();
- public PutLogic putLogic = new PutLogic("",0,"");
- public GetLogic getLogic = new GetLogic("");
- private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
- private boolean isLaunched = false;
- public MemcachedClientKeeper(final String host, final int port) throws IOException {
- this.host = host;
- this.port = port;
- this.client = new XMemcachedClient(host, port);
- }
- public XMemcachedClient getClient() {
- return client;
- }
- public long getBreathTime() {
- return breathTime;
- }
- public void setBreathTime(long breathTime) {
- this.breathTime = breathTime;
- }
- public long getInitalTime() {
- return initalTime;
- }
- public void setInitalTime(long initalTime) {
- this.initalTime = initalTime;
- }
- public int getStatus() {
- return status;
- }
- public void setStatus(int status) {
- this.status = status;
- }
- public int getBreathBreakThreshold() {
- return breathBreakThreshold;
- }
- public void setBreathBreakThreshold(int breathBreakThreshold) {
- this.breathBreakThreshold = breathBreakThreshold;
- }
- public int getBreathBreak() {
- return breathBreak;
- }
- public void setBreathBreak(int breathBreak) {
- this.breathBreak = breathBreak;
- }
- /**
- * 启动
- */
- public void launch(){
- if(!isLaunched){
- scheduler.scheduleAtFixedRate(this.breathLogic, this.initalTime,
- this.breathTime, TimeUnit.SECONDS);
- isLaunched = !isLaunched;
- }
- }
- public BreathLogic getBreathLogic() {
- return breathLogic;
- }
- public void setBreathLogic(BreathLogic breathLogic) {
- this.breathLogic = breathLogic;
- }
- public ScheduledExecutorService getScheduler() {
- return scheduler;
- }
- public void setScheduler(ScheduledExecutorService scheduler) {
- this.scheduler = scheduler;
- }
- public String getHost() {
- return host;
- }
- public void setHost(String host) {
- this.host = host;
- }
- public int getPort() {
- return port;
- }
- public void setPort(int port) {
- this.port = port;
- }
- public int getBeforeStatus() {
- return beforeStatus;
- }
- public void setBeforeStatus(int beforeStatus) {
- this.beforeStatus = beforeStatus;
- }
- /**
- * 心跳逻辑
- *
- * @author xuchen
- *
- */
- public class BreathLogic implements Runnable {
- public void run() {
- try {
- Map<String,String> stat = client.stats(new InetSocketAddress(host,port));
- System.out.println("breath : " + stat);
- } catch (Exception e) {
- //心跳异常
- breathBreak ++;
- if(breathBreak >= breathBreakThreshold ){ //达到允许次数
- breathBreak = 0;
- //记录服务节点之前的状态
- beforeStatus = status;
- status = MemcachedGroup.NOT_READY;
- //todo 发出报警
- }
- e.printStackTrace();
- return ;
- }
- //判断如果服务器正常 则恢复到出现问题之前的状态
- if(MemcachedGroup.NOT_READY == status){
- status = beforeStatus;
- }
- }
- }
- public class PutLogic implements Callable<Object> {
- private String key ;
- private int exp = 0;
- private Object value;
- public String getKey() {
- return key;
- }
- public void setKey(String key) {
- this.key = key;
- }
- public int getExp() {
- return exp;
- }
- public void setExp(int exp) {
- this.exp = exp;
- }
- public Object getValue() {
- return value;
- }
- public void setValue(Object value) {
- this.value = value;
- }
- public PutLogic(final String key,final Object value){
- this(key,0,value);
- }
- public PutLogic(final String key,final int exp,final Object value){
- this.key = key;
- this.exp = exp;
- this.value = value;
- }
- public Object call() throws Exception {
- try {
- if(client.add(key, exp, value)){
- return OP_SUC + "|" + host + ":" + port;
- }else {
- return OP_FAL + "|" + host + ":" + port;
- }
- }catch (Exception e){
- e.printStackTrace();
- return OP_FAL + "|" + host + ":" + port;
- }
- }
- }
- /**
- * @author xuchen
- *
- */
- public class GetLogic implements Callable<Object> {
- private String key;
- public String getKey() {
- return key;
- }
- public void setKey(String key) {
- this.key = key;
- }
- public GetLogic(final String key){
- this.key = key;
- }
- public Object call() throws Exception {
- return client.get(this.key);
- }
- }
- }
package com.iuwcity.memcached.group;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import net.rubyeye.xmemcached.XMemcachedClient;
public class MemcachedClientKeeper {
public static final String OP_SUC = "0";
public static final String OP_FAL = "1";
private XMemcachedClient client;
private String host;
private int port;
private long breathTime = 5;
private long initalTime = 5;
private int breathBreakThreshold = 5; //心跳异常允许的次数
private int breathBreak = 0; //当前心跳异常次数
private int status = MemcachedGroup.READ_WRITE;
private int beforeStatus = status;
private BreathLogic breathLogic = new BreathLogic();
public PutLogic putLogic = new PutLogic("",0,"");
public GetLogic getLogic = new GetLogic("");
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private boolean isLaunched = false;
public MemcachedClientKeeper(final String host, final int port) throws IOException {
this.host = host;
this.port = port;
this.client = new XMemcachedClient(host, port);
}
public XMemcachedClient getClient() {
return client;
}
public long getBreathTime() {
return breathTime;
}
public void setBreathTime(long breathTime) {
this.breathTime = breathTime;
}
public long getInitalTime() {
return initalTime;
}
public void setInitalTime(long initalTime) {
this.initalTime = initalTime;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getBreathBreakThreshold() {
return breathBreakThreshold;
}
public void setBreathBreakThreshold(int breathBreakThreshold) {
this.breathBreakThreshold = breathBreakThreshold;
}
public int getBreathBreak() {
return breathBreak;
}
public void setBreathBreak(int breathBreak) {
this.breathBreak = breathBreak;
}
/**
* 启动
*/
public void launch(){
if(!isLaunched){
scheduler.scheduleAtFixedRate(this.breathLogic, this.initalTime,
this.breathTime, TimeUnit.SECONDS);
isLaunched = !isLaunched;
}
}
public BreathLogic getBreathLogic() {
return breathLogic;
}
public void setBreathLogic(BreathLogic breathLogic) {
this.breathLogic = breathLogic;
}
public ScheduledExecutorService getScheduler() {
return scheduler;
}
public void setScheduler(ScheduledExecutorService scheduler) {
this.scheduler = scheduler;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public int getBeforeStatus() {
return beforeStatus;
}
public void setBeforeStatus(int beforeStatus) {
this.beforeStatus = beforeStatus;
}
/**
* 心跳逻辑
*
* @author xuchen
*
*/
public class BreathLogic implements Runnable {
public void run() {
try {
Map<String,String> stat = client.stats(new InetSocketAddress(host,port));
System.out.println("breath : " + stat);
} catch (Exception e) {
//心跳异常
breathBreak ++;
if(breathBreak >= breathBreakThreshold ){ //达到允许次数
breathBreak = 0;
//记录服务节点之前的状态
beforeStatus = status;
status = MemcachedGroup.NOT_READY;
//todo 发出报警
}
e.printStackTrace();
return ;
}
//判断如果服务器正常 则恢复到出现问题之前的状态
if(MemcachedGroup.NOT_READY == status){
status = beforeStatus;
}
}
}
public class PutLogic implements Callable<Object> {
private String key ;
private int exp = 0;
private Object value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public int getExp() {
return exp;
}
public void setExp(int exp) {
this.exp = exp;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public PutLogic(final String key,final Object value){
this(key,0,value);
}
public PutLogic(final String key,final int exp,final Object value){
this.key = key;
this.exp = exp;
this.value = value;
}
public Object call() throws Exception {
try {
if(client.add(key, exp, value)){
return OP_SUC + "|" + host + ":" + port;
}else {
return OP_FAL + "|" + host + ":" + port;
}
}catch (Exception e){
e.printStackTrace();
return OP_FAL + "|" + host + ":" + port;
}
}
}
/**
* @author xuchen
*
*/
public class GetLogic implements Callable<Object> {
private String key;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public GetLogic(final String key){
this.key = key;
}
public Object call() throws Exception {
return client.get(this.key);
}
}
}
MemcachedGroupHandle 保持一组Keeper 简单的操作 put/get
put方式只是遍历当前可写节点进行写操作
get方式也比较简单 对可读的节点 目前默认取第一个 进行读
- package com.iuwcity.memcached.group;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- import net.rubyeye.xmemcached.XMemcachedClient;
- public class MemcachedGroupHandle implements MemcachedGroup {
- // FIX ME
- private List<MemcachedClientKeeper> serverKeepers = new ArrayList<MemcachedClientKeeper>();
- private ExecutorService service = Executors.newCachedThreadPool();
- public void addServer(final String host, final int port) throws IOException {
- MemcachedClientKeeper keeper = new MemcachedClientKeeper(host, port);
- this.addServer(keeper);
- }
- public void addServer(MemcachedClientKeeper keeper) throws IOException {
- keeper.launch();
- this.serverKeepers.add(keeper);
- }
- public void putByFuture(final String key, final int exp, final Object value) throws Exception {
- List<Future<Object>> futures = new ArrayList<Future<Object>>();
- // 遍历所有服务器进行写操作 此处有待优化
- for (MemcachedClientKeeper keeper : serverKeepers) {
- if (keeper.getStatus() != MemcachedGroup.NOT_READY && keeper.getStatus() != MemcachedGroup.READ_ONLY) {
- keeper.putLogic.setKey(key);
- keeper.putLogic.setExp(exp);
- keeper.putLogic.setValue(value);
- Future<Object> f = service.submit(keeper.putLogic);
- futures.add(f);
- }
- }
- for (Future<Object> f : futures) {
- if (f.get() != null) {
- String result = f.get().toString();
- if (result.startsWith(MemcachedClientKeeper.OP_FAL)) {
- // 写失败操作
- }
- }
- }
- }
- /**
- * 遍历第一个可读节点即返回
- * @param key
- * @return
- * @throws Exception
- */
- public Object getByFuture(final String key) throws Exception {
- // 遍历所有服务器进行写操作 此处有待优化
- for (MemcachedClientKeeper keeper : serverKeepers) {
- if (keeper.getStatus() != MemcachedGroup.NOT_READY && keeper.getStatus() != MemcachedGroup.WRITE_ONLY) {
- keeper.getLogic.setKey(key);
- Future<Object> f = service.submit(keeper.getLogic);
- return f.get();
- }
- }
- return null;
- }
- /**
- * 遍历第一个可读节点即返回
- * @param key
- * @return
- * @throws Exception
- */
- public Object get(final String key) throws Exception {
- // 遍历所有服务器进行写操作 此处有待优化
- for (MemcachedClientKeeper keeper : serverKeepers) {
- if (keeper.getStatus() != MemcachedGroup.NOT_READY && keeper.getStatus() != MemcachedGroup.WRITE_ONLY) {
- return keeper.getClient().get(key);
- }
- }
- return null;
- }
- public void put(final String key, final int exp, final Object value) throws Exception {
- // 遍历所有服务器进行写操作 此处有待优化
- for (MemcachedClientKeeper keeper : serverKeepers) {
- if (keeper.getStatus() != MemcachedGroup.NOT_READY && keeper.getStatus() != MemcachedGroup.READ_ONLY) {
- XMemcachedClient client = keeper.getClient();
- if(client.add(key, exp, value)){
- //todo写异常
- }
- }
- }
- }
- public ExecutorService getService() {
- return service;
- }
- public void setService(ExecutorService service) {
- this.service = service;
- }
- }
package com.iuwcity.memcached.group;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import net.rubyeye.xmemcached.XMemcachedClient;
public class MemcachedGroupHandle implements MemcachedGroup {
// FIX ME
private List<MemcachedClientKeeper> serverKeepers = new ArrayList<MemcachedClientKeeper>();
private ExecutorService service = Executors.newCachedThreadPool();
public void addServer(final String host, final int port) throws IOException {
MemcachedClientKeeper keeper = new MemcachedClientKeeper(host, port);
this.addServer(keeper);
}
public void addServer(MemcachedClientKeeper keeper) throws IOException {
keeper.launch();
this.serverKeepers.add(keeper);
}
public void putByFuture(final String key, final int exp, final Object value) throws Exception {
List<Future<Object>> futures = new ArrayList<Future<Object>>();
// 遍历所有服务器进行写操作 此处有待优化
for (MemcachedClientKeeper keeper : serverKeepers) {
if (keeper.getStatus() != MemcachedGroup.NOT_READY && keeper.getStatus() != MemcachedGroup.READ_ONLY) {
keeper.putLogic.setKey(key);
keeper.putLogic.setExp(exp);
keeper.putLogic.setValue(value);
Future<Object> f = service.submit(keeper.putLogic);
futures.add(f);
}
}
for (Future<Object> f : futures) {
if (f.get() != null) {
String result = f.get().toString();
if (result.startsWith(MemcachedClientKeeper.OP_FAL)) {
// 写失败操作
}
}
}
}
/**
* 遍历第一个可读节点即返回
* @param key
* @return
* @throws Exception
*/
public Object getByFuture(final String key) throws Exception {
// 遍历所有服务器进行写操作 此处有待优化
for (MemcachedClientKeeper keeper : serverKeepers) {
if (keeper.getStatus() != MemcachedGroup.NOT_READY && keeper.getStatus() != MemcachedGroup.WRITE_ONLY) {
keeper.getLogic.setKey(key);
Future<Object> f = service.submit(keeper.getLogic);
return f.get();
}
}
return null;
}
/**
* 遍历第一个可读节点即返回
* @param key
* @return
* @throws Exception
*/
public Object get(final String key) throws Exception {
// 遍历所有服务器进行写操作 此处有待优化
for (MemcachedClientKeeper keeper : serverKeepers) {
if (keeper.getStatus() != MemcachedGroup.NOT_READY && keeper.getStatus() != MemcachedGroup.WRITE_ONLY) {
return keeper.getClient().get(key);
}
}
return null;
}
public void put(final String key, final int exp, final Object value) throws Exception {
// 遍历所有服务器进行写操作 此处有待优化
for (MemcachedClientKeeper keeper : serverKeepers) {
if (keeper.getStatus() != MemcachedGroup.NOT_READY && keeper.getStatus() != MemcachedGroup.READ_ONLY) {
XMemcachedClient client = keeper.getClient();
if(client.add(key, exp, value)){
//todo写异常
}
}
}
}
public ExecutorService getService() {
return service;
}
public void setService(ExecutorService service) {
this.service = service;
}
}
还有个接口类 方法定义没家进去 里边还有很多FIXME TODO 主要看看大家的看法 听说XMemcached 的作者要加入集群功能了 首先对此表示非常的感谢
- package com.iuwcity.memcached.group;
- public interface MemcachedGroup {
- public static final int READ_ONLY = 1;
- public static final int WRITE_ONLY = 2;
- public static final int READ_WRITE = 3;
- public static final int NOT_READY = 4;
- public static final int WRITE_NO_READ = 5;
- }
package com.iuwcity.memcached.group;
public interface MemcachedGroup {
public static final int READ_ONLY = 1;
public static final int WRITE_ONLY = 2;
public static final int READ_WRITE = 3;
public static final int NOT_READY = 4;
public static final int WRITE_NO_READ = 5;
}
公司要求可能要用到集群 自己无聊写了一个 与ali的机群客户端一起测试过 由于是基于XMemcached 所以在多线程下速度相对ali较高
欢迎大家给点看法
附件里有写代码是没用的 不用看 就这三类有用