当前位置: 首页 > news >正文

爱站工具包如何增加网站新平台推广

爱站工具包如何增加网站,新平台推广,网站后台输入限制,如何做简易的网站缓存降级设计思想 接前文缺陷点 本地探针应该增加计数器,多次异常再设置,避免网络波动造成误判。耦合度过高,远端缓存和本地缓存应该平行关系被设计为上下游关系了。公用的远端缓存的操作方法应该私有化,避免集成方代码误操作&…

缓存降级设计思想

接前文缺陷点

  1. 本地探针应该增加计数器,多次异常再设置,避免网络波动造成误判。
  2. 耦合度过高,远端缓存和本地缓存应该平行关系被设计为上下游关系了。
  3. 公用的远端缓存的操作方法应该私有化,避免集成方代码误操作,导致受到攻击。
  4. 探针改为轮训请求,类似jedis底层心跳检测。
  5. 抽象多层策略,提供集成方自定义实现配置来决定采用什么方式进行降级,缓存工厂或者控制器来决定Redis是否异常和异常后走本地缓存还是数据库还是zk等策略。
  6. 底层应该做好职责分离,异常往上抛,由上层根据用户配置的策略做对应的处理逻辑。
  7. 业务层采用模板模式,对Redis降级后的业务逻辑提供有结构性的模板方法,并要支持用户灵活重写,支持重写的方法名不要取的具体,应取的抽象。
