In the previousSpring Cloud(03) – Build payment module and consumer order module and engineering refactoringWe built a simple Rest service with RestFul apis, service providers, and service consumers. Let’s implement how to deploy the Eureka registry!

Introduction to Spring Cloud Eureka

  • Eureka is a part of The Netflix Microservices suite, which is repackaged based on Netflix Eureka and is mainly responsible for realizing the service governance functions in the microservices architecture. Eureka is an open source framework in Netflix, so it can take advantage of other components in Netfilix, such as Zull, etc.

  • Eureka is a REST-based service and provides a Java-based client component, which makes it easy to register services in Eureka for unified management.

  • Service governance is an essential part of microservices architecture, and Ali’s open source Dubbo framework (Dubbo also has several registries, such as Zookeeper, Redis, etc., but the most commonly used is Zookeeper) is aimed at service governance. Service governance must have a registry, in addition to Eureka as the registry, we can also use Consul, Etcd, Zookeeper, and so on as the service registry.

Eureka consists of two components: Eureka Server and Eureka Client.

  • ==Eureka Server== Provides service registration services. After nodes are started, they register with the EurekaServer. In this way, the service registry of the EurekaServer stores information about all available service nodes.

  • The Eureka Client is a Java Client designed to simplify interactions with the Eureka Server. The Client is also a built-in load balancer that uses the round-robin load algorithm. Eureka client can be divided into ==Service Provider== and ==Service Consumer==.

    • Service Provider Registers its services with Eureka so that Service consumers can find them
  • A Service Consumer that obtains a list of registered services from Eureka so that it can consume services

  • After the application is started, the Eureka Client connects to the Eureka Server and maintains the heartbeat connection. The default interval is 30 seconds. If the Eureka Server does not receive the heartbeat of a node within multiple heartbeat cycles, Eureka Server will remove this service node from the service registry (default: 90 seconds).

  • Eureka servers synchronize data through replication. Eureka also provides a client cache mechanism. Even if all Eureka servers fail, clients can still use the cache information to consume apis for other services. In summary, Eureka ensures high availability, flexibility, and scalability through mechanisms such as heartbeat check and client caching.

    The above excerpt from Baidu Encyclopedia

2. Comparison between Eureka and Zookeeper

In the field of distributed systems, there is a famous CAP theorem:

  • C:Consistency.
  • A: Availability.
  • P:Partition tolerance. Similar to multi-room deployment, ensuring service stability.

None of these three features can be met simultaneously in any distributed system, but at most two can be met simultaneously.

The difference between Eureka and Zookeeper:

  • Zookeeper is CP, a distributed collaborative service that emphasizes consistency. Consistent data results can be obtained for each request to ZooKeeper, but there is no guarantee of service availability for each access. For example, when the request arrives, Zookeer is electing the leader and cannot provide services, that is, the availability of A is not satisfied.

  • Euere is AP, a highly available and scalable Service discovery Service that emphasizes availability. Compared to Zookeeper, the returned data may not be consistent, but the data is returned and the service is available. That is, the C consistency is not satisfied.

3. Deploy the Eureka Server

1. Create a submodule cloud-Eureka-server7001

2. Import dependencies

  <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <dependency>
            <groupId>com.cheng.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

              <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
Copy the code

3. Write configuration files

server:
  port: 7001

eureka:
  instance:
    hostname: localhost  # Eureka Server instance name
  client:
    register-with-eureka: false  # Since the application is a registry, set it to false to not register itself with the registry
    fetch-registry: false # fetch- Registry is false, which means that I am a registry and my responsibility is to maintain service instances, not to retrieve services
    service-url:
    Set the address to which the Eureka Server will interact. Service registration and queries will depend on this address
      defaultZone: http//${eureka.instance.hostname}:${server.port}/eureka/

Copy the code

4, write the main boot class

@SpringBootApplication
@EnableEurekaServer 
public class EurekaMain7001 {
    public static void main(String[] args) { SpringApplication.run(EurekaMain7001.class,args); }}Copy the code

5, test,

To start the program, access the request http://localhost:7001/ to test:

Deployment succeeded!

4. Pay for microservice 8001 and register with Eureka Server

==Eureka Client Cloud-provider-Payment8001 will be registered with EurekaServer as a service provider ==

1. Add dependencies to the cloud-provider-Payment8001 module of the service provider

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Copy the code

2. Add the eureka configuration to the service provider configuration file

# eureka configuration
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
    register-with-eureka: true Register yourself to Eureka Server
    Whether to fetch existing registration information from eurekaServer. Default to true. If the euREKA cluster is set to true, the EuREKA cluster can work with the Ribbon to use load balancing
    fetchregistry: true
  instance:
    instance-id: springcloud-provider-dept-8001   Custom status information
Copy the code

3. Annotate the main boot class @enableeurekaclient

4, test,

  1. Start Eureka server Server7001,
  2. Restart the service provider cloud-provider-Payment8001 module

Access request http://localhost:7001/ to test: to see if the service is registered with the registry,

Registration successful!

5. Order micro-service 80 Register with Eureka Server

==Eureka Client cloud-consumer-Order80 will register with EurekaServer as service consumer ==

1. Add dependencies in the service consumer cloud-consumer-Order80 module

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Copy the code

Add eureka and Spring to service provider configuration file (note space in configuration file)

spring:
  application:
    name: cloud-order-service

# eureka configuration
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
    register-with-eureka: true Register yourself to Eureka Server
    Whether to fetch existing registration information from eurekaServer. Default to true. If the euREKA cluster is set to true, the EuREKA cluster can work with the Ribbon to use load balancing
    fetchregistry: true
Copy the code

3. Annotate the main boot class @enableeurekaclient

4, test,

  1. Start Eureka server Server7001,
  2. Start the service provider cloud-provider-Payment8001 module
  3. Start the service consumer cloud-consumer-Order80 module

Access request http://localhost:7001/ for testing: both microservices are registered

6. Set up Eureka cluster

6.1 Eureka Cluster Principles

Register with each other, watch out for each other, expose each other

Eureka registry cluster implements load balancing + fault tolerance

6.2 Setting up the Eureka cluster environment

1. Create cloud-Eureka-Server7002 module by referring to cloud-Eureka-Server7001 module

  1. Copy the POM dependency of 7001 to 7002
  2. Copy the configuration file of 7001 to 7002. Note that the port number of Eureka Server7002 is 7002
  3. Copy the primary boot class and directory structure of 7001 to 7002. The primary boot class of 7002 is EurekaMain7002

2. Modify the mapping configuration

  1. Locate the hosts file in C:\Windows\System32\drivers\etc,

  2. Add a mapping to the hosts file:

    127.0.0.1  eureka7001.com
    127.0.0.1  eureka7002.com
    Copy the code

You can simulate two Eureka Serve servers (7001 and 7002)

3. Modify the YML configuration files on the two Eureka Servers

  1. Change the yML configuration file of cloud-Eureka-server7001 to:

    server:
      port: 7001
    
    eureka:
      instance:
        hostname: eureka7001.com  # Eureka Server instance name
      client:
        register-with-eureka: false  # Since the application is a registry, set it to false to not register itself with the registry
        fetch-registry: false # fetch- Registry is false, which means that I am a registry and my responsibility is to maintain service instances, not to retrieve services
        service-url:
        Set the address to which the Eureka Server will interact. Service registration and queries will depend on this address
          defaultZone: http://eureka7002.com:7002/eureka/22
    Copy the code
  2. Example Change the yML configuration file of cloud-Eureka-server7002 to:

    server:
      port: 7002
    
    eureka:
      instance:
        hostname: eureka7002.com  # Eureka Server instance name
      client:
        register-with-eureka: false  # Since the application is a registry, set it to false to not register itself with the registry
        fetch-registry: false # fetch- Registry is false, which means that I am a registry and my responsibility is to maintain service instances, not to retrieve services
        service-url:
        Set the address to which the Eureka Server will interact. Service registration and queries will depend on this address
          defaultZone: http://eureka7001.com:7001/eureka/
    Copy the code

4, test,

  1. Start the cloud-Eureka-Server7001 module

  2. Start the cloud-Eureka-Server7002 module

  3. Access request eureka7001.com:7001/ to view module 7001

  1. Access request: eureka7002.com:7002/ to view module 7002

A eureka cluster environment consisting of two Eureka nodes has been set up successfully.

6.3 Register order and payment microservices into Eureka cluster

Register payment service 8001 in the Eureka cluster

Modify the configuration of Eureka in the YML configuration file of the payment service 8001 module:

# eureka configuration
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/   # version of the cluster
    register-with-eureka: true Register yourself to Eureka Server
    Whether to fetch existing registration information from eurekaServer. Default to true. If the euREKA cluster is set to true, the EuREKA cluster can work with the Ribbon to use load balancing
    fetchregistry: true
Copy the code

Example Register order service 80 in the Eureka cluster

Modify the configuration of eureka in the YML configuration file of the order service 80 module:

# eureka configuration
eureka:
  client:
    service-url:
      Stand-alone version # defaultZone: http://localhost:7001/eureka/
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/   # version of the cluster
    register-with-eureka: true Register yourself to Eureka Server
    Whether to fetch existing registration information from eurekaServer. Default to true. If the euREKA cluster is set to true, the EuREKA cluster can work with the Ribbon to use load balancing
    fetchregistry: true
Copy the code

test

  1. Start the cloud-Eureka-Server7001 and cloud-Eureka-Server7002 modules

  2. Start the payment service module 8001

  3. Start the order service module 80

  4. Visit eureka7001.com:7001/ and http://eur…

    Eureka Server7001 registration succeeded. Procedure

Eureka Server7002 registration succeeded. Procedure

  1. Test whether the services provided by service provider 8001 are accessible

    To access the query service: http://localhost/consumer/payment/get/1

Access to add service: http://localhost/consumer/payment/create? serial=%E7%A5%9E%E6%98%8E

Test successful!

6.4. Configure the payment microservice cluster

1. Create cloud-Provider-Payment8002 by referring to the payment module cloud-Provider-Payment8001

  1. Copy the POM dependency of module 8001 to module 8002
  2. Copy 8001’s Java directory and resource directory into 8002
  3. Change the port number of module 8002 to 8002 in the YML configuration file
  4. Change the main startup class name of module 8002 to PaymentMain8002

2. Modify the controller of module 8001 and 8002

Example Change the controller of module 8001

Add port numbers to the original controller to distinguish service providers

@RestController
@Slf4j
public class PaymentController {

    @Resource
    private PaymentService paymentService;

    // Used to get the port number in the configuration file
    @Value("${server.port}")
    private String serverPort;


    @PostMapping(value = "/payment/create")
    public CommonResult create(@RequestBody Payment payment){
        int result = paymentService.create(payment);

        log.info("======= Add result ="+result);

        if (result > 0) {return new CommonResult(200."Add performed successfully, serverPort="+serverPort,result);
        }else {
            return new CommonResult(500."Add execution failed".null); }}@GetMapping(value = "/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id){
        Payment payment = paymentService.getPaymentById(id);

        log.info("======= Query Result ="+payment);

        if(payment ! =null) {return new CommonResult(200."Query executed successfully, serverPort="+serverPort,payment);
        }else {
            return new CommonResult(500."Query id as"+id+"Execution failed".null); }}}Copy the code

Example Change the controller of module 8002

The code is exactly the same, so I won’t repeat it.

After the modification of payment module 8001 and 8002, when the order module accesses the payment module cluster, it can distinguish which payment module is accessed through the port.

3, test,

  1. Start the cloud-Eureka-Server7001 and cloud-Eureka-Server7002 modules

  2. Start the payment service 8001 and 8002 modules

  3. Start the order service module 80

  4. Visit eureka7001.com:7001/ and http://eur…

    Eureka Server7001 registration succeeded. Procedure

    Eureka Server7002 registration succeeded. Procedure

  5. Test whether the services provided by the payment microservice clusters 8001 and 8002 are accessible

    To access the query service: http://localhost/consumer/payment/get/1

The query is successful, but when we refresh the browser and access again, the port number does not change, which means that the payment service we access is always module 8001 in the payment microservice cluster, which does not achieve load balancing.

This is because we are in the controller of module 80 of order, and the URL to access is fixed: so we are always accessing 8001.

public static final String REST_URL_PREFIX = "http://localhost:8001";
Copy the code

The RestTemplate load balancing function is implemented

Therefore, in the case of multiple service providers (payment microservices), it is not suitable for service consumers (order microservices) to access the service providers through the URL, but through the service name, because each service name in the payment microservices cluster is the same.

In order 80 module controller, change access by address to access by service name:

//public static final String REST_URL_PREFIX = "http://localhost:8001";
public static final String REST_URL_PREFIX = "http://CLOUD-PAYMENT-SERVICE";
Copy the code

Use the @loadBalanced annotation to give the RestTemplate load-balancing capability:

@Configuration
public class ConfigBean {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(a){
        return newRestTemplate(); }}Copy the code

Visit the query service again: http://localhost/consumer/payment/get/1

8001 when discovering the first accessed service

Refresh the browser, re-access, access the service for 8002

After that, the 8001 and 8002 services will be accessed in turn, which implements the default load balancing mechanism — polling

7. Improve the MICRO-service information of ACTUATOR

The Actuator function (health monitoring) of Spring Boot provides many interfaces for monitoring, such as viewing application system configurations and collecting statistics on related functions.

User-defined service instance name

1. Add the instance configuration to the YML profiles of Pay microservice 8001, Pay microservice 8002 and Order microservice 80

8001

# Note: Instance is the same as client
  instance:
    instance-id: springcloud-provider-payment8001   Custom status information
Copy the code

8002

  instance:
    instance-id: springcloud-provider-payment8002   Custom status information
Copy the code

80

instance:
  instance-id: springcloud-consumer-order80
Copy the code

2, start the program to view the effect:

User-defined service instance name succeeded!

Set the IP address displayed in the access path

Add a line below the instance configuration above:

8001

instance:
  instance-id: springcloud-provider-payment8001   
  prefer-ip-address: true  
Copy the code

8002

instance:
  instance-id: springcloud-provider-payment8002   
  prefer-ip-address: true  
Copy the code

80

instance:
  instance-id: springcloud-consumer-order80
  prefer-ip-address: true
Copy the code

Check the effect:

Defining status information

1, write configuration, info and Eureka sibling

info:
  app.name: springcloud-pengcheng
  company.name: wanli
Copy the code

2. Click the link for the status message

3. The page is displayed and the configuration information is returned successfully:

8. Service Discovery

For microservices registered in Eureka, information about that service can be obtained through service discovery

1. Modify the controller of payment module 8001

Inject DiscoveryClient, add a method

@Resource
private DiscoveryClient discoveryClient;


@GetMapping(value = "/payment/discovery")
public Object discovery(a){
    // Get the list of services
    List<String> services = discoveryClient.getServices();
    for (String service : services) {
        log.info("Service List:"+service);
    }
    // Obtain all instances of the service by the name of the service
    List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
    for (ServiceInstance instance : instances) {
        log.info(instance.getServiceId()+"\t"+
                 instance.getHost()+"\t"+
                 instance.getPort()+"\t"+
                 instance.getUri()
        );
    }
    return this.discoveryClient;
}
Copy the code

2. Add the @enableDiscoveryClient annotation to the primary startup class

3, test,

Access request: http://localhost:8001/payment/discovery

You can see the registered service name in Eureka.

Take another look at the idea console output:

Description All service names that have been registered in the Eureka registry and all service instances under the Cloud-payment-service service are displayed.

Self-protection mode

Error “EMERGENCY!” on admin page EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’re NOT. RENEWALS ARE LESSER THAN THRESHOLD AND lead to THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.”

Eureka is in self-protection mode.

Self-protection mode: When a microservice is not available, Eureka will not immediately clean up the service, but will still save the information of the microservice.

  • Protected mode, a feature provided by Eureka, is turned on by default and is recommended for use online.
  • If the Eureka Server does not receive a heartbeat from a microservice instance for a certain period of time, the Eureka Server will log off the instance (default 90 seconds). However, when a network partition fault occurs, the microservice cannot communicate with the Eureka Server. In this case, the Eureka Server enters the protected mode. After entering the self-protection mode, the service registry will be protected and the data in the service registry will not be deleted. After the network fault is recovered, the Eureka Server automatically exits the self-protection mode

You can disable the self-protection mode in eureka-server by using the following configuration:

eureka:
  server:
    enable-self-preservation: false
Copy the code

When the self-protection mode is off, a prompt will be displayed on the Eureka interface: