可以从内存,客户端获取了配置中心的配置信息以后,会将配置信息在本地内存中存储一份
在本地中靠Map对象存储
客户端每隔30s向Nacos配置中心发起一次请求,拉取一次配置信息 wait29.5s
没有配置更新时,客户端会在Nacos服务端的队列中等待
每隔XX秒发送一次请求定时任务调度
package com.jt.common.util;
import java.util.Timer;
import java.util.TimerTask;
/*单线程定时任务工具类*/
public class TimerUtils {
public static void main(String[] args) {
//1.构建执行任务对象
Timer timer=new Timer();/*创建对象时,会创建一个线程,并且为线程分配一个任务队列*/
//2.构建任务对象
TimerTask task1=new TimerTask() {
@Override
public void run() {
System.out.println(System.currentTimeMillis());
}
};
//3.定时执行任务
timer.schedule(task1, 1000, 1000);
}
}
实现效果
结束任务
timer.cancle();
package com.jt.common.util;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/*多线程定时任务工具类*/
public class ScheduledExecutorServiceUtils {
public static void main(String[] args) {
/*1.构建一个负责任务调度的线程池对象*/
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(5);
/*2.任务对象*/
Runnable runnable=new Runnable() {
@Override
public void run() {
String tName=Thread.currentThread().getName();
System.out.println(tName+"->"+System.currentTimeMillis());
}
};
/*3.任务调度*/
scheduledExecutorService.
scheduleAtFixedRate(runnable,1000,//1s以后开始执行
1000,//每隔1s开始执行 与任务是否执行完毕无关
TimeUnit.MILLISECONDS);//时间单位
}
}
server:
port: 8082
spring:
application:
name: sca-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #假如nacos和你的服务在一台电脑上,默认服务本机,是可以省略的
config:
server-addr: localhost:8848 #配置中心的地址
file-extension: yml #添加配置中心配置格式
namespace: 1ec9fffa-c171-458d-815d-502a52daf446 #指定命名空间
logging:
level:
com.jt: debug #配置com.jt包以及子包中的日志级别 默认是info
public配置信息
dev配置信息
测试结果
说明读取的是指定命名空间的配置中心信息,也就是dev中的sca-provider名字的配置信息
若不指定命名空间,则默认为pubilic空间
package com.jt.provider.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RefreshScope
@RestController
public class ProviderCacheController {
@Value("${useLocalCache:false}")
private boolean useLocalCache;
@RequestMapping("/provider/cache")
public String doUseLocalCache(){
return "useLocalCache'value is "+useLocalCache;
}
}
package com.jt.common.thread;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class SyncTests {
//private static List cache=new Vector<>();
//CopyOnWriteArrayList是一个线程安全的List集合,允许多个线程执行并发更新,但是只能有一个更新成功.
private static List<String> cache=new CopyOnWriteArrayList<>();//CAS(比较和交换)
// public synchronized static List selectAll(){
// if (cache.isEmpty()) {
// System.out.println("Get Data From Database");
// List data = Arrays.asList("A", "B", "C");
// cache.addAll(data);
// }
// return cache;
// }
public static List<String> selectAll(){
if(cache.isEmpty()) {//A,B,C,D
synchronized (cache) {
if (cache.isEmpty()) {
System.out.println("Get Data From Database");
List<String> data = Arrays.asList("A", "B", "C");
cache.addAll(data);
}
}
}
return cache;
}
public static void main(String[] args) {
//System.out.println(Thread.currentThread().getName());
Thread t1=new Thread(){
@Override
public void run() {
System.out.println(selectAll());
}
};
Thread t2=new Thread(){
@Override
public void run() {
System.out.println(selectAll());
}
};
Thread t3=new Thread(){
@Override
public void run() {
System.out.println(selectAll());
}
};
Thread t4=new Thread(){
@Override
public void run() {
System.out.println(selectAll());
}
};
Thread t5=new Thread(){
@Override
public void run() {
System.out.println(selectAll());
}
};
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
package com.jt.provider.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@RefreshScope
@RestController
public class ProviderCacheController {
@Value("${useLocalCache:false}")
private boolean useLocalCache;
@RequestMapping("/provider/cache")
public String doUseLocalCache(){
return "useLocalCache'value is "+useLocalCache;
}
//构建一个本地(Local)缓存对象(基于jvm中的一个对象存储从数据库获取的数据).
private List<String> cache=new CopyOnWriteArrayList<>();
@RequestMapping("/provider/cache02")
public List<String> doUseLocalCache02(){
if(!useLocalCache){
System.out.println("==Get data from database==");
List<String> cates = Arrays.asList("Category-A", "Category-B", "Category-C");
}
if(cache.isEmpty()){
synchronized (cache) {
if (cache.isEmpty()) {//Thread-A,Thread-B,...
System.out.println("==Get data from database==");
//假设这部分分类信息是从数据库获取的,但是,我不希望每次获取分类信息都要从数据库查
List<String> cates = Arrays.asList("Category-A", "Category-B", "Category-C");
cache.addAll(cates);
}
}
}
return cache;
}//生产层面
}
配置中新为false
实现效果
redis分布式缓存
lruCache 本地缓存+分布式缓存
package com.jt.provider.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
public class ProviderSecretController {
@Value("${app.secret:123456}")
private String secret;
@GetMapping("/provider/doGetSecret")
public String doGetSecret(){
return "the secret is"+secret;
}
}