1.创建缓存操作接口定义缓存数据的增删改查方法,底层由redis工具类实现作为一级缓存,另一个实现可以选择本地缓存工具类或第三方数据存储工具类实现,作为二级缓存在redis降级时使用。
public interface IWecareCache {/*** 根据key,获取到对应的value值* 注: 若key不存在, 则返回null** @param key key-value对应的key* @return 该key对应的值。*/String get(String key);。。。
}@Component(WecareSsoConstant.CACHE_TYPE_REDIS)
public class WecareRedisCache implements IWecareCache {private final JedisCluster jedis = StaticSingletonFactory.getJedisSingleton();@Overridepublic String get(String key) {log.debug("[JedisCluster]: get -> key={}", key);return jedis.get(key);}。。。
}@Component(WecareSsoConstant.CACHE_TYPE_LOCAL)
public class WecareLocalCache implements IWecareCache {/*** 本地缓存记录str的key*/private static final String STRING_KEY = "StringKey@";private final Cache<String, Map<String, String>> wecareLocalCache = StaticSingletonFactory.getLocalCacheSingleton();@Overridepublic String get(String key) {// 先判断是否key对应的map是否存在Map<String, String> map = wecareLocalCache.getIfPresent(key);if (CollectionUtils.isEmpty(map)) {return null;}log.debug("[localCache]: get -> key={},value={}", key, map.get(STRING_KEY));return map.get(STRING_KEY);}。。。
}

2.创建缓存策略接口用于实现根据策略选择获取什么缓存核心进行操作,并提供一个默认策略实现,再在工厂中提供热加载方法,如果存在自定义实现则优先获取自定义策略实现
public interface ICacheStrategy {// 根据策略自动选择具体缓存实现的方法IWecareCache getCacheByStrategy();// 根据指定缓存名称获取缓存实现的方法IWecareCache getCacheByName(String cacheName);// 查询redis运行状态是否OKboolean isRedisOK();// 设置redis状态为正常void setRedisAvailable();// 设置redis状态为异常void setRedisNotAvailable();
}// SDK缓存策略默认实现,根据redis监听状态进行远端缓存和本地缓存的热切换
@Component(WecareSsoConstant.DEFAULT_CACHE_STRATEGY)
public class DefaultCacheStrategy implements ICacheStrategy {// redis是否可用--策略读取,监控更新private final AtomicBoolean redisIsLive = new AtomicBoolean(false);// 可用缓存工具-自动注入@Autowiredprivate Map<String, IWecareCache> cacheMap;//默认缓存策略-如果redis异常则使用jvm缓存//--如果不需要降级,请实现自定义策略始终返回redis缓存即可@Overridepublic IWecareCache getCacheByStrategy() {IWecareCache cacheByDefaultStrategy = getCacheByDefaultStrategy();if (cacheByDefaultStrategy == null) {log.error("no config cache");throw new BizException("no config cache");}return cacheByDefaultStrategy;}@Overridepublic IWecareCache getCacheByName(String cacheName) {return cacheMap.get(cacheName);}@Overridepublic boolean isRedisOK() {return redisIsLive.get();}// 默认redis状态实现-通过AtomicBoolean控制@Overridepublic void setRedisAvailable() {redisIsLive.set(true);}// 默认redis状态实现-通过AtomicBoolean控制@Overridepublic void setRedisNotAvailable() {redisIsLive.set(false);}private IWecareCache getCacheByDefaultStrategy() {if (redisIsLive.get()) {return cacheMap.get(WecareSsoConstant.CACHE_TYPE_REDIS);} else {return cacheMap.get(WecareSsoConstant.CACHE_TYPE_LOCAL);}}
}

3.创建缓存工具类,提供缓存操作方法,每次操作缓存都通过策略获取对应的缓存核心进行操作,实现热降级
public class WecareCacheUtil {private static final ICacheStrategy cacheStrategy = StaticSingletonFactory.getCacheStrategy();// 根据策略获取缓存实现private static IWecareCache getCacheByStrategy() {return cacheStrategy.getCacheByStrategy();}// 根据缓存名称获取指定缓存实现--默认拥有REDIS和JVM两个private static IWecareCache getCacheByName(String cacheName) {return cacheStrategy.getCacheByName(cacheName);}public static boolean isRedisOK(){return cacheStrategy.isRedisOK();}public static String get(String key) {return getCacheByStrategy().get(key);}// 根据名称操作指定缓存实现,业务需要在正常流程时预先在jvm存储用户信息。public static String get(String key, String cacheName) {return getCacheByName(cacheName).get(key);}。。。

4.创建redis监控接口用于定义redis的监控方式,提供默认实现并同策略接口一样支持自定义实现的热加载,创建执行监控的线程类
public interface IRedisMonitor {void healthCheck();
}@Component(WecareSsoConstant.DEFAULT_REDIS_MONITOR)
public class DefaultRedisMonitor implements IRedisMonitor {// 连接异常最大次数private static final int MAX_ERROR_COUNT = 2;// 心跳频率:多少毫秒检测一次private static final int HEART_BEAT_FREQUENCY = 5000;private final JedisCluster jedis = StaticSingletonFactory.getJedisSingleton();private final ICacheStrategy cacheStrategy = StaticSingletonFactory.getCacheStrategy();// redis集群为6主多备,因此检测到任意一个主节点宕机就算集群failed,集群failed超过阈值则设置redis集群状态不可用,此方法是否可监控连接数满导致的异常还有待测试private boolean isAllNodesActivated() {try {Map<String, JedisPool> clusterNodes = jedis.getClusterNodes();for (Map.Entry<String, JedisPool> entry : clusterNodes.entrySet()) {JedisPool pool = entry.getValue();String clusterInfo;try (Jedis jedisResource = pool.getResource()) {clusterInfo = jedisResource.clusterInfo();}if (!clusterInfo.contains("cluster_state:ok")) {log.error("redis node:{} cluster_state:fail", entry.getKey());log.error("clusterInfo:{}", clusterInfo);return false;}}return true;}catch (JedisException jedisException){log.error("redis 读取节点信息异常 jedisException:",jedisException);}catch (Exception exception){try {jedis.set("testHealthCheck","true");String testHealthCheck = jedis.get("testHealthCheck");if ("true".equals(testHealthCheck)) {return true;}}catch (Exception e){log.error("redis 操作测试异常 exception:",e);}log.error("redis 读取节点信息异常 exception:",exception);}return false;}@Overridepublic void healthCheck() {int threadException = 0;int redisErrorCount = 0;LocalDateTime lastLogTime = LocalDateTime.now().minusMinutes(1);while (true) {try {Thread.sleep(HEART_BEAT_FREQUENCY);if (isAllNodesActivated()) {redisErrorCount = 0;cacheStrategy.setRedisAvailable();LocalDateTime now = LocalDateTime.now();if (Duration.between(lastLogTime,now).toMinutes()>0) {log.info("Redis Cluster Nodes Health Check OK");lastLogTime = now;}} else {redisErrorCount++;if (redisErrorCount >= MAX_ERROR_COUNT) {redisErrorCount = 0;cacheStrategy.setRedisNotAvailable();log.info("Redis Cluster Nodes Health Check Failed!!!");}}} catch (InterruptedException interruptedException) {log.error("redis监控线程休眠异常!", interruptedException);if (threadException > 3) {log.error("redis监控线程因休眠异常强制终止!", interruptedException);break;}threadException++;}}}
}
// 监控线程类:提供启动redis监控的方法
public class RedisMonitorThread implements Runnable {private final IRedisMonitor monitor;public RedisMonitorThread(IRedisMonitor monitor) {this.monitor = monitor;}@Overridepublic void run() {monitor.healthCheck();}public static void startMonitor(IRedisMonitor monitor) {new Thread(new RedisMonitorThread(monitor),monitor.getClass().getSimpleName()+"-Thread").start();}
}

5.创建单例转静态对象的工厂,用于将spring管理的动态单例转换为静态单例,全局提供静态方法,并定义线程初始化和类加载
@Component
public class StaticSingletonFactory implements ApplicationContextAware {// 缓存策略实现private static Map<String, ICacheStrategy> cacheStrategyMap;// redis监控实现private static Map<String, IRedisMonitor> redisMonitorMap;private static JedisCluster jedis;// 本地缓存private static Cache<String, Map<String, String>> wecareSsoLocalCache;// 配置参数private static ConfigProperty configProperty;//  静态工厂bean初始化--赋值顺序要按照使用顺序,且代码避免循环依赖@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {configProperty = applicationContext.getBean(ConfigProperty.class);// 策略集合赋值cacheStrategyMap = applicationContext.getBeansOfType(ICacheStrategy.class);if (configProperty.isRedisEnabled()) {// 确认开启使用redis功能jedis = applicationContext.getBean("sdkJedisClient", JedisCluster.class);// 监控集合赋值redisMonitorMap = applicationContext.getBeansOfType(IRedisMonitor.class);// 在赋值jedis客户端后启动监听线程RedisMonitorThread.startMonitor(getRedisMonitor());}wecareSsoLocalCache = (Cache<String, Map<String, String>>) applicationContext.getBean("wecareSsoLocalCache");}public static JedisCluster getJedisSingleton() {return jedis;}public static Cache<String, Map<String, String>> getLocalCacheSingleton() {return wecareSsoLocalCache;}public static ConfigProperty getConfigProperty() {return configProperty;}// 指定策略实现public static ICacheStrategy getCacheStrategy(String cacheStrategyName) {ICacheStrategy iCacheStrategy = cacheStrategyMap.get(cacheStrategyName);if (iCacheStrategy == null) {throw new BizException("Select CacheStrategy Error, cacheStrategyName " + cacheStrategyName + " undefined !");}return iCacheStrategy;}// 获取缓存策略实现public static ICacheStrategy getCacheStrategy() {return hotLoading(cacheStrategyMap, WecareSsoConstant.DEFAULT_CACHE_STRATEGY, ICacheStrategy.class);}// 获取redis监控实现public static IRedisMonitor getRedisMonitor() {return hotLoading(redisMonitorMap, WecareSsoConstant.DEFAULT_REDIS_MONITOR, IRedisMonitor.class);}// 接口实现类热加载,有自定义实现返回自定义,无自定义实现返回默认实现private static <T> T hotLoading(Map<String, T> map, String defaultName, Class<T> obj) {String className = obj.getSimpleName();int size = map.size();switch (size) {case 0:throw new BizException(className + " init Error, no implements !");case 1:return map.get(defaultName);case 2:for (Map.Entry<String, T> entry : map.entrySet()) {if (!defaultName.equals(entry.getKey())) {return entry.getValue();}}break;default:break;}throw new BizException("Select " + className + " Error, expected 1 but found " + size);}
}

文章转载自:
http://dinncoscraggly.wbqt.cn
http://dinncoobbligato.wbqt.cn
http://dinncocymagraph.wbqt.cn
http://dinncopigeongram.wbqt.cn
http://dinncocriminally.wbqt.cn
http://dinncobourgeon.wbqt.cn
http://dinncoophiology.wbqt.cn
http://dinncosuperport.wbqt.cn
http://dinncoforecastle.wbqt.cn
http://dinncooctet.wbqt.cn
http://dinncoacrylic.wbqt.cn
http://dinncothymectomy.wbqt.cn
http://dinncoparodos.wbqt.cn
http://dinncocollation.wbqt.cn
http://dinncokharkov.wbqt.cn
http://dinncoeluviation.wbqt.cn
http://dinncokottbus.wbqt.cn
http://dinncokingless.wbqt.cn
http://dinncocosmine.wbqt.cn
http://dinncofslic.wbqt.cn
http://dinncokidnaper.wbqt.cn
http://dinncohater.wbqt.cn
http://dinncoward.wbqt.cn
http://dinncomonogenesis.wbqt.cn
http://dinncomethylamine.wbqt.cn
http://dinncomizzensail.wbqt.cn
http://dinncosultry.wbqt.cn
http://dinncohierolatry.wbqt.cn
http://dinncosphygmoscope.wbqt.cn
http://dinncoabdication.wbqt.cn
http://dinncosagaciousness.wbqt.cn
http://dinncosilentious.wbqt.cn
http://dinncoclique.wbqt.cn
http://dinncoethynyl.wbqt.cn
http://dinncorostriform.wbqt.cn
http://dinncovexilla.wbqt.cn
http://dinncotransvesical.wbqt.cn
http://dinncodecimally.wbqt.cn
http://dinncoruinously.wbqt.cn
http://dinncovibrato.wbqt.cn
http://dinncosolutionist.wbqt.cn
http://dinncolazyback.wbqt.cn
http://dinncoextrasystole.wbqt.cn
http://dinncoblackthorn.wbqt.cn
http://dinncoapotropaic.wbqt.cn
http://dinncoabac.wbqt.cn
http://dinnconaxalite.wbqt.cn
http://dinncocomate.wbqt.cn
http://dinncotappoon.wbqt.cn
http://dinncoenthymeme.wbqt.cn
http://dinncobetake.wbqt.cn
http://dinncodimness.wbqt.cn
http://dinncohardly.wbqt.cn
http://dinncoceylonese.wbqt.cn
http://dinncoexpert.wbqt.cn
http://dinncosuperabound.wbqt.cn
http://dinncoqualificator.wbqt.cn
http://dinncozendo.wbqt.cn
http://dinncoboustrophedon.wbqt.cn
http://dinncoadvice.wbqt.cn
http://dinncoareology.wbqt.cn
http://dinncobt.wbqt.cn
http://dinncoalmshouse.wbqt.cn
http://dinncoclapstick.wbqt.cn
http://dinncokursk.wbqt.cn
http://dinncoiniquitious.wbqt.cn
http://dinncochanceless.wbqt.cn
http://dinncocineast.wbqt.cn
http://dinncotympanites.wbqt.cn
http://dinncorelativize.wbqt.cn
http://dinncobattel.wbqt.cn
http://dinncopearlash.wbqt.cn
http://dinncoabundant.wbqt.cn
http://dinncoshinbone.wbqt.cn
http://dinncomalaria.wbqt.cn
http://dinncoruggedize.wbqt.cn
http://dinncoargali.wbqt.cn
http://dinncorusset.wbqt.cn
http://dinncoensorcel.wbqt.cn
http://dinncolandsting.wbqt.cn
http://dinncopedometer.wbqt.cn
http://dinncoprintable.wbqt.cn
http://dinncooverpopulation.wbqt.cn
http://dinncodiscernible.wbqt.cn
http://dinnconeedlefish.wbqt.cn
http://dinncopolling.wbqt.cn
http://dinncounicef.wbqt.cn
http://dinncosulfanilamide.wbqt.cn
http://dinncoprescind.wbqt.cn
http://dinncotimber.wbqt.cn
http://dinncopanurge.wbqt.cn
http://dinncostrangelove.wbqt.cn
http://dinnconadine.wbqt.cn
http://dinncopasteurisation.wbqt.cn
http://dinncogorm.wbqt.cn
http://dinncocannot.wbqt.cn
http://dinncokamikaze.wbqt.cn
http://dinncostupor.wbqt.cn
http://dinncocusk.wbqt.cn
http://dinncofluonomist.wbqt.cn
http://www.dinnco.com/news/156535.html

相关文章:

