非标准程序猿 / 🧑‍💻爱编码 / 📹爱摄影 / ⛰️爱徒步 / ❤️ 更爱女朋友 新晋:米家好物推荐官 🎉🎉🎉 关注我哦,让我们一起变得更强~

How to design a business concurrent framework from 0 to 1 in the Phoenix framework and how to organize the design of a framework.

The previous article mainly discussed the problems encountered before designing the Phoenix framework and the ideas for designing the framework in the article 《Phoenix Framework: Designing a Business Concurrency Framework from 0 to 1 for the Xiaomi Mall Product Site》. This article mainly discusses how to design the framework.

PhoenixFramework is a framework that automatically constructs directed graphs, builds concurrent groups according to depth, and performs concurrent invocation of results.

Both the static and dynamic interfaces of the product site business need to call a large number of backend services to obtain data for business orchestration, and there are dependencies between each concurrent call. By using concurrent group design to break down dependencies and control concurrent calls, and using a unified Transfer layer for BO to DTO conversion, developers only need to define the Task and Transfer code logic for each call event and directly return the business data.

Layered Design


  • PhoenixFramework: The name of the Phoenix (Phoenix) framework for this business concurrency framework.
  • Task: Defines a call in business concurrency, which can be an HTTP, DUBBO, or Redis retrieval, or a MySQL read operation.
  • Transfer: In business definition, it is the conversion logic of a sub-business module that converts BO data into DTO data.

Task and Trans Annotations#

How to Define a Task#

At the beginning of the framework design, we had two internal options. One was to implement Task by inheriting an abstract class. Task was defined by implementing the PhoenixTask class through inheritance. The other option was to use annotations to define each Task as a Task with strong constraints, and to define detailed description information in the annotations, providing developers with a clear design idea.

After internal discussions, we chose the excellent language feature of Java, which is to declare and define Task using annotations. This definition makes the code concise and clear, and is also conducive to collecting our definitions through Spring Bean collection tools.

 * PhoenixTask 
 * Task annotation  
 * @author debuginn
public @interface PhoenixTask {  
    String taskName();                     // Task name  
    String[] beforeTaskName() default {};  // Preceding tasks  
    String[] filterPlatform() default {};  // Filter channels, blacklist  
    String[] taskBoName();                 // BO data generated by the task, used to check conflicts  

The PhoenixTask annotation is defined very simply:

  • taskName is used to identify the task name and is enforced by enumeration for unique naming.
  • beforeTaskName is the preceding task. As mentioned earlier, each task is an event. Distinguishing the preceding task requires waiting for the return of the result during concurrent invocation, and then using it as the preceding parameter for this Task call.
  • filterPlatform is the filter channel, which is the functionality of the blacklist. If the request channel is declared as a blacklist in Task, it will be automatically blocked during concurrent execution.
  • taskBoName is the data that the task is converted into BO. It is used to obtain data through interface calls or middleware and convert it into data used by the Transfer layer. Data parameter verification is performed at the framework layer.

How to Define a Trans#

Trans is short for Transfer. Just like Task design, it is also defined using annotations:

 * PhoenixTrans 
 * Business orchestration annotation  
 * @author debuginn 
public @interface PhoenixTrans {  
    String transName();             // Business orchestration block name  
    String apiName();               // Execute using concurrent API  
    String[] tasks() default {};    // Dependent task tasks  

The PhoenixTrans annotation is defined in a similarly simple way:

  • transName is used to identify the name of the business orchestration block.
  • apiName is used to distinguish which concurrent API this Transfer business orchestration belongs to.
  • tasks defines the dependent Task tasks. A business orchestration may use BO data returned by n tasks for orchestration.

You may be confused here. Why is apiName not defined in Task but in Transfer? This is because in the design, in order for Task to be shared by n concurrent APIs, apiName is defined in Transfer. Then, by defining the dependent Task through tasks, you can infer which API the Task is currently used by.

How to Collect Task and Trans#

After customizing the PhoenixTask and PhoenixTrans annotations, collect the defined annotations by declaring an AnnotationProcessor that inherits BeanPostProcessor.

  • First, collect the corresponding Task and Trans based on the annotation class.
  • Divide different APIs based on different Trans and collect the Task dependencies used by different APIs.
  • Use the Task used by Trans to filter dependencies.
  • Group the Tasks based on their mutual dependencies.

This completes the design of the framework's layering and automatic construction. The main consideration in designing the framework is how to abstract the modules used in actual business into design, and at the same time, consider the scalability and strong constraints of the framework.


This article mainly explains how I abstract the relationship between business and calls into Trans and Task. Next, I will discuss a series of articles on the core design of the concurrent thread pool, configuration thinking, monitoring design, and automatic construction algorithm of the concurrent framework.

If you are interested, I recommend following the official account or subscribing to this site. Welcome to interact and communicate. Let's become stronger together~


Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.