Elasticsearch 高扩展且开源的全文检索和分析引擎(可以在承载 PB 级数据的成百上千台服务器上运行)
概念:
Near Realtime(NRT 近实时,不是 实时读写。)
Cluster(集群) 一个或者多个节点的集合,它们一起保存数据并且提供所有节点联合索引以及搜索功能
Node(节点) 一个单独的服务器,它是集群的一部分,存储数据,参与集群中的索引和搜索功能
Index(索引) 具有稍微类似特征文档的集合
Type(类型) 在索引中定义,标识不同的文档字段信息(Type在6.0.0版本中已经不赞成使用)
Document(文档) 是索引信息的基本单位,用json来表示
Shards & Replicas(分片 & 副本) 索引拆分成分片&索引备份
以上就是简单的基本介绍,估计没接触的人肯定一脸懵逼。我偷懒直接用msi装的,不安装系统服务,通过bin目录下elasticsearch.exe来启动(cmd .\elasticsearch.exe)。节点名称my_node,ip默认本机地址,端口号默认9200。
Springboot项目配置
pom.xml
<!-- elasticsearch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>复制
application.properties
# elasticsearch
#集群名
spring.data.elasticsearch.cluster-name = elasticsearch
#节点地址 配置9200是通过HTTP连接的端口,9300是TCP连接的端口
spring.data.elasticsearch.cluster-nodes = 127.0.0.1:9300
spring.data.elasticsearch.repositories.enable = true复制
实体类
@Document(indexName = "esindex")
public class Esentity {
@Id
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}复制
Dao层
@Component
public interface Esdao extends ElasticsearchRepository<Esentity, String>{
}复制
控制类,仿照网上的,实现简单的CRUD
@RestController
@RequestMapping("/es")
public class Escontroller {
@Autowired
private Esdao esdao;
@RequestMapping("/add/{id}")
public String add(@PathVariable("id")String id){
Esentity esentity=new Esentity();
esentity.setId(id);
esentity.setName("Tom");
esdao.save(esentity);
return "add success";
}
@RequestMapping("/delete")
public String delete(){
Esentity esentity=new Esentity();
esentity.setId("1");
esdao.delete(esentity);
return "delete success";
}
@RequestMapping("/update")
public String update(){
Esentity esentity = esdao.findById("1").get();
esentity.setName("Jerry");
esdao.save(esentity);
return "update success";
}
@RequestMapping("/query/{id}")
public Esentity query(@PathVariable("id")String id){
return esdao.findById(id).get();
}
}复制
可以通过Elasticsearch-Head集群操作和管理工具界面来查看数据。
忽然发现部分定时器一直在运行,原来是通过@Scheduled注解定义的。当然实际的项目一般不会写死。虽然后来用spring自带的又写了一个动态的定时器,但是还是想知道如何停止通过注解定义的定时器(搬砖的执着)。
动态定时器
@Component
public class DynamicSpringTasks {
@Autowired
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
private Map<String, ScheduledFuture<?>> futureMap = new HashMap<String, ScheduledFuture<?>>();
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
/**
* 设定定时任务
* @param key
* @param cron
* @return
*/
public ScheduledFuture<?> startTask(String key, String cron) {
ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(new Runnable(){
@Override
public void run() {
System.out.println(key + " : Starting......");
}
}, new CronTrigger(cron));
futureMap.put(key, future);
System.out.println(key + " : Started");
return future;
}
/**
* 停止定时任务
* @param key
*/
public void stopTask(String key) {
if (futureMap != null && futureMap.get(key) != null) {
futureMap.get(key).cancel(true);
futureMap.remove(key);
}
System.out.println(key + " : ......Stoped");
}
public void testTask() {
System.out.println("testing......");
startTask("test1", "0/5 * * * * ?");
startTask("test2", "0/3 * * * * ?");
try {
Thread.sleep(25L * 1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
stopTask("test1");
}
}复制
国内貌似找不到停止的资料,StackOverflow①上找到一个解决方案,其他大部分搜索结果都预期类似。但是只试成功第一种解决方案,第二种用了一晚上也没试出来(此处省略)……果然是个渣渣,有方案都解决不了。然后参考这个,开始想自己的思路。因为方法里边想要的对象是私有的,然后反射,问题解决。
// 停止所有task 法1
// Set<ScheduledTask> test = postProcessor.getScheduledTasks();
// test.forEach(v -> v.cancel());
// 停止所有task 法2
// postProcessor.destroy();
// 停止某一个类task
// 法1 通过ScheduledAnnotationBeanPostProcessor的postProcessBeforeDestruction来停止相关的bean
// postProcessor.postProcessBeforeDestruction(scheduledTasks, null);
try {
// 法2 通过反射获取ScheduledAnnotationBeanPostProcessor的私有变量scheduledTasks来停止相关的ScheduledTask
Field field = postProcessor.getClass().getDeclaredField("scheduledTasks");
field.setAccessible(true);
Map<Object, Set<ScheduledTask>> scheduledTasks = (Map<Object, Set<ScheduledTask>>) field.get(postProcessor);
scheduledTasks.forEach((k, v) -> {
if (k instanceof ScheduledTasks2) {
v.forEach(task -> {
System.out.println(task.toString());
// 可以根据名字单独停止一个
if ("com.xuchl.quartz.quartz.util.ScheduledTasks2.testFixedRate".equals(task.toString())) {
task.cancel();
}
});
}
});
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}复制
然而并没有任何意义,实际的项目不会这么写。最近又开始失眠,被某人传染了吗!比我强的人都在努力学习,自己又有什么理由不努力呢。来写些这种没有技术含量的文章来安慰自己吗?
①https://stackoverflow.com/questions/44644141/how-to-stop-a-scheduled-task-that-was-started-using-scheduled-annotation