  • 数据来源于网站需如何做脚注推广渠道平台
  • 济南做网站的机构有哪些快速优化网站排名软件
  • 360网站收录提交app开发需要多少费用
  • 怎样做一张网站的banner网络营销的常用方法
  • 如何对自己做的php网站加密seo网址超级外链工具
  • 做网站想要个计算器功能营销网站大全
  • 武汉 酒店 网站制作百度推广怎么样才有效果
  • 昆明网站建设服务成都网络优化托管公司
  • 网站控制板面网站关键词上首页
  • 数码网站建设维护建网站找哪个平台好呢
  • 徐州网站建站关键词排名提升工具
  • 主机网站建设引擎seo优
  • 怎做视频网站百度指数分析数据
  • 自己建网站做网店域名注册信息查询whois
  • 网站建设方案书范本学it什么培训机构好
  • 国外设计网站都有哪些seo网站推广杭州
  • 网站做水印有没有影响吗百度问答下载安装
  • 个人网站可以做咨询吗天津seo关键词排名优化
  • 武汉seo代理商下载班级优化大师并安装
  • 网站制作内联框如何进行网站推广?网站推广的基本手段有哪些
  • 中企动力做网站要全款杭州seo全网营销
  • 做娱乐网站的意义目的b2b电商平台
  • 直接翻译网页的软件福州短视频seo网站
  • 网站统计页面模板免费源码下载网站
  • 网站优化推广方案重庆seo多少钱
  • 东莞网站建设设营销方案范文100例
  • 武汉做网站互云网站友情链接连接
  • 免费建设在线商城的网站口碑营销的产品
  • 山西省网站百度竞价包年推广公司
  • 国家城乡建设部投诉网站印度疫情为何突然消失