当前位置:网站首页>Using annotation + interceptor to implement asynchronous execution

Using annotation + interceptor to implement asynchronous execution

2020-11-08 20:18:00 osc_03803522

background

You may have used Spring Of @Async annotation , In this way, some methods can be converted into asynchronous execution , In order to improve the response efficiency of the request

But in the continuous evolution of service architecture , This way of dropping into the thread pool processing brings more and more obvious defects :

  • It's not good for monitoring
  • If it stops unexpectedly , All the unfinished tasks will be lost
  • When a node in the cluster has to handle a large number of asynchronous tasks , Can't share the pressure with other nodes in the cluster
  • If the project integrates the use of ThreadLocal Feature modules or third-party components , Attention should be paid to the problem of context loss

Ideas

Using message queuing as an implementation of asynchronous tasks , So we can :

  • A large number of mature MQ Middleware provides visual management platform , Monitoring is more convenient
  • You can use message queuing Header To save the context , Such as user information 、token etc.
  • Message queue Publishing - Subscription mode can maximize the business processing capacity of the cluster
  • It's easier to ensure the sequence of tasks
  • If a service node goes down , You can use the message to confirm 、 Message retrying and other mechanisms ensure the correctness of task execution

Realization

In order to ensure the decoupling of business code and Implementation Scheme , Be similar to @Aync programme , We also use annotations + Interceptor way for logic Injection

@Around("@annotation(org.springframework.amqp.rabbit.annotation.RabbitListener)")
	public Object cut(ProceedingJoinPoint pjp) throws Throwable {
		...
	}

The realization idea is similar with little difference , It is to read the queue statement in the annotation to confirm the release - Subscribe to the relationship between , Then replace the drop in thread pool with drop in message queue  

    private String resolveKey(Queue[] queues) {
		String s = this.beanFactory.resolveEmbeddedValue(queues[0].value());
		return (String) resolver.evaluate(s, evalContext);
	}
rabbitTemplate.convertAndSend(resolveKey(queues), args[0]);

Inject... Into the message queue Json converter , Convenient object transfer

    @Bean
    public Jackson2JsonMessageConverter producerJackson2MessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

If necessary , We can put the context of user information 、token Wait for the message to be written Header in

    private MessagePostProcessor beforePublishPostProcessor() {
        return message -> {
//          setting up context to message header
            return message;
        };
    }

Called asynchronously service Code :

@Service
@Slf4j
public class DemoService {
    
    @RabbitListener(queuesToDeclare = @Queue("mytestqueue"))
    public void checkSome(List<String> tagTuple) {
        log.warn("check here {}", tagTuple);
    }
}

call service Of controller:

@RestController
public class DemoController {
    
    @Autowired
    private DemoService demoService;
    
    @RequestMapping("check")
    public Integer checkSome() {
        ArrayList<String> tagTuple = new ArrayList<>();
        tagTuple.add("bar");
        tagTuple.add("foo");
        demoService.checkSome(tagTuple);
        return 0;
    }
}

Execute view effect

17:00:14.584TRACE[AbstractHandlerMapping.java:411]Mapped to org.smop.duplex.sample.DemoController#checkSome()
17:00:21.263WARN [DemoService.java:16]check here [bar, foo]

 

 

External file operations django Of models

# External files use django Of models, Need configuration django Environmental Science 
import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "singletablehw.settings")
    import django
    django.setup()

    from app01 import models
    import datetime
    obj_list = []
    for i in range(1,10):
        obj = models.Book(
            title=' Sunflower dictionary No %s type '%i,
            price=20 + i,
            pub_date='198%s-11-11 00:00:00'%i,
            # pub_date=datetime.datetime.now(),

            publish= ' Boss Wu Publishing House ' if i < 5 else ' Taibai Publishing House ',

        )
        obj_list.append(obj)

    models.Book.objects.bulk_create(obj_list)

url Alias reverse resolution

    # Add books 
    url(r'^add_book/', views.add_book,name='abook'), #name='abook'   Alias 

    #  Delete books 
    url(r'^delete_book/(\d+)/', views.delele_book,name='delete_book'),

 View :
    from django.urls import reverse
    reverse(' Alias ')  reverse('abook') -- /add_book/  # No parameters 
    print(reverse('delete_book',args=(71,))) #/delete_book/71/  Parameterized 

 Templates :
    {% url 'abook' %}   No parameters 
    {% url 'delete_book' book.id %}   Parametric 

 

 

 

版权声明
本文为[osc_03803522]所创,转载请带上原文链接,感谢