package com.jd.platform.hotkey.worker.starters;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.ibm.etcd.api.Event;
import com.ibm.etcd.api.KeyValue;
import com.ibm.etcd.client.kv.KvClient;
import com.ibm.etcd.client.kv.WatchUpdate;
import com.jd.platform.hotkey.common.configcenter.ConfigConstant;
import com.jd.platform.hotkey.common.configcenter.IConfigCenter;
import com.jd.platform.hotkey.common.rule.KeyRule;
import com.jd.platform.hotkey.common.tool.FastJsonUtils;
import com.jd.platform.hotkey.common.tool.IpUtils;
import com.jd.platform.hotkey.worker.cache.CaffeineCacheHolder;
import com.jd.platform.hotkey.worker.model.AppInfo;
import com.jd.platform.hotkey.worker.model.TotalCount;
import com.jd.platform.hotkey.worker.netty.dashboard.NettyClient;
import com.jd.platform.hotkey.worker.netty.filter.HotKeyFilter;
import com.jd.platform.hotkey.worker.netty.holder.ClientInfoHolder;
import com.jd.platform.hotkey.worker.netty.holder.WhiteListHolder;
import com.jd.platform.hotkey.worker.rule.KeyRuleHolder;
import com.jd.platform.hotkey.worker.tool.AsyncPool;
import com.jd.platform.hotkey.worker.tool.InitConstant;
import io.grpc.StatusRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static com.jd.platform.hotkey.worker.tool.InitConstant.*;
/**
* worker端对etcd相关的处理
*
* @author wuweifeng wrote on 2019-12-10
* @version 1.0
*/
@Component
public class EtcdStarter {
/**
* 是否开启日志
*/
public static boolean LOGGER_ON = true;
private Logger logger = LoggerFactory.getLogger(getClass());
@Resource
private IConfigCenter configCenter;
@Value("${netty.port}")
private int port;
/**
* 该worker放到etcd worker目录的哪个app下
*/
@Value("${etcd.workerPath}")
private String workerPath;
@Value("${local.address}")
private String localAddress;
@Value("${open.monitor}")
private boolean openMonitor;
private static final String DEFAULT_PATH = "default";
private static final String MAO = ":";
private static final String ETCD_DOWN = "etcd is unConnected . please do something";
// private static final String EMPTY_RULE = "very important warn !!! rule info is null!!!";
/**
* 用来存储临时收到的key总量,来判断是否很久都没收到key了
*/
private long tempTotalReceiveKeyCount;
/**
* 每次10秒没收到key发过来,就将这个加1,加到3时,就停止自己注册etcd 30秒
*/
private int mayBeErrorTimes = 0;
/**
* 是否可以继续上报自己的ip
*/
private volatile boolean canUpload = true;
//Grant:分配一个租约。
//Revoke:释放一个租约。
//TimeToLive:获取剩余TTL时间。
//Leases:列举所有etcd中的租约。
//KeepAlive:自动定时的续约某个租约。
//KeepAliveOnce:为某个租约续约一次。
//Close:貌似是关闭当前客户端建立的所有租约。
/**
* 该worker是否只服务于一个应用
*/
private boolean isForSingle() {
return !DEFAULT_PATH.equals(workerPath);
}
@PostConstruct
public void watchLog() {
AsyncPool.asyncDo(() -> {
try {
String loggerOn = configCenter.get(ConfigConstant.logToggle);
LOGGER_ON = "true".equals(loggerOn) || "1".equals(loggerOn);
} catch (StatusRuntimeException ex) {
logger.error(ETCD_DOWN, ex);
}
KvClient.WatchIterator watchIterator = configCenter.watch(ConfigConstant.logToggle);
while (watchIterator.hasNext()) {
WatchUpdate watchUpdate = watchIterator.next();
List<Event> eventList = watchUpdate.getEvents();
KeyValue keyValue = eventList.get(0).getKv();
logger.info("log toggle changed : " + keyValue);
String value = keyValue.getValue().toStringUtf8();
LOGGER_ON = "true".equals(value) || "1".equals(value);
}
});
}
/**
* 启动回调监听器,监听rule变化
*/
@PostConstruct
public void watch() {
AsyncPool.asyncDo(() -> {
KvClient.WatchIterator watchIterator;
if (isForSingle()) {
watchIterator = configCenter.watch(ConfigConstant.rulePath + workerPath);
} else {
watchIterator = configCenter.watchPrefix(ConfigConstant.rulePath);
}
while (watchIterator.hasNext()) {
WatchUpdate watchUpdate = watchIterator.next();
List<Event> eventList = watchUpdate.getEvents();
KeyValue keyValue = eventList.get(0).getKv();
logger.info("rule changed : " + keyValue);
try {
ruleChange(keyValue);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* 启动回调监听器,监听白名单变化,只监听自己所在的app,白名单key不参与热key计算,直接忽略
*/
@PostConstruct
public void watchWhiteList() {
AsyncPool.asyncDo(() -> {
//获取所有白名单
fetchWhite();
KvClient.WatchIterator watchIterator = configCenter.watch(ConfigConstant.whiteListPath + workerPath);
while (watchIterator.hasNext()) {
WatchUpdate watchUpdate = watchIterator.next();
logger.info("whiteList changed ");
try {
fetchWhite();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void fetchWhite() {
String value = configCenter.get(ConfigConstant.whiteListPath + workerPath);
if (StrUtil.isNotEmpty(value)) {
String[] list = value.split(",");
for (String s : list) {
WhiteListHolder.add(s);
}
}
}
/**
* 每隔1分钟拉取一次,所有的app的rule
*/
@Scheduled(fixedRate = 60000)
public void pullRules() {
try {
if (isForSingle()) {
String value = configCenter.get(ConfigConstant.rulePath + workerPath);
if (!StrUtil.isEmpty(value)) {
List<KeyRule> keyRules = FastJsonUtils.toList(value, KeyRule.class);
KeyRuleHolder.put(workerPath, keyRules);
}
} else {
List<KeyValue> keyValues = configCenter.getPrefix(ConfigConstant.rulePath);
for (KeyValue keyValue : keyValues) {
ruleChange(keyValue);
}
}
} catch (StatusRuntimeException ex) {
logger.error(ETCD_DOWN, ex);
}
}
/**
* 每隔10秒上传一下client的数量到etcd中
*/
@Scheduled(fixedRate = 10000)
public void uploadClientCount() {
try {
String ip = IpUtils.getIp();
for (AppInfo appInfo : ClientInfoHolder.apps) {
String appName = appInfo.getAppName();
int count = appInfo.size();
//即便是full gc也不能超过3秒
configCenter.putAndGrant(ConfigConstant.clientCountPath + appName + "/" + ip, count + "", 13);
}
configCenter.putAndGrant(ConfigConstant.caffeineS
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
京东App后台中间件,毫秒级探测热点数据,毫秒级推送至服务器集群内存,大幅降低热key对数据层查询压力。对任意突发性的无法预先感知的热点请求,包括并不限于热点数据(如突发大量请求同一个商品)、热用户(如爬虫、刷子)、热接口(突发海量请求同一个接口)等,进行毫秒级精准探测到。 然后对这些热数据、热用户等,推送到该应用部署的所有机器JVM内存中,以大幅减轻对后端数据存储层的冲击,并可以由客户端决定如何使用这些热key(譬如对热商品做本地缓存、对热用户进行拒绝访问、对热接口进行熔断或返回默认值)。 这些热key在整个应用集群内保持一致性。
资源推荐
资源详情
资源评论
收起资源包目录
hotkey-master-v0.0.4.zip (650个子文件)
mvnw.cmd 6KB
mvnw.cmd 6KB
mvnw.cmd 6KB
bootstrap.css 143KB
bootstrap.css 120KB
bootstrap.css.map.css 120KB
bootstrap.min.css 118KB
bootstrap.min.css 107KB
style.css 66KB
font-awesome.css 37KB
bootstrap-theme.css 26KB
jquery.treetable.theme.default.css 25KB
bootstrap-theme.min.css 23KB
entypo-icon.css 23KB
font-awesome.min.css 21KB
all.css 21KB
jquery.idealforms.css 17KB
select2.min.css 15KB
layer.css 14KB
all.css 13KB
bootstrap-datetimepicker.css 12KB
bootstrap-switch.css 11KB
bootstrap-datetimepicker.min.css 11KB
extra-pages.css 11KB
ladda.min.css 10KB
iconfont.css 10KB
tooltipster.css 9KB
build.css 9KB
calendar.css 9KB
social.css 7KB
awesome-bootstrap-checkbox.css 7KB
demo.css 6KB
clockface.css 6KB
jquery.steps.css 6KB
dripicon.css 5KB
weather-icons.min.css 5KB
layer.css 5KB
tabelizer.min.css 5KB
datepicker.css 5KB
media.css 5KB
signin.css 5KB
bootstrap-table.min.css 4KB
slidebars.css 4KB
skin-select.css 4KB
DT_bootstrap.css 4KB
bootstrap-timepicker.css 3KB
bootstrap-colorpicker.css 3KB
maki-icons.css 3KB
jquery.treeview.css 3KB
profile.css 3KB
awwwards.css 2KB
base.css 2KB
jquery.stepy.css 2KB
responsive-table.css 2KB
jquery.pnotify.default.css 2KB
acc-wizard.min.css 1KB
jquery.easy-pie-chart.css 1KB
pace-theme-center-simple.css 1KB
bootstrap-treeview.css 1KB
jquery.tagsinput.css 992B
common-add.css 901B
number-pb.css 737B
jquery.treetable.css 652B
datatables.responsive.css 618B
validate.css 583B
open-sans.css 567B
stacktable.css 565B
jquery.numberedtextarea.css 551B
loader-style.css 544B
user-editPwd.css 527B
common-edit.css 509B
icons-style.css 490B
fontawesome-webfont.eot 162KB
entypod41d.eot 74KB
entypo.eot 74KB
weathericons-regular-webfontd41d.eot 28KB
weathericons-regular-webfont.eot 28KB
dripicons.eot 21KB
dripiconsd41d.eot 21KB
glyphicons-halflings-regular.eot 20KB
glyphicons-halflings-regulard41d.eot 20KB
glyphicons-halflings-regular.eot 20KB
makid41d.eot 19KB
maki.eot 19KB
iconfont.eot 10KB
loading-0.gif 6KB
treeview-default-line.gif 2KB
treeview-black-line.gif 2KB
treeview-red-line.gif 2KB
treeview-gray-line.gif 2KB
loading-2.gif 2KB
loading.gif 2KB
treeview-famfamfam.gif 1KB
treeview-gray.gif 1KB
treeview-red.gif 1KB
treeview-default.gif 1KB
treeview-black.gif 1KB
ajax-loader.gif 847B
treeview-famfamfam-line.gif 807B
loading-1.gif 701B
共 650 条
- 1
- 2
- 3
- 4
- 5
- 6
- 7
资源评论
m0_72731342
- 粉丝: 2
- 资源: 1832
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 演讲稿.txt
- 基于Python的爬虫案例-软科中国大学TOP200
- 碳排放权交易明细数据(2024年5月更新).xlsx
- 特殊文件属性命令chattr和lsattr
- HTML、CSS 和 JavaScript动态、交互式的网页 .txt
- b0cd8f9b23d4e5e381b6a8fd8ee0e907.JPG
- ff45d61c5900e45634cf4cac6cff61a1.JPG
- springboot.springboot.springboot.springboot.txt
- linux-进程与服务管理
- 毕业设计基于Django+MySQL+Redis实现简单的天气预报系统python源码.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功