Prefácio
Para garantir alta disponibilidade e alta concorrência de aplicativos, vários nós são geralmente implantados; Para tarefas de tempo, se cada nó executar suas próprias tarefas de tempo, ele consome recursos do sistema, por um lado.
Por outro lado, algumas tarefas são executadas várias vezes, o que pode causar problemas lógicos de aplicativos; portanto, é necessário um sistema de agendamento distribuído para coordenar cada nó para executar tarefas de tempo.
A primavera integra quartzo
O quartzo é um sistema de agendamento de tarefas maduro. A primavera é compatível com o quartzo para facilitar o desenvolvimento. Vamos ver como integrá -lo:
1. Arquivo de dependência do MAVEN
<Dependences> <pendency> <voundId> org.springframework </frugid> <ArtifactId> Spring-core </ArtifactId> <Versão> 4.3.5.Release </sipers> </dependency> <pendence> <vSeriSs.s.Sers.Port-SERG-SUPROPT-SUPRUPROPT-SUPRUPROPR-SUPRIFRIFROPR-SUPRUPROPR-SUPROPR-SUPROPT <//Groupid> <TifactId> Spring-Context> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.3.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.5.RELEASE</version> </dependency> <pendency> <puperid> org.quartz-scheduler </groupiD> <TRORFACTID> quartz </artifactId> <versão> 2.2.3 </versão </dependency> <pendency> <puperid> mySQL </groupid> <tifactid> mysql-connector-Java </artistiFactid> <.10SQLECTIDECHETHELECTIDENCIDO </ARTIFACTID> <.1SSQLECTENCIDENTE </Groupid> </siSTIFACTID> </dependência </dependências>
Os principais são bibliotecas relacionadas à primavera, bibliotecas de quartzo e bibliotecas de driver MySQL. Nota: A programação distribuída requer o uso do banco de dados e o MySQL é selecionado aqui;
2. Configure o trabalho
Existem duas maneiras de configurar empregos, a saber: MethodInvingJobDetailFactoryBean e JobDetailFactoryBean
2.1MethodinvingJobDetailFactoryBean
Quando você deseja chamar um método de um feijão específico, a configuração específica é a seguinte:
<bean id = "FirstTask"> <propriedade name = "TargetObject" ref = "FirstService" /> <propriedade name = "TargetMethod" value = "Service" /> </SEA>
2.2JobDetailFactoryBean
Este método é mais flexível e pode definir os parâmetros de aprovação, como segue:
<bean id = "primeirotask"> <propriedade name = "jobclass" value = "zh.maven.squartz.task.firsttask"/> <propriedade name = "jobDatamap"> <pap> <entradas key = "primeiroservice" value-ref = "primeiroservice"/> </map> </bens> </bean> </bean>
A classe de tarefas definida pelo JobClass herda o quartzjobbean e implementa o método executivo -interno; JobDatamap é usado para passar dados para o trabalho
3. Configure os gatilhos usados para agendar
Dois tipos de gatilho também são fornecidos: SimpleTriggerFactoryBean e CrontriggerFactoryBean
Concentre -se no CrontriggerFactoryBean, esse tipo é mais flexível, da seguinte maneira:
<bean id = "FirstCRONTRIGGER"> <propriedade name = "jobDetail" ref = "FirstTask" /> <names name = "cronexpression" value = "0/5 * *? * *" /> </i bean>
JobDetail Especifica o trabalho configurado na Etapa 2, e a cronexpressão é configurada para executar o trabalho a cada 5 segundos;
4. Configure o SchedulerFactoryBean do agendador de quartzo
Existem também dois métodos: Memória Ramjobstore e métodos de banco de dados
4.1 Memória Ramjobstore
As informações relacionadas ao trabalho são armazenadas na memória, e cada nó armazena seu próprio, isola-se e é configurado da seguinte maneira:
<Bean> <propriedade name = "gatilhos"> <lista> <ref bean = "FirstCRONTRIGGER"/> </list> </Property> </i bean>
4.2 Método do banco de dados
As informações relevantes do trabalho são armazenadas no banco de dados. Todos os nós compartilham o banco de dados. Cada nó se comunica através do banco de dados para garantir que um trabalho seja executado apenas em um nó ao mesmo tempo.
Se um nó falhar, o trabalho será atribuído a outros nós para execução. A configuração específica é a seguinte:
<bean id = "DataSource" Destroy-Method = "Close"> <propriedade name = "driverclass" value = "com.mysql.jdbc.driver" /> <names name = "jdbcurl" value = "jdbc: mysql: // lochost: 3306 /quartz" /> <nome da names = ")" </bean> <Bean> <propriedade name = "DataSource" ref = "DataSource"/> <propriedade name = "configLocation" value = "classPath: quartz.properties"/> <names name = "gatilhos"> <list>
O DataSource é usado para configurar fontes de dados e informações relacionadas à tabela de dados. Você pode baixar o pacote GZ no site oficial. O arquivo SQL está sob o caminho: Docs/DBTables, que fornece o arquivo SQL para o banco de dados principal;
O arquivo quartz.properties configurado no ConfigLocation está no pacote org.quartz de quartz.jar, que fornece alguns dados padrão, como org.quartz.jobstore.class
org.quartz.jobstore.class: org.quartz.simpl.ramjobstore
Aqui você precisa copiar quartz.properties e fazer algumas modificações. As modificações específicas são as seguintes:
org.quartz.scheduler.instanceId: Autoorg.quartz.jobstore.class: org.quartz.impl.jdbcjobstore.jobstoretxorg.quartz.jobstore.isclustered: trueg.quartz.jobstore.clusterChckin:
5. Categorias relacionadas
classe pública FirstTask estende o quartzjobbean {private FirstService FirstService; @Override Protected void ExecuteInternal (contexto JobExecutionContext) lança JobExecutionException {FirstService.Service (); } public void setFirstService (FirstService FirstService) {this.firstService = FirstService; }}FirstTask herda o quartzjobbean, implementa o método executivo e chama de primeiro serviço
classe pública FirstService implementa serializável {private estático final serialversionuid = 1L; public void Service () {System.out.println (new SimpleDateFormat ("Yyymmdd hh: mm: ss"). tente {thread.sleep (2000); } catch (interruptedException e) {e.printStackTrace (); } System.out.println (new SimpleDateFormat ("yyymmdd hh: mm: ss"). Formato (new Date ()) + "--- final FirstService"); }}O FirstService precisa fornecer uma interface de serialização porque precisa ser salva no banco de dados;
public class App {public static void main (string [] args) {abstractApplicationContext context = new ClassPathXMLApplicationContext ("quartz.xml"); }}A classe principal é usada para carregar o arquivo de configuração de quartzo;
Programação distribuída de teste
1. Inicie o aplicativo duas vezes ao mesmo tempo e observe o log:
20180405 14:48:10 --- Start FirstService
20180405 14:48:12 ---- END FirstService
20180405 14:48:15 --- Start FirstService
20180405 14:48:17 ---- END FirstService
Entre eles, o A1 possui saída de log, mas A2 não; Quando A1 é interrompido, A2 possui saída de log;
2. Adicione novos trabalhos e crie novos: SecondTask e SecondService, respectivamente. Adicione arquivos de configuração relevantes ao mesmo tempo. Inicie o aplicativo duas vezes e observe o log:
O log A1 é o seguinte:
20180405 15:03:15 --- Start FirstService
20180405 15:03:15 --- Start SecondService
20180405 15:03:17 ---- END FirstService
20180405 15:03:17 --- Termine SecondService
20180405 15:03:20 --- Start FirstService
20180405 15:03:22 ---- END FirstService
20180405 15:03:25 --- Start FirstService
20180405 15:03:27 ---- END FirstService
O log A2 é o seguinte:
20180405 15:03:20 --- Start SecondService
20180405 15:03:22 --- Termine SecondService
20180405 15:03:25 --- Start SecondService
20180405 15:03:27 --- Termine SecondService
Pode -se descobrir que A1 e A2 têm tarefas de execução, mas a mesma tarefa será executada apenas em um nó ao mesmo tempo, e é possível ser atribuído a outros nós após a conclusão da execução;
3. Se o tempo de intervalo for menor que o tempo de execução da tarefa, por exemplo, aqui é alterado para dormir (6000)
O log A1 é o seguinte:
20180405 15:14:40 --- Start FirstService
20180405 15:14:45 --- Start FirstService
20180405 15:14:46 ---- END FirstService
20180405 15:14:50 --- Start FirstService
20180405 15:14:50 --- Start SecondService
20180405 15:14:51 --- final FirstService
O log A2 é o seguinte:
20180405 15:14:40 --- Start SecondService
20180405 15:14:45 --- Start SecondService
20180405 15:14:46 --- END SEGUNDO AVERIOR
20180405 15:14:51 --- END SEGUNDO SERVIÇO
O intervalo é de 5 segundos, enquanto a execução da tarefa leva 6 segundos. Observando o log, você pode descobrir que a tarefa ainda não terminou e uma nova tarefa começou. Essa situação pode causar problemas lógicos no aplicativo, que é realmente a questão de saber se a tarefa pode suportar serial;
4. A anotação @disallowconcurrentExecution garante a serialização das tarefas
Adicione a anotação @disallowconcurrentExecution no FirstTask e SecondTask, respectivamente, e os resultados do log são os seguintes:
O log A1 é o seguinte:
20180405 15:32:45 --- Start FirstService
20180405 15:32:51 --- final FirstService
20180405 15:32:51 --- Start FirstService
20180405 15:32:51 --- Start SecondService
20180405 15:32:57 ---- END FirstService
20180405 15:32:57 --- Termine SecondService
20180405 15:32:57 --- Start FirstService
20180405 15:32:57 --- Start SecondService
O log A2 é o seguinte:
20180405 15:32:45 --- Start SecondService
20180405 15:32:51 --- Termine SecondService
Observando os logs, você pode descobrir que a tarefa apenas iniciará uma nova tarefa após o final e perceberá a serialização da tarefa;
Resumir
Este artigo tem como objetivo ter uma compreensão intuitiva do agendamento distribuído da primavera+quartzo e resolver o problema através do uso real. Obviamente, pode haver muitas perguntas, como como está agendado, o que acontecerá se o banco de dados for pendurado, etc., e é necessário um entendimento mais profundo.
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.