Smart Discovery profile

An overview of the

Smart Discovery aims to enhance the SpringCloud service registration Discovery function and provide an intelligent micro-service governance framework for rule-based service registration Discovery and routing. Based on this flexible rule configuration, service scenarios such as service registration verification, group isolation, weight routing, host routing, custom label routing, dynamic parameter routing, gray scale publishing, and blacklist and whitelist can be implemented. At the same time, the framework ADAPTS to mainstream registries and configuration centers, and implements dynamic delivery of configuration rules based on the capabilities of the configuration center.

Developers only need to introduce the framework and do a little rule configuration to enjoy the functionality brought by the framework, no code intrusion; Developers can also implement custom business logic based on the extension mechanism provided by the framework. See the GitHub address for the framework source, and the usage documentation for more information.

features

  • Service registration: Verifies the registered services, such as host and service name, to ensure the validity, compliance, and security of access services.
  • Service discovery: Filters service metadata information (such as host, version information, and user-defined labels) and implements functions such as blacklist and whitelist, version-based, and label discovery and filtering.
  • Service routing: Supports routing of service metadata information (such as host, version information, and user-defined labels) based on conditional rules. At the same time, it supports conditional matching based on Request parameters (such as Header and Request parameters) to realize dynamic parameter routing, and supports SpEL expression.
  • Grayscale publishing: Based on the functions and features of service routing, grayscale publishing of services can be realized. For example, grayscale publishing can be realized through service version, rule switching of user-defined labels, or matching request parameters.
  • Group isolation: You can configure group information to isolate service groups.
  • Service-weight routing: supports service-weight routing, global weight conditions and interface-level fine-grained weight conditions, and supports blue-green advertisement scenarios through weight adjustment.
  • Dynamic configuration publishing: Supports RESTful apis and dynamic push from the configuration center to implement dynamic configuration publishing. By default, dynamic configuration takes precedence over local configuration and serves as the basis for grayscale publishing.
  • Support multiple configuration centers: support mainstream configuration centers, such as Nacos, Apollo, and consider the expansion of more configuration center access.
  • Multiple registries: Mainstream registries, such as Nacos, Eureka, and Consul, are supported.
  • Expansibility: The framework provides easy to use, perfect extension mechanism, developers can quickly customize business logic through the extension interface, such as custom conditional rule implementation, extended service registration filter, extended service routing filter, etc.
  • No code intrusion: developers only need to introduce this framework and do a little rule configuration to enjoy the features brought by this framework, no code intrusion, zero code.

Smart Discovery Quick Start

Github sample project

If you want to learn about Smart Discovery as quickly as possible, you can download a sample project on Github and run it.

Develop the first introductory example

The following example uses Nacos as the registry to implement version-based routing based on Smart Discovery. For example, a service consumer can only call a service provider of the same Version

Step 1: Run the Registry (Nacos)

See the official Nacos documentation

Step 2: Develop service providers

To better simulate the version-based routing effect, start the two service providers respectively, set the version numbers 1.0 and 2.0, and set port numbers 28081 and 28082 respectively. The following shows the sample service provider code for version 1.0 only.

This step is no different from normal SpringCloud development and is a quick guide for developers familiar with SpringCloud.

Step 2.1: Introduce Maven dependencies

This example uses NACOS as the registry and simply introduces the following additional POM

<dependency>
  <groupId>io.github.leonside</groupId>
  <artifactId>springleaf-cloud-smart-discovery-nacos</artifactId>
</dependency>
Copy the code

Note: Currently, all versions under the RELEASE branch have been released to the central repository (e.g. 1.0.1). In addition, if the versions of SpringBoot and SpringCloud referenced in the framework are inconsistent with those of the project, the project can define the version number by itself, for example:

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2020.02.</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.56.</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
      </dependencies>
</dependencyManagement>
Copy the code
Step 2.3: Write a simple example for SpringCloud
  • Write SpringBoot ServerBController

    @RestController
    public class ServerBController {
    
        @Value("${server.port}")
        private int serverPort;
    
        @RequestMapping(path = "/demo-b/echo", method = RequestMethod.GET)
        public String echo(@RequestParam("input") String input)throws UnknownHostException {
            System.out.println("serverB say: " + input);
            // Print the IP address and port of the service provider
            return "serverB[" + InetAddress.getLocalHost().getHostAddress() + ":" + serverPort  + "] say: "+ input; }}Copy the code
  • Write the SpringBoot Main function

    Here just add @ EnableSmartDiscoveryClient annotations, other just follow SpringCloud sample development.

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableSmartDiscoveryClient
    public class DemoApplicationB1 {
    
        public static void main(String[] args) {
        	// Set spring Profile Active, mainly used to simulate starting multiple service providers
    		System.setProperty("spring.profiles.active"."b1");
            //System.setProperty("spring.profiles.active", "b2");SpringApplication.run(DemoApplicationB1.class, args); }}Copy the code

    Note: To simulate multiple service providers, set the Spring Profile Active. The spring profile corresponding to DemoApplicationB1 is named application-b1.yml

  • Write the application-b1.yml configuration file

    Again, this configuration just needs to be developed normally as per the SpringCloud instructions.

    server:
      port: 28080
    spring:
      application:
        name: demo-b
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
            metadata:  # Configure more service metadata based on which Smart Discovery routes (version routes in this example)
              version: 1.0
     # region: dev
     # tag: tag1
    Copy the code
  • Start the DemoApplicationB1 service provider

Run DemoApplicationB1 main if the following message is displayed, the DemoApplicationB1 main function is successfully started

The 2021-10-05 16:35:12. 24632-663 the INFO [main] O.S.B.A.E.W eb. EndpointLinksResolver: Exposing 20 to the Exposing 20 endpoint(S) : Drive to the rim of the RING '/ Exposing to the Exposing 20 '-- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 28080 (HTTP) with the context path '16:35:12 2021-10-05. 24632-976 the INFO [main] O.S.C.A.N.R egistry. NacosServiceRegistry : nacos registry, Demo-b 192.168.75.1:28080 Register Finished 2021-10-05 16:35:12.979 INFO 24632 -- [main] c.s.c.d.controller.DemoApplicationB1 : Started DemoApplicationB1 in 10.461 seconds (JVM running for 12.625) 2021-10-05 16:35:14.052 INFO 24632 -- [n (2) - 10.11.1.14] O.A.C.C.C. [Tomcat] [localhost]. / / : Initializing Spring DispatcherServlet 'DispatcherServlet' 2021-10-05 16:35:14.052 INFO 24632 -- [N (2)-10.11.1.14] o.s.web.servlet.DispatcherServlet : Initializing Servlet' dispatcherServlet' 2021-10-05 16:35:14.084 INFO 24632 -- [N (2)-10.11.1.14] o.s.web.servlet.DispatcherServlet : Completed initialization in 32 msCopy the code

As above, continue to develop the DemoApplicationB2, application-b2.yml services and set the version number to 2.0 (omitted).

Step 3: Develop service consumers

Different from the service provider, SmartDiscovery service discovery rule configuration (based on version number service discovery) is added here, and other code development is no different from normal SpringCloud development.

Step 3.1: Introduce Maven dependencies

As above, just introduce the following additional POM. To simplify development, you can also write the service consumer code under the current project and skip this step.

<dependency>
  <groupId>io.github.leonside</groupId>
  <artifactId>springleaf-cloud-smart-discovery-nacos</artifactId>
</dependency>
Copy the code
Step 3.2: Write a simple example for SpringCloud
  • Write the SpringBoot Main function and Controller

    Just add @ EnableSmartDiscoveryClient annotations, other according to the normal SpringCloud development example, the development service consumer. For simplicity, the RestTemplate call is used here, but you can also use Feign.

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableSmartDiscoveryClient
    public class DemoApplicationA1 {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplicationA1.class, args);
        }
    
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate(a){
            return new RestTemplate();
        }
    
        @RestController
        @RequestMapping("demo-a")
        public class ServerAController {
    
            @Autowired
            private RestTemplate restTemplate;
    
            @RequestMapping(path = "/router/rule1", method = RequestMethod.GET)
            public String rule1(@RequestParam("input") String input){
    
                System.out.println("server a say: " + input);
                String echo = restTemplate.getForObject("http://demo-b/demo-b/echo? input=" + input, String.class);
                returnecho; }}}Copy the code
Step 3.3: Configure the discovery rule for the SmartDiscovery service
  • Configure the service discovery condition rule

    This example uses the local JSON configuration file to create a discovery-rule-discovery. JSON rule configuration file in the resources directory. The configuration is as follows:

    [{"serviceId": "demo-a"."force": true."priority": 0."conditions": " => version = $version"."enabled": true}]Copy the code

    The meaning of conditions rule: The version number of the service provider is equal to the version number of the service consumer. For specific rules, see the detailed explanation of Conditions rule.

  • Configure the Spring Application.yml configuration

    server:
      port: 18080
    spring:
      application:
        name: demo-a
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
            metadata:  # Configure more service metadata based on which Smart Discovery routes (version routes in this example)
              version: 1.0
     # region: dev
     # tag: tag1
    springleaf:
      smart:
        discovery:
          router:
            config:
              file:
                file: classpath:discovery-rule-discovery.json  # Configure file and specify the path of the configuration file. For more information, see section "Rule Configuration"
                
    logging:
      level:
        com:
          springleaf: debug   To verify the results, print smart Discovery logs
    Copy the code

    In addition, thanks to the Spring-configuration-metadata function of Spring, the configuration of frame-related parameters in the IDEA development environment can be induced by prompts, including parameter description, mandatory or not, and example information, as follows:

Step 3.4: Run and verify the results

Run DemoApplicationA1 main function, and call the http://localhost:18080/demo-a/router/rule1? Input =123, view the output log from the console of the service consumer:

The 17:23:33 2021-10-05. 32608-364 the DEBUG [erListUpdater - 0] F.S.L oadBalanceServerListConditionFilter: [Discovery filtering] List of Servers for demo-a obtained from Discovery client: [192.168.75.1:28080], service before Filtering is :[192.168.75.1:28081, 192.168.75.1:28080]Copy the code

At the same time, view the IP address and port information of the invoked service provider returned by the browser to check which provider is invoked.

After many invocations, we found that the Demo-B service provider with version V1 (port number 28080) was always called. Thus, Smart Discovery helped us realize the business scenario where the service consumer could only call the service provider with the same version. See usage documentation for more features

Write in the last

Smart Discovery was written in my spare time after work to summarize the appeal of using SpringCloud in my work project. It is inevitable that there will be some imperfections, which are welcome to point out. Also, if the Smart Discovery framework helps you, please give it a thumbs up (and a thumbs up on GitHub). That’s my biggest encouragement!