SpringBoot2.x integrated lightweight distributed using regular tasks ShedLock3.x Detailed

 

table of Contents

Foreword

SpringBoot2.x integrated lightweight distributed using regular tasks ShedLock3.x Detailed

First, on ShedLock

Two, ShedLock of three core components

Three, ShedLock using the three-step

Four, SpringBoot integrated ShedLock (to provide lock-based JDBC)

Five, Spring integration ShedLock two modes


Foreword

Some time ago, according to the project requirements, the need to achieve high availability of micro services that will deploy multiple instances of a service, but which involves a lot of timed tasks scheduling problem (... Other ado), thought to want to tentatively use the ShedLock regular tasks to implement a distributed lock This part describes the integration of lightweight distributed SpringBoot2.x regular tasks ShedLock3.x Detailed use.

 

SpringBoot2.x integrated lightweight distributed using regular tasks ShedLock3.x Detailed

First, on ShedLock

ShedLock using thought non-invasive programmed to implement the corresponding functions by way of annotations. ShedLock is a timing task frame for use in a distributed environment, to solve the problem at the same timing tasks in a distributed environment, multiple instances of the same point in time repeatedly executed, Solutions through a common database of a table and lock records, so that the same point in time only the first task execution time and successfully written into the node corresponding records in the database table can be successfully performed while the other nodes skip this task . Of course, not just a database, has been implemented to support data storage types in addition to the classic relational database also includes JDBC, Redis, MongoDB, CosmosDB, DynamoDB, and distributed coordination services Zookeeper, there ElasticSearch etc., it is very rich .

 

Two, ShedLock of three core components

    Core - lock mechanism
    Integration integration by Spring AOP, Micronaut AOP or hand-written code with the application -
    Lock Provider - use a relational database (RDBMS), non-relational database: Mongo, Redis and other external processes to provide a lock

 

Three, ShedLock using the three-step

    1), enable and configure Scheduled lock
    2), add annotations in the Scheduled Tasks above
    3), lock configuration provider (JDBC, Redis, Mongo, etc.)

 

Four, SpringBoot integrated ShedLock (to provide lock-based JDBC)

1), is introduced in pom.xml Spring integrate new dependencies ShedLock

<dependency>
	<groupId>net.javacrumbs.shedlock</groupId>
	<artifactId>shedlock-spring</artifactId>
	<version>3.0.1</version>
</dependency>
<dependency>
	<groupId>net.javacrumbs.shedlock</groupId>
	<artifactId>shedlock-provider-jdbc-template</artifactId>
	<version>3.0.1</version>
</dependency>

 

2), arranged LockProvider, JDBC used herein, it is necessary to configure the JDBC LockProvider, the new lock table -shedlock table corresponding to each instance of the database (note name is the primary key to be) built TABLE statement is as follows:

CREATE TABLE shedlock(
    name VARCHAR(64), 
    lock_until TIMESTAMP(3) NULL, 
    locked_at TIMESTAMP(3) NULL, 
    locked_by VARCHAR(255), 
    PRIMARY KEY (name)
);
COMMENT ON COLUMN "shedlock"."name" IS '锁名称(name必须是主键)';
COMMENT ON COLUMN "shedlock"."lock_until" IS '释放锁时间';
COMMENT ON COLUMN "shedlock"."locked_at" IS '获取锁时间';
COMMENT ON COLUMN "shedlock"."locked_by" IS '锁提供者';

* Note: You must create the table structure based on external memory in the form of a relational database (RDBMS), rather than relational, such as: external storage in the form of non-relational databases such as Redis, template automatically creates a lock according to the name of annotation @SchedulerLock statement corresponding key-value pairs, in order to provide an implementation of the lock.

 

3), arranged LockProvider, LockProvider on several configurations, as implemented here to JDBC,

package com.huazai.aiyou.common.config;

import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * 
 * @author HuaZai
 * @contact [email protected]
 *          <ul>
 * @description 配置 LockProvider
 *              </ul>
 * @className ShedlockConfig
 * @package com.huazai.aiyou.common.config
 * @createdTime 2019年03月20日
 *
 * @version V1.0.0
 */
@Configuration
public class ShedlockConfig
{

	@Bean
	public LockProvider lockProvider(DataSource dataSource)
	{
		return new JdbcTemplateLockProvider(dataSource);
	}
}

Of course, there are more fine-grained configuration is achieved through the Configuration object, you can own to try, as follows:

new JdbcTemplateLockProvider(builder()
    .withTableName("shdlck")
    .withColumnNames(new ColumnNames("n", "lck_untl", "lckd_at", "lckd_by"))
    .withJdbcTemplate(new JdbcTemplate(getDatasource()))
    .withLockedByValue("my-value")
    .build())

* Note: In the process of ShedLock in use, do not manually delete a row or lock a document from a database table. ShedLock have an existing lock memory cache, it will not automatically re-create the line before the application is restarted. If desired, you can edit line or document, the risk of doing so is only to hold multiple locks. In 1.0.0 you can clear the cache by calling clearCache () method on the LockProvider.

 

4), the new "start class project  @EnableSchedulerLock " notes, open ShedLock

package com.huazai.aiyou.controller;

import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * 
 * @author HuaZai
 * @contact [email protected]
 *          <ul>
 * @description 门户网站Web端启动类
 *              </ul>
 * @className AiyouApplication
 * @package com.huazai.aiyou
 * @createdTime 2019年03月20日
 *
 * @version V1.0.0
 */
@EnableHystrix
@EnableCaching
@EnableDiscoveryClient
@EnableFeignClients
@EnableEurekaClient
@EnableCircuitBreaker
@EnableAutoConfiguration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT20M", defaultLockAtLeastFor = "PT20M")
public class AiyouApplication
{

	public static void main(String[] args)
	{
		SpringApplication.run(AiyouApplication.class, args);
	}
}

 

5), add comments "on the need to lock the Scheduled Tasks  @SchedulerLock "

package com.huazai.aiyou.controller.task.schedu;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.core.SchedulerLock;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 
 * @author HuaZai
 * @contact [email protected]
 *          <ul>
 * @description TODO
 *              </ul>
 * @className TaskSchedulerController
 * @package com.huazai.aiyou
 * @createdTime 2019年03月20日
 *
 * @version V1.0.0
 */
@RestController
@Slf4j
public class TaskSchedulerController extends BaseController
{

	// TODO

	/**
	 * 
	 * @author HuaZai
	 * @contact [email protected]
	 * @title sendItemInfoMessage
	 *        <ul>
	 * @description TODO
	 *              </ul>
	 * @createdTime 2019年03月20日
	 * @throws GlobalException
	 * @return void
	 *
	 * @version : V1.0.0
	 */
	@Scheduled(cron = "0 0 0 * * ?")
	@SchedulerLock(name = "sendItemInfoMessage")
	public void sendItemInfoMessage() throws GlobalException
	{
		try
		{
			// TODO
		} catch (Exception e)
		{
			throw new GlobalException(ExceptionCode.global.ITEM_FAIL, ParamContext.NONE_ITEM_INFO);
		}
	}

}

 

Parameter Description:

@SchedulerLock role: only on a way to add a method to the annotation will be locked, the library will ignore all other scheduled tasks. And must specify a name for the lock, so as to at the same time only one task to perform with the same name, in order to achieve the desired lock.

parameter Types of description
name             String               It used to mark a regular service name is used to distinguish between different services written to the database as identification, if there are multiple scheduled tasks with the same name is the same point in time there is only one successful. The default is:""
lockAtMostFor              long

Node successfully perform a task that can have an exclusive lock on the maximum time, in milliseconds ms. The default value is: -1L, said they did not take effect when set to take effect only if a positive integer.

The main attribute specified how long the lock should remain in the case of executing node death. It's just a strain of the plan, lock will be released under normal conditions when the task is completed, even if the node death, after which time the value set will be released, to avoid deadlock situations. But lockAtMostFor must be set to a value much longer than the normal execution time, how much concrete, this would require according to their own judgment on the task. If the time spent on the task compared with lockAtMostFor time, the results may be unpredictable (especially when multiple processes effectively holding the lock).

lockAtMostForString String Node successfully perform a task that can have a long string expression most exclusive lock. For example: "PT30S", denotes 30 seconds; "PT10M", indicates 14 minutes.
lockAtLeastFor long

Node can have a successful mission in the shortest time exclusively in milliseconds ms. The default value is: -1L, said they did not take effect when set to take effect only if a positive integer.

lockAtLeastFor should be retained attribute specifies the minimum time lock, its main purpose is to solve the plurality of nodes performing the task execution time is short, the time difference between the node and the node issues (e.g.: A node is the time 18: 00, B time of the node is 18:08, the time difference at this time is 8 minutes, so this time because the specified lockAtLeastFor> = 8M, ensure that the same tasks are performed only once during this period, no more than once).

lockAtLeastForString String Node can have a successful mission string expression shortest time exclusive lock. For example: "PT30S", denotes 30 seconds; "PT10M", indicates 14 minutes.

 

@EnableSchedulerLock Role: open support of ShedLock

interceptMode The default is: EnableSchedulerLock.InterceptMode.PROXY_METHOD
defaultLockAtMostFor               Exclusive lock string expression node successfully perform a task that can have the most time, such as "PT30S" represents 30 seconds
defaultLockAtLeastFor String expression shortest time an exclusive lock on the node successfully perform a task that can have, for example, "PT30S" is expressed as 30 seconds, the default is: "PT0S"
mode The default is: AdviceMode.PROXY
proxy target class The default is: false

 

* Note: By setting lockAtMostFor, we can ensure that even the death of the node, the lock will be properly released; by setting lockAtLeastFor, we can ensure that it will not perform more than once within a specified time. Note that in the case of node mission of death, lockAtMostFor just to ensure a safe range node to perform, so when setting this time, the time required is much greater than the maximum execution time of assessment tasks. If the time it takes to perform the task longer than lockAtMostFor set, then it may be executed again, that situation appears repeatedly executed the same task, the result will be unpredictable (leading to more process holding the lock).

 

Five, Spring integration ShedLock two modes

ShedLock Spring integration supports two modes. About a scheduling method using AOP agent (PROXY_METHOD), the other agent is a task scheduler (PROXY_SCHEDULER), as shown below:

 

About ShedLock integrated mode, the default values ​​are used under normal circumstances, to understand what you can, do not write here, and if small partner interested can view Quguan network.

 

 

 

references:

ShedLock GitHub related documents: https://github.com/lukas-krecan/ShedLock


 Well, on the integration of lightweight distributed SpringBoot2.x regular tasks ShedLock3.x use Comments To write here, if you have any questions or encounter any questions please scan code to ask questions, you can give me a message oh, my It will be 11 detailed answer. 
Twisters: "common learning and common progress," I hope you lot of attention CSND the IT community.


Author: Hua Tsai
Contact the author: [email protected]
Source: CSDN (Chinese Software Developer Network)
Original statement: https://blog.csdn.net/Hello_World_QWP/article/details/103710853
版权声明: 本文为博主原创文章,请在转载时务必注明博文出处!

 

发布了321 篇原创文章 · 获赞 651 · 访问量 149万+

Guess you like

Origin blog.csdn.net/Hello_World_QWP/article/details/103710853