Javaはredisを通じてクラスタのタイミングタスクを管理します
3554 ワード
前言
実習の時、筆者はspring-taskとquartzのフレームワークに接触し、javaプログラマーはいずれもタイミングタスクの需要があり、単機でタイミングタスクを使用するのは簡単だが、クラスタ環境では難しいと信じている.は、1台のマシンだけがタイミングタスクを実行する をどのように限定するか.あるサービスがダウンタイムした後、どのようにフェイルオーバを行うか 実行中のサービスをどのように決定するか この問題には公式に解決策があるに違いない.資料も少なくない.quartzクラスタ分布式(同時)配置ソリューション-Springは筆者は怠け者だが、上述のソリューションには多くのquartzテーブルを配置する必要があり、業務にはタイミングタスクを動的に配置する必要はなく、quartzフレームワークに依存していない.したがって,他の方法を用いてタイミングタスクの分散スケジューリングを実現することを考慮する.
Uncode-Scheduleの初期試行
Uncode-Scheduleは筆者がオープンソース中国で見たオープンソースの分散スケジューリングタスクコンポーネントであり、springとの統合が比較的容易で、使用が便利で、zookeeperを借りている.ここで私はあまり評価しません.結局、個人のオープンソースフレームワークなので、使用中にいくつかの穴を踏んだのか、ドキュメントがまだそろっていないので、しばらくしてから廃棄することにしました.興味のある学生は以下のことを理解することができます:分布式タスクスケジューリングコンポーネントUncode-Scheduleは幸いにも穴を埋める過程でこのタスクスケジューリングの過程に対して一定の理解があって、そこで自分で簡単なタスクスケジューラを実現することを決定しました.
redisによるタスクスケジューリングの考え方
機能を実装する前に、シングルポイント実行、フェイルオーバ、サービスステータスの3つの問題をレビューします.redisのいくつかのインタフェースの特性を結びつけて、解決の構想は以下の通りです:タスクスケジューリングセンタとしてredisを用いる、redisの自動期限切れと分散ロック特性 を採用した.各サービスのipプラスプロジェクト名は、各サービスの一意の別名 として使用される.は、redisのkey値に対応するvalueによって、どのサービスが実行されるかを判定する.例えば、redisのkeyがschedular_であるroot:projectA,valueは192.168.1.187. プロジェクトプロジェクトAが現在実行するタスクを意味するノードは192.168である.1.187この機械のサービス タスクを実行するたびにredisでschedular_を判定するroot:projectAが空かどうか、空であれば現在のipを設定し、一定時間の有効期間を設定し、タイミングタスクを実行します.空でない場合は、自機ipと同一か否かを判断し、同一である場合はタイミングタスクを実行し、そうでない場合は をスキップする.有効期間を設けるのは、ある機器が故障した場合にフェイルオーバできるようにするための である.
コアプロセスコード
このソリューションは非常に簡単で,コアコードも集積しやすく,結合度を低減するためにspringのaopを用いて実現した.
コアAOPコード
RedisUtilのロックコード
コアコードはすでに全放送されており、redisについては分散ロックを実現し、別の時間に皆さんと共有しますので、ご注目ください.
実習の時、筆者はspring-taskとquartzのフレームワークに接触し、javaプログラマーはいずれもタイミングタスクの需要があり、単機でタイミングタスクを使用するのは簡単だが、クラスタ環境では難しいと信じている.
Uncode-Scheduleの初期試行
Uncode-Scheduleは筆者がオープンソース中国で見たオープンソースの分散スケジューリングタスクコンポーネントであり、springとの統合が比較的容易で、使用が便利で、zookeeperを借りている.ここで私はあまり評価しません.結局、個人のオープンソースフレームワークなので、使用中にいくつかの穴を踏んだのか、ドキュメントがまだそろっていないので、しばらくしてから廃棄することにしました.興味のある学生は以下のことを理解することができます:分布式タスクスケジューリングコンポーネントUncode-Scheduleは幸いにも穴を埋める過程でこのタスクスケジューリングの過程に対して一定の理解があって、そこで自分で簡単なタスクスケジューラを実現することを決定しました.
redisによるタスクスケジューリングの考え方
機能を実装する前に、シングルポイント実行、フェイルオーバ、サービスステータスの3つの問題をレビューします.redisのいくつかのインタフェースの特性を結びつけて、解決の構想は以下の通りです:
コアプロセスコード
このソリューションは非常に簡単で,コアコードも集積しやすく,結合度を低減するためにspringのaopを用いて実現した.
コアAOPコード
@Aspect
@Component
@Log4j
public class QuartzAop {
public boolean checkStatus(){
String key = "schedular_root:projectA";
try {
// ,
while (true) {
//
boolean lock = RedisUtil.checkLock(key,1);
if (lock) {
// ,
break;
}
}
String ip = InetAddress.getLocalHost().getHostAddress();
// ip
String currentIp = RedisUtil.get(key);
// ,
if(currentIp == null){
RedisUtil.setex(key, ip, 10);
return true;
}
// , true
if(currentIp.equals(ip)){
return true;
}else{
return false;
}
} catch (Exception e) {
log.error(e);
return false;
} finally {
RedisUtil.unLock(key);
}
}
@Around("@annotation(org.springframework.scheduling.annotation.Scheduled)")
public void around(ProceedingJoinPoint jp) throws Throwable{
if(checkStatus()){
String ip = InetAddress.getLocalHost().getHostAddress();
log.info(" "+jp.getSignature()+":"+ip);
jp.proceed();
}
}
}
RedisUtilのロックコード
public static boolean checkLock(String key,int second) {
String lockKey = "lock:" + key;
try {
// 1 ,
if (setnx(lockKey, "lock") == 1) {
//
setExpiredTime(lockKey, second);
return true;
} else {
// 50 ,
try {
Thread.sleep(50L);
} catch (InterruptedException e) {
log.error(e);
}
return false;
}
} catch (RedisException e) {
log.error(e);
return true;
}
}
コアコードはすでに全放送されており、redisについては分散ロックを実現し、別の時間に皆さんと共有しますので、ご注目ください.