Application of basic components in microservice Engineering

Posted by rachwilbraham on Tue, 08 Mar 2022 01:57:52 +0100

1, Gateway service

1. Gateway mode

As the outermost service of the architecture, the gateway is used to uniformly intercept requests from various ports, identify the legitimacy of requests, intercept abnormal actions, provide routing and load capacity, and protect business services; This strategy is similar to the appearance mode.

The logic of Gateway Services and facade services is similar in part. The interception of Gateway Services focuses on dealing with general policies and routing loads, while different facade aggregation services focus on scene classification, such as several common facade services:

  • Facade: open port requests of service products, such as Web, App, applet, etc;
  • Admin: usually serves the internal management system, such as Crm, BI report, console, etc;
  • Third: aggregate third-party docking services, such as SMS, risk control, action embedding point, etc;

There will also be specific interception strategies in different Facade services. If Facade, Admin, Third and other verifications are integrated into the gateway, it will obviously increase the burden of Gateway Services and is not conducive to the stability of the architecture.

2. Gateway component

If the microservice architecture comes into contact earlier, Zuul components are often used in the Gateway in the initial stage, and then the Gateway components are released by spring cloud, which is a commonly used model at present.

  • Request interception: as the open entrance of API requests, the gateway is the basic ability to complete the interception, identification and verification of requests;
  • Customization strategy: in addition to conventional identity recognition, the corresponding interception logic is designed according to the service scenario to intercept abnormal requests as much as possible;
  • Service Routing: requests are forwarded to specific business services after being intercepted. There are two core action routes and loads;

As a commonly used selection component in microservice architecture, the use mode of Gateway gateway and the docking process and mode with other components are analyzed in detail from the use details.

As the registration and configuration center of microservices, Nacos has become a commonly used component at present, and Nacos also provides an integration case of Gateway components. First, register the Gateway service with Nacos:

spring:
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
      discovery:
        server-addr: 127.0.0.1:8848

Nacos manages the gateway service registration and related configuration files. In the project, it usually shares a set of MySQL database with Nacos to manage the service routing data of the gateway. It is a common solution at present.

3. Gateway interception

GlobalFilter: the global filter in the gateway, which intercepts all requests passing through the gateway and determines whether the request needs to be executed through the corresponding verification strategy:

@Order(-1)
@Component
public class GatewayFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        return chain.filter(exchange);
    }
}

Generally, some necessary common interception will be performed in the gateway, such as IP black-and-white list and Token identity Token. Obtain the corresponding parameters in the request and execute the verification method of relevant services.

4. Dynamic routing

4.1 route definition

In the implementation of service routing, there are complex logic and strategies to adapt to various scenarios; For how to define the concept of routing, you can refer to the source code RouteDefinition object of the Gateway component. The structure involves several core attributes: routing, assertion, filtering and metadata:

  • Route: consists of ID, forwarding Uri, assertion, filtering and metadata;
  • Predicate assertion: judge whether the request and route match;
  • Filter: you can modify request actions, such as parameters;
  • Metadata: load the meta information of the routing service;
@Validated
public class RouteDefinition {
    private String id;
    @NotNull
    private URI uri;
    @NotEmpty
    @Valid
    private List<PredicateDefinition> predicates = new ArrayList<>();
    @Valid
    private List<FilterDefinition> filters = new ArrayList<>();
    private Map<String, Object> metadata = new HashMap<>();
}

These routes are usually placed in the config of the nacos library_ In the route data table, you can manage the corresponding table data around the structure of the above routing objects:

There are also different configurations for the forwarding target uri. Here, the mode of lb: / / service registration name is selected, that is, the request load is distributed to the service node corresponding to the route. For a supplementary explanation, the Ribbon load algorithm is used inside the Nacos component. You can refer to the relevant documents.

4.2 manage routing

There are two core interfaces for routing management: Locator loading and Writer addition and deletion, and it also provides an aggregated Repository interface:

public interface RouteDefinitionLocator {
    // Get route list
    Flux<RouteDefinition> getRouteDefinitions();
}
public interface RouteDefinitionWriter {
    // Save route
    Mono<Void> save(Mono<RouteDefinition> route);
    // Delete route
    Mono<Void> delete(Mono<String> routeId);
}
public interface RouteDefinitionRepository extends RouteDefinitionLocator, RouteDefinitionWriter{}

In this way, the above aggregation interface is realized by defining the routing management component to complete the process of loading routing data from the data table to the application:

@Component
public class RouteFactory implements RouteDefinitionRepository {
    @Resource
    private RouteService routeService ;

    // Load all routes
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        return Flux.fromIterable(routeService.getRouteDefinitions());
    }
}

RouteService is the service class of route management, which manages configuration data and the conversion between entity object and route definition object:

@Service
public class RouteServiceImpl implements RouteService {
    // The database routing entity is converted into the definition object of gateway routing
    private RouteDefinition buildRoute (ConfigRoute configRoute){
        RouteDefinition routeDefinition = new RouteDefinition () ;
        // Basics
        routeDefinition.setId(configRoute.getRouteId());
        routeDefinition.setOrder(configRoute.getOrders());
        routeDefinition.setUri(URI.create(configRoute.getUri()));
        // Assert
        routeDefinition.setPredicates(JSONUtil.parseArray(configRoute.getPredicates()).toList(PredicateDefinition.class));
        // filter
        routeDefinition.setFilters(JSONUtil.parseArray(configRoute.getFilters()).toList(FilterDefinition.class));
        return routeDefinition ;
    }
}

Through the above process, the routing information can be persisted and stored in the database. If there are few service nodes, it can also be directly managed in the configuration file of nacos.

4.3 matching mode

Predicate assertion is actually the setting of matching rules. Referring to the relevant source code of predicteddefinition, we can see that there are Host, Path, Time and other modes. From the above data, we can see that this paper adopts Path matching,

Because the path matching method will splice the / service name at the beginning of the uri, set StripPrefix to remove the route ID when configuring the filtering rule.

After the request enters the gateway, it first enters the global interceptor to execute the verification strategy. After passing the verification, it matches the service of the relevant route. After the matching is successful, it carries out the filtering operation, and finally forwards the request to the corresponding service. This is the core process to be executed by the request in the gateway.

2, Registration and configuration

In the whole microservice system, Nacos provides two core capabilities: service registration and configuration management. Usually, only the core bootstrap configuration file is retained in the code engineering, which can greatly simplify the configuration in the engineering and improve the security of relevant data.

1. Service registration

Nacos supports DNS based and RPC based service discovery, and provides real-time health inspection of services to prevent sending requests to unhealthy hosts or service instances:

In the service registration list, you can view the registration information, the number of instances, the number of health, etc., and you can delete the registered service; In the details, you can view the specific instance information, and dynamically go online and offline and edit the relevant configuration of the service instance.

2. Configuration file

Namespace namespace management is usually adopted to separate the registration and configuration of different services. Tenant can be found in the nacos library_ Info, there are generally the following categories:

This is the most common namespace. The gateway gateway is relatively independent, the configuration of seat transaction is relatively complex, and the service business service has a large number of public configurations. The following strategies are usually adopted:

  • application.yml: public configuration of all services, such as mybatis;
  • dev||pro.yml: environment isolation configuration. Different middleware addresses are set in different environments;
  • serve.yml: personalized configuration of services, such as connected libraries, parameters, etc;
spring:
  application:
    name: facade
  profiles:
    active: dev,facade
  cloud:
    nacos:
      config:
        prefix: application
        file-extension: yml
        server-addr: 127.0.0.1:8848
      discovery:
        server-addr: 127.0.0.1:8848

The service will identify and load the corresponding configuration file through the above profiles parameter. In this management mode, the difference of the environment is only in dev||pro It can be maintained in the YML configuration file, and other configurations will be relatively stable.

3, Inter service call

1. Feign component

Feign component is a declarative and templated HTTP client, which can make the call between services easier and elegant. Generally, the feign interface provided by the service is managed in an independent code package, which is convenient for other services to rely on:

/**
 * Specify service name
 */
@FeignClient(name = "account")
@Component
public interface FeignService {
    /**
     * API interface of service
     */
    @RequestMapping(value = "/user/profile/{paramId}", method = RequestMethod.GET)
    Rep<Entity> getById(@PathVariable("paramId") String paramId);
}
public class Rep<T> {
    // Response coding
    private int code;
    // semantic description 
    private String msg;
    // Return data
    private T data;
}

Usually, the response format of Feign interface is packaged to realize the unified management of back parameter structure, which is conducive to the identification of the caller. Here, it involves the processing of generic data.

2. Response decoding

By inheriting the ResponseEntityDecoder class, the user-defined Feign interface response data processing is realized, such as return parameter style, data conversion, etc

/**
 * Configure decoding
 */
@Configuration
public class FeignConfig {
    @Bean
    @Primary
    public Decoder feignDecoder(ObjectFactory<HttpMessageConverters> feignHttpConverter) {
        return new OptionalDecoder(
                new FeignDecode(new SpringDecoder(feignHttpConverter)));
    }
}
/**
 * Define decoding
 */
public class FeignDecode extends ResponseEntityDecoder {
    public FeignDecode(Decoder decoder) {
        super(decoder);
    }
    @Override
    public Object decode(Response response, Type type) {
        if (!type.getTypeName().startsWith(Rep.class.getName())) {
            throw new RuntimeException("Abnormal response format");
        }
        try {
            return super.decode(response, type);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
    }
}

3. Request resolution

The communication request between services can be easily realized by annotation. You can understand the encapsulation logic by referring to the source code of Feign component. Its essence is to convert the interface call into HTTP request:

  • FeignClientBuilder: directly build the client requested by Feign without annotation. This class is helpful to understand the annotation principle of @ FeignClient;
  • Feignclientsregister: the @ FeignClient annotation method is adopted in the project. The API describes the parsing method of annotation and the construction logic of service request;

The process of selecting the official components and services of fecos is a very simple entry point. It is also necessary to use the logic of the official components and services of fecos as the core of the project. It is also a very complex entry point to make the selection of the official components and services of fecos as the entry point of this article.

4, Reference source code

Application warehouse:
https://gitee.com/cicadasmile/butte-flyer-parent

Component encapsulation:
https://gitee.com/cicadasmile/butte-frame-parent

Topics: Distribution Microservices Nacos gateway feign