暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Elasticsearch(划掉) SpringBoot Scheduled注解的停止

糸色望TestBeta 2021-05-16
308

  Elasticsearch 高扩展且开源的全文检索和分析引擎(可以在承载 PB 级数据的成百上千台服务器上运行)

  概念:

Near RealtimeNRT 近实时,不是 实时读写。)

Cluster(集群) 一个或者多个节点的集合,它们一起保存数据并且提供所有节点联合索引以及搜索功能

Node(节点) 一个单独的服务器,它是集群的一部分,存储数据,参与集群中的索引和搜索功能

Index(索引) 具有稍微类似特征文档的集合

Type(类型) 在索引中定义,标识不同的文档字段信息(Type6.0.0版本中已经不赞成使用)

Document(文档) 是索引信息的基本单位,用json来表示

Shards & Replicas(分片 & 副本) 索引拆分成分片&索引备份

  以上就是简单的基本介绍,估计没接触的人肯定一脸懵逼。我偷懒直接用msi装的,不安装系统服务,通过bin目录下elasticsearch.exe来启动(cmd .\elasticsearch.exe)。节点名称my_nodeip默认本机地址,端口号默认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<ObjectSet<ScheduledTask>> scheduledTasks = (Map<ObjectSet<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

文章转载自糸色望TestBeta,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论