How to debug so many Spring Cloud microservice interfaces?

Posted by martincrumlish on Mon, 06 Jan 2020 19:09:29 +0100

Preface

Today, let's talk about the debugging and management of service interface under Spring Cloud microservice! We know that under the microservice architecture, the software system will be divided into many independent running services, and these services need to communicate with each other, so they need to define a variety of service interfaces. Specifically, in the microservice mode based on Spring Cloud, each microservice will define multiple interfaces that need to be published externally based on Spring MVC Controller.

According to the different definitions of each microservice function boundary, some microservices will provide the interface related to specific business, such as payment interface, account interface, etc.; while some microservices will provide some service interfaces of public nature, such as SMS interface, unified authentication interface, etc. These microservices are often developed and maintained by many different teams. Under the traditional mode, the definition of service interface often requires the service provider to provide good and readable interface documents to facilitate the docking and testing. In fact, with the passage of time and the iterative updating of personnel, in many cases, these early interface documents are often very fast It will be out of date because of no maintenance. Even if it is not out of date, such a way in microservice mode will make developers mad because there are too many service interface documents!

Is there a more convenient way to automatically generate documents that are highly consistent with the service interface while developing the interface? The answer is yes. Next, let's talk about how to make the interface management of microservices easier!

Introduction to interface management mode

In fact, there are many open source projects on the market that provide such support! For example, Swagger, ApiDoc, RAP, DOCLever, CrapApi, etc. all of these projects provide the management function of Api online documents. Which is more suitable in the Spring Cloud system? Let's compare the advantages and disadvantages of these projects.

Swagger

Swagger is a tool based on YAML and JSON for online document generation and automatic code generation. Its advantages are as follows:

1) , it can be directly embedded in the Spring Boot project, and the interface document can be generated automatically by writing comments during development, so as to achieve a high degree of consistency between the code and the document;
2) , can analyze the structure of the interface, and can also verify the correctness of the interface by initiating a request;
3) , it provides a solution to separate the front and back end of various programming languages, and supports exporting the server or client code of various languages according to the defined interface;
4) , it also includes Swagger Editor, which is the editor of Swagger API in yaml language, and supports the export of interface files in yaml and json formats;
5) , including the Swagger UI, which can display the interface documents edited by Swagger Editor in the form of html;
6) Free and open source, supporting internationalization, rich ecology and active community;

Its disadvantages are:

1) . it is intrusive to the code;
2) , the Swagger interface documents of different projects are separated and need to be found in different places;
3) . the interface documents presented by Swagger UI are lack of classification and poor in use experience;
4) . the interface documents of different projects do not have permission management and lack Mock;

ApiDoc

ApiDoc is a lightweight online document generation tool similar to Swagger. Its disadvantages are similar to Swagger, and its interface management, automatic testing and other functions are relatively weak, and its community and ecological internationalization are not as good as Swagger.

RAP

RAP is a visual interface management tool, which can analyze the interface structure, dynamically generate simulation data, verify the correctness of the real interface, around the interface definition, through a series of automation tools to improve the cooperation efficiency under the micro service mode.

Its advantages are as follows:

1) Support project management, team management and document version management;
2) . support Mock test data;
3) , produced by alidachang and practiced in Alibaba;
4) . support interface retrieval;
5) . analyze the interface structure and initiate a request to verify the correctness of the interface;
6) , free and open source

The disadvantages are as follows:

1) , documents and interfaces are separated, which is easy to cause inconsistency;
2) . each interface needs to be edited manually;
3) . the backend is written in nodejs, which is inconsistent with the Java based Spring Cloud technology stack;

DOCLever

Doclevel is also a free and open-source interface management tool, with the following advantages:

1) Support project management, team management and rich documentation tools;
2) Support rich Mock test data;
3) . there are also abundant user cases: Didi, meituan, 58 intra city, intra city tourism, etc;
4) . support interface retrieval;
5) , it can analyze the structure of the interface, launch a request to verify the correctness of the interface, and the parameters are also very rich;
6) Support automatic testing in complex scenarios, such as obtaining verification code, login, order list, and even specific order details;

The disadvantages are as follows:

1) , documents and interfaces are separated, which is easy to cause inconsistency;
2) . each interface needs to be edited manually;
3) , the backend is also written in nodejs, which is inconsistent with the Java technology stack of Spring Cloud;

CrapApi

The advantages are as follows:

1) Support project management, team management and document version management;
2) . support Mock test data;
3) . support interface retrieval;
4) , can analyze the interface structure and initiate a request to verify the correctness of the interface;
5) . support interface monitoring, set alarm rules, and notify the service principal in time when the interface is unavailable;
6) , the back end is developed based on Java, matching with Spring Cloud technology stack Java;
7) Free and open source;

Disadvantages:

1) , documents and interfaces are separated, which is easy to cause inconsistency;
2) . each interface needs to be edited manually;
3) . there are few use cases and incomplete functions, which may lead to many pits;

Spring Cloud integration Swagger

Through the analysis of the above open source projects, all the other projects except Swagger adopt the method of document and code separation. Although this will reduce the invasion to the code, it will also cause the inconsistency between the document and the code. Therefore, in the microservice project based on Spring Cloud, we choose Swagger as the microservice interface management tool.

So how can Spring Cloud microservices based on Spring Boot integrate Swagger?

1) Introduce Maven dependency in Spring Boot microservice project:

 <dependency>
     <groupId>io.springfox</groupId>
     <artifactId>springfox-swagger2</artifactId>
     <version>2.2.2</version>
 </dependency>
 <dependency>
     <groupId>io.springfox</groupId>
     <artifactId>springfox-swagger-ui</artifactId>
     <version>2.2.2</version>
 </dependency>

2) , create Swagger2 configuration class:

@Configuration
@EnableSwagger2
@Profile("!production")
public class SwaggerConfiguration {
    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("Api")
                .select()
                .apis(withClassAnnotation(RestController.class))
                .build()
                .globalOperationParameters(commonParameters())
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Api")
                .version("1.0.0-SNAPSHOT")
                .build();
    }

    private List<Parameter> commonParameters() {
        List<Parameter> parameters = Lists.newArrayList();
        parameters.add(new ParameterBuilder()
                .name("war")
                .description("backdoor Bypass authentication in test environment")
                .modelRef(new ModelRef("string"))
                .parameterType("query")
                .required(false)
                .defaultValue("war123")
                .build());
        parameters.add(new ParameterBuilder()
                .name("uid")
                .description("backdoor Set user ID")
                .modelRef(new ModelRef("string"))
                .parameterType("query")
                .required(false)
                .defaultValue("1000053")
                .build());
        parameters.add(new ParameterBuilder()
                .name("Authorization")
                .description("In the production environment, the users to be transferred are currently Token")
                .modelRef(new ModelRef("string"))
                .parameterType("header")
                .required(false)
                .defaultValue("Bearer XXXXX")
                .build());
        return parameters;
    }
}

In the above configuration class, we can use @ Profile("!production") annotation to specify the effective environment. For example, here we set the environment to take effect except for the production environment.

3) , add document content

After the above configuration is completed, the document content can be produced. However, such a document is mainly aimed at the request itself. The main source of description is function naming, which is not friendly to multiple users. In order to make the document easier to read and understand, we can add some descriptions through Swagger annotation. These notes mainly include:

@Api: used on a class to illustrate its function. Br / > @ apioperation: Annotation to add method description to API.
@Apiimplicit params: used to include a set of parameter descriptions on a method.
Br / > @ apiimplicitparam: used to annotate method input parameters.
@ApiResponses: used to represent a set of responses.
Br / > @ apiresponse: used in @ ApiResponses to express a wrong response information.
@ApiModel: describes the information of a Model (usually used when the request parameter cannot be described with @ ApiImplicitParam annotation).

Next, we will demonstrate the following through an actual microservice interface definition case:

@Api(value = "External interface of user layer of operation and maintenance end system", description = "For assembly, directly facing operation and maintenance App End related services")
@RestController
@Slf4j
public class OperationUserController {

    @Autowired
    OperationUserService operationUserServiceImpl;

    @ApiOperation(value = "Operation and maintenance end user registration", httpMethod = "POST")
    @RequestMapping(value = "/userRegister", method = RequestMethod.POST)
    public APIResponse sysUserRegister(@RequestParam(value = "mobileNo") String mobileNo,
            @RequestParam(value = "email") String email,
            @RequestParam(value = "nickName", required = false) String nickName,
            @RequestParam(value = "idName") String idName, @RequestParam(value = "idType") String idType,
            @RequestParam(value = "idNo") String idNo, @RequestParam(value = "gender") String gender,
            @RequestParam(value = "password") String password, @RequestParam(value = "verifyCode") String verifyCode,
            @RequestParam(value = "creator") String creator) {
        UserRegisterReqVo userRegisterReqVo = UserRegisterReqVo.builder().mobileNo(mobileNo).email(email)
                .nickName(nickName).idName(idName).idType(idType).idNo(idNo).gender(gender).passwd(password)
                .passcode(verifyCode).creator(creator).build();
        UserRegisterResVo userRegisterResVo;
        try {
            userRegisterResVo = operationUserServiceImpl.userRegister(userRegisterReqVo);
        } catch (BizException e) {
            log.error(e.toString() + "_" + e.getMessage(), e);
            return APIResponse.error(e.getCode(), e.getMessage());
        } catch (Exception e) {
            log.error(e.toString() + "_" + e.getMessage(), e);
            return APIResponse
                    .error(ApiResultStatus.INTERNAL_SERVER_ERROR.getApiResultStatus(),
                            ApiResultStatus.INTERNAL_SERVER_ERROR.getMessageResourceName());
        }
        return APIResponse
                .success(ApiResultStatus.SUCCESS.getApiResultStatus(), ApiResultStatus.SUCCESS.getMessageResourceName(),
                        userRegisterResVo);
    }
}

Above, we defined a user registration interface under the microservice. At this time, start the microservice, and then input the IP + port + / swagger ui.html of the microservice to see the swagger UI, as follows:

Through swagger UI, we can test the interface in the way of verification. At the same time, because the interface fields are described and temporary in the UI, and are completely consistent with the actual code, we can dock based on these interface definitions when docking!

Topics: Java Spring JSON Programming