"Make a wheel" -- cicada (lightweight WEB framework)

preface

As the saying goes, "don't make the wheel again." whether it is necessary is not the scope of this discussion.

The main purpose of creating this project is to improve yourself, see the gap with famous open source projects and learn excellent open source methods.

Now, let's focus on the core functions of the project.

I define it as a fast and lightweight WEB framework; There is not too much dependency, and the core jar package is only 30KB.

Only one line of code is required to start an HTTP service.

characteristic

Now let's talk about some important features.

The current version mainly implements basic request, response, user-defined parameters and interceptor functions.

Although it has few functions, it has everything.

In the future iteration process, we will gradually improve the function of the above figure. We welcome any good ideas https://github.com/crossoverJie/cicada/issues .

quick start

Let's see how to quickly start an HTTP service.

Just create a Maven project and introduce the core package.

<dependency>
    <groupId>top.crossoverjie.opensource</groupId>
    <artifactId>cicada-core</artifactId>
    <version>1.0.0</version>
</dependency>
copy

As shown in the figure above, configure another startup class.

public class MainStart {

    public static void main(String[] args) throws InterruptedException {
        CicadaServer.start(MainStart.class,"/cicada-example") ;
    }
}
copy

Configure business Action

Of course, we also need a place to implement business logic. cicada provides an interface, and only needs to implement this interface to realize the specific logic.

Create a business Action to implement top.crossverjie.cicada.server.Action Workaction interface.

@CicadaAction(value = "demoAction")
public class DemoAction implements WorkAction {


    private static final Logger LOGGER = LoggerBuilder.getLogger(DemoAction.class) ;

    private static AtomicLong index = new AtomicLong() ;

    @Override
    public WorkRes<DemoResVO> execute(Param paramMap) throws Exception {
        String name = paramMap.getString("name");
        Integer id = paramMap.getInteger("id");
        LOGGER.info("name=[{}],id=[{}]" , name,id);

        DemoResVO demoResVO = new DemoResVO() ;
        demoResVO.setIndex(index.incrementAndGet());
        WorkRes<DemoResVO> res = new WorkRes();
        res.setCode(StatusEnum.SUCCESS.getCode());
        res.setMessage(StatusEnum.SUCCESS.getMessage());
        res.setDataBody(demoResVO) ;
        return res;
    }

}
copy

At the same time, the @ CicadaAction annotation needs to be added to the custom class, and a value needs to be specified. This value is mainly used to find the business class when requesting routing.

This launches the application and accesses

http://127.0.0.1:7317/cicada-example/demoAction?name=12345&id=10

The business logic can be executed and the return of the server can be obtained.

At present, json response is supported by default, and template parsing will be added later.

Relevant logs will also be printed in the service.

Flexible parameter configuration

All request parameters here are encapsulated in Param, and request data can be obtained by using various API s.

Flexible: we can even request:

http://127.0.0.1:7317/cicada-example/demoAction?jsonData="info": {
    "age": 22,
    "name": "zhangsan"
  }
copy

In this way, data of any structure can be transferred as long as it is parsed during business processing.

custom interceptor

Interceptor is the basic function of a framework. It can be used to achieve common work such as logging and transaction submission.

For this purpose, cicada provides an interface: top.crossoverjie.cicada.server.intercept.CicadaInterceptor.

We only need to implement this interface to write the interception function:

@Interceptor(value = "executeTimeInterceptor")
public class ExecuteTimeInterceptor implements CicadaInterceptor {

    private static final Logger LOGGER = LoggerBuilder.getLogger(ExecuteTimeInterceptor.class);

    private Long start;

    private Long end;

    @Override
    public void before(Param param) {
        start = System.currentTimeMillis();
    }

    @Override
    public void after(Param param) {
        end = System.currentTimeMillis();

        LOGGER.info("cast [{}] times", end - start);
    }
}
copy

The demonstration here is to record the execution time of all action s.

At present, only action interceptors are implemented by default, and custom interceptors will be added later.

Intercept adapter

Although before/after methods are provided in the interceptor, not all methods need to be implemented.

Therefore, cicada provides an adapter:

top.crossoverjie.cicada.server.intercept.AbstractCicadaInterceptorAdapter

We need to inherit it to implement one of the methods as needed, as shown below:

@Interceptor(value = "loggerInterceptor")
public class LoggerInterceptorAbstract extends AbstractCicadaInterceptorAdapter {

    private static final Logger LOGGER = LoggerBuilder.getLogger(LoggerInterceptorAbstract.class) ;

    @Override
    public void before(Param param) {
        LOGGER.info("logger param=[{}]",param.toString());
    }

}
copy

performance testing

Since it is an HTTP service framework, the performance must be guaranteed.

Under the test conditions: 300 concurrent continuous pressure test for two rounds; 1G memory, single core CPU, 1Mbps. The pressure measurement with Jmeter is as follows:

The same server uses Tomcat to test the results.

Tomcat thread pool configuration:

<Executor name="tomcatThreadPool" namePrefix="consumer-exec-"
        maxThreads="510" minSpareThreads="10"/>
copy

What I'm requesting here is a doc directory of Tomcat. Although it seems that the performance of cicada is better than that of Tomcat.

However, the variables in the comparison process are not fully controlled. Tomcat returns HTML, while cicada only returns json. Of course, there are more problems.

But it still shows that the current performance of cicada is good.

summary

This article does not discuss the implementation principle of cicada too much. Those interested can look at the source code, which is relatively simple.

This content will be discussed in detail in subsequent updates.

At the same time, not surprisingly, cicada will continue to be updated and more practical functions will be added in the future.

I will even apply it to my production projects at an appropriate time, and I hope that more friends can participate in making this "wheel" better.

Project address: https://github.com/crossoverJie/cicada

Posted by dr.maju on Fri, 19 Aug 2022 18:40:11 +0930