SpringCloud Notes Eureka Service Registration Center, Zookeeper Service Registration Center, and Consul Service Registration Center Case Details

1. Introduction

technologyVersion
Spring Cloud versionHoxton.SR1
Spring Boot version2.2.2RELEASE
Cloud Alibaba version2.1.0.RELEASE

official address

git address: https://github.com/spring-projects/spring-boot/releases/

Spring Boot official website: https://spring.io/projects/spring-boot

git address: https://github.com/spring-projects/spring-cloud

Spring Boot official website: https://spring.io/projects/spring-cloud

Version of Spring Cloud

Spring Cloud is named after the London subway station in England, and releases an iterative version in the form of subway station names A-Z and so on. Spring Cloud is a comprehensive project composed of many sub-projects, and each sub-project has a different release rhythm. In order to manage the version dependencies between SpringCloud and each sub-project, a list is released, which includes the sub-project version corresponding to a SpringCloud version. In order to avoid confusion between the SpringCloud version number and the sub-project version number, the SpringCloud version uses a name instead of a version number. The names of these versions use the names of London subway stations, and correspond to the version time sequence according to the order of the alphabet. For example, Angel is the first version, and Brixton is the second version. When the release content of SpringCloud reaches a critical point or a major BUG is resolved, a "service releases" version, SRX version for short, will be released. For example, Greenwich.SR2 is the second SRX version of the Greenwich version released by SpringCloud.

1. The relationship between SpringBoot and SpringCloud

Website: https://spring.io/projects/spring-cloud#overview

View address for a more detailed version: https://start.spring.io/actuator/info

{
    "git":{
        "branch":"64b2829d7b37506fa4e7e5361462ac3ca91c1692",
        "commit":{
            "id":"64b2829",
            "time":"2023-02-13T11:11:29Z"
        }
    },
    "build":{
        "version":"0.0.1-SNAPSHOT",
        "artifact":"start-site",
        "versions":{
            "spring-boot":"3.0.2",
            "initializr":"0.20.0-SNAPSHOT"
        },
        "name":"start.spring.io website",
        "time":"2023-02-13T11:12:37.946Z",
        "group":"io.spring.start"
    },
    "bom-ranges":{
        "codecentric-spring-boot-admin":{
            "2.4.3":"Spring Boot >=2.3.0.M1 and <2.5.0-M1",
            "2.5.6":"Spring Boot >=2.5.0.M1 and <2.6.0-M1",
            "2.6.8":"Spring Boot >=2.6.0.M1 and <2.7.0-M1",
            "2.7.4":"Spring Boot >=2.7.0.M1 and <3.0.0-M1",
            "3.0.0-M4":"Spring Boot >=3.0.0-M1 and <3.1.0-M1"
        },
        "solace-spring-boot":{
            "1.1.0":"Spring Boot >=2.3.0.M1 and <2.6.0-M1",
            "1.2.2":"Spring Boot >=2.6.0.M1 and <3.0.0-M1"
        },
        "solace-spring-cloud":{
            "1.1.1":"Spring Boot >=2.3.0.M1 and <2.4.0-M1",
            "2.1.0":"Spring Boot >=2.4.0.M1 and <2.6.0-M1",
            "2.3.2":"Spring Boot >=2.6.0.M1 and <3.0.0-M1"
        },
        "spring-cloud":{
            "Hoxton.SR12":"Spring Boot >=2.2.0.RELEASE and <2.4.0.M1",
            "2020.0.6":"Spring Boot >=2.4.0.M1 and <2.6.0-M1",
            "2021.0.0-M1":"Spring Boot >=2.6.0-M1 and <2.6.0-M3",
            "2021.0.0-M3":"Spring Boot >=2.6.0-M3 and <2.6.0-RC1",
            "2021.0.0-RC1":"Spring Boot >=2.6.0-RC1 and <2.6.1",
            "2021.0.5":"Spring Boot >=2.6.1 and <3.0.0-M1",
            "2022.0.0-M1":"Spring Boot >=3.0.0-M1 and <3.0.0-M2",
            "2022.0.0-M2":"Spring Boot >=3.0.0-M2 and <3.0.0-M3",
            "2022.0.0-M3":"Spring Boot >=3.0.0-M3 and <3.0.0-M4",
            "2022.0.0-M4":"Spring Boot >=3.0.0-M4 and <3.0.0-M5",
            "2022.0.0-M5":"Spring Boot >=3.0.0-M5 and <3.0.0-RC1",
            "2022.0.0-RC1":"Spring Boot >=3.0.0-RC1 and <3.0.0-RC2",
            "2022.0.0-RC2":"Spring Boot >=3.0.0-RC2 and <3.0.0",
            "2022.0.1":"Spring Boot >=3.0.0 and <3.1.0-M1"
        },
        "spring-cloud-azure":{
            "4.6.0":"Spring Boot >=2.5.0.M1 and <3.0.0-M1",
            "5.0.0":"Spring Boot >=3.0.0-M1 and <3.1.0-M1"
        },
        "spring-cloud-gcp":{
            "2.0.11":"Spring Boot >=2.4.0-M1 and <2.6.0-M1",
            "3.4.3":"Spring Boot >=2.6.0-M1 and <3.0.0-M1",
            "4.0.0":"Spring Boot >=3.0.0-M1 and <3.1.0-M1"
        },
        "spring-cloud-services":{
            "2.3.0.RELEASE":"Spring Boot >=2.3.0.RELEASE and <2.4.0-M1",
            "2.4.1":"Spring Boot >=2.4.0-M1 and <2.5.0-M1",
            "3.3.0":"Spring Boot >=2.5.0-M1 and <2.6.0-M1",
            "3.4.0":"Spring Boot >=2.6.0-M1 and <2.7.0-M1",
            "3.5.0":"Spring Boot >=2.7.0-M1 and <3.0.0-M1",
            "4.0.0":"Spring Boot >=3.0.0 and <3.1.0-M1"
        },
        "spring-shell":{
            "2.1.6":"Spring Boot >=2.7.0 and <3.0.0-M1",
            "3.0.0":"Spring Boot >=3.0.0 and <3.1.0-M1"
        },
        "vaadin":{
            "14.9.6":"Spring Boot >=2.1.0.RELEASE and <2.6.0-M1",
            "23.2.15":"Spring Boot >=2.6.0-M1 and <2.7.0-M1",
            "23.3.5":"Spring Boot >=2.7.0-M1 and <2.8.0-M1"
        },
        "wavefront":{
            "2.0.2":"Spring Boot >=2.1.0.RELEASE and <2.4.0-M1",
            "2.1.1":"Spring Boot >=2.4.0-M1 and <2.5.0-M1",
            "2.2.2":"Spring Boot >=2.5.0-M1 and <2.7.0-M1",
            "2.3.4":"Spring Boot >=2.7.0-M1 and <3.0.0-M1",
            "3.0.1":"Spring Boot >=3.0.0-M1 and <3.1.0-M1"
        }
    },
    "dependency-ranges":{
        "okta":{
            "1.4.0":"Spring Boot >=2.2.0.RELEASE and <2.4.0-M1",
            "1.5.1":"Spring Boot >=2.4.0-M1 and <2.4.1",
            "2.0.1":"Spring Boot >=2.4.1 and <2.5.0-M1",
            "2.1.6":"Spring Boot >=2.5.0-M1 and <3.0.0-M1",
            "3.0.2":"Spring Boot >=3.0.0-M1 and <3.1.0-M1",
            "managed":"Spring Boot >=3.1.0-M1"
        },
        "mybatis":{
            "2.1.4":"Spring Boot >=2.1.0.RELEASE and <2.5.0-M1",
            "2.2.2":"Spring Boot >=2.5.0-M1 and <2.7.0-M1",
            "2.3.0":"Spring Boot >=2.7.0-M1 and <3.0.0-M1",
            "3.0.0":"Spring Boot >=3.0.0-M1"
        },
        "camel":{
            "3.5.0":"Spring Boot >=2.3.0.M1 and <2.4.0-M1",
            "3.10.0":"Spring Boot >=2.4.0.M1 and <2.5.0-M1",
            "3.13.0":"Spring Boot >=2.5.0.M1 and <2.6.0-M1",
            "3.17.0":"Spring Boot >=2.6.0.M1 and <2.7.0-M1",
            "3.20.2":"Spring Boot >=2.7.0.M1 and <3.0.0-M1",
            "4.0.0-M1":"Spring Boot >=3.0.0-M1 and <3.1.0-M1"
        },
        "picocli":{
            "4.7.0":"Spring Boot >=2.5.0.RELEASE and <3.1.0-M1"
        },
        "open-service-broker":{
            "3.2.0":"Spring Boot >=2.3.0.M1 and <2.4.0-M1",
            "3.3.1":"Spring Boot >=2.4.0-M1 and <2.5.0-M1",
            "3.4.1":"Spring Boot >=2.5.0-M1 and <2.6.0-M1",
            "3.5.0":"Spring Boot >=2.6.0-M1 and <2.7.0-M1"
        }
    }
}

2. Regarding the suspension/upgrade/replacement of various components of Cloud

Official website: https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/

Official website: https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/

Spring Cloud Chinese documentation: https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md

After upgrade:

3. Code construction of microservice architecture (cloud-provider-payment8001)

3.1 pom file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.yyds</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8001</artifactId>



    <dependencies>
        <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.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>


        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.22</version>
        </dependency>


        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</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>
        
    </dependencies>


</project>

3.2 Change the yml file

server:
  port: 8001


spring:
  application:
    name: cloud-payment-service



  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root



mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.yyds.springcloud.entities

3.3 Main Boot

package com.yyds.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class, args);
        System.out.println("*******************PaymentMain8001 Start successfully********************");
    }
}

3.4 Business class

3.4.1 dao and mapper.xml

package com.yyds.springcloud.dao;

import com.yyds.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface PaymentDao {

    int create(Payment  payment);


    Payment getPaymentById(@Param("id") Long id);

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yyds.springcloud.dao.PaymentDao">

    <resultMap id="BaseResultMap" type="payment">
        <result column="id" property="id"/>
        <result column="serial" property="serial"/>
    </resultMap>

    <insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
        insert into payment (serial) value (#{serial});
    </insert>


   <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
       select * from payment where id = #{id}
   </select>

</mapper>

3.4.2 service

package com.yyds.springcloud.service;

import com.yyds.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Param;

public interface PaymentService {
     int create(Payment payment);
     Payment getPaymentById(@Param("id") Long id);
}
package com.yyds.springcloud.service.impl;

import com.yyds.springcloud.dao.PaymentDao;
import com.yyds.springcloud.entities.Payment;
import com.yyds.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class PaymentServiceImpl implements PaymentService {

    @Resource
    private PaymentDao paymentDao;

    @Override
    public int create(Payment payment) {
        return paymentDao.create(payment);
    }

    @Override
    public Payment getPaymentById(Long id) {
        return paymentDao.getPaymentById(id);
    }
}

3.4.3 controller

package com.yyds.springcloud.controller;

import com.yyds.springcloud.entities.CommonResult;
import com.yyds.springcloud.entities.Payment;
import com.yyds.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

@RestController
@RequestMapping("/payment")
@Slf4j
public class PaymentController {
    @Resource
    private PaymentService paymentService;

    @PostMapping("/create")
    public CommonResult<Payment> create(@RequestBody  Payment payment){
        int result = paymentService.create(payment);
        if(result > 0){
            return new CommonResult(200,"Inserted into the database successfully",result);
        }else {
            return new CommonResult(444,"Failed to insert into database",null);
        }
    }

    @GetMapping("/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        Payment payment = paymentService.getPaymentById(id);
        log.info("*****search result:{}",payment);
        if (payment != null) {
            return new CommonResult(200,"search successful",payment);
        }else {
            return new CommonResult(200,"no correspondence id",null);
        }
    }
}

3.4.4 Entity class

package com.yyds.springcloud.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T>{

    private Integer code;

    private String message;

    private T data;


    public CommonResult(Integer code, String message) {
        this(code,message,null);
    }
}
package com.yyds.springcloud.entities;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
    private Long id;
    private String serial;
}

4,cloud-consumer-order80

RestTemplate provides a variety of convenient methods for accessing remote Http services. It is a simple and convenient way to access restful service template classes. It is a client template tool set provided by Spring for accessing Rest services.

  • Official website address

https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

  • use

Using restTemplate to access the restful interface is very simple and rude. (url, requestMap, ResponseBean.class) These three parameters represent
REST request address, request parameters, and HTTP response conversion are converted into object types.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.yyds</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-order80</artifactId>


    <dependencies>
        <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>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>
  • config configuration class
package com.yyds.springcloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;


@Configuration
public class ApplicationContextConfig {

    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
package com.yyds.springcloud.controller;


import com.yyds.springcloud.entities.CommonResult;
import com.yyds.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@RequestMapping("/consumer/payment")
@Slf4j
public class OrderController {

    public static final String PAYMENT_URL = "http://localhost:8001";

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/create")
    public CommonResult<Payment> create(Payment payment) {
        return restTemplate.postForObject(PAYMENT_URL +"/payment/create",payment,CommonResult.class);
    }

    @GetMapping("/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {
        return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }
   
}

test

# calls between services

http://localhost/consumer/payment/get/10
{"code":200,"message":"search successful","data":{"id":10,"serial":"11111"}}

http://localhost/consumer/payment/create?serial=6666
{"code":200,"message":"Inserted into the database successfully","data":1}

engineering reconstruction

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.yyds</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-api-commons</artifactId>


    <dependencies>
        <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>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.1.0</version>
        </dependency>
    </dependencies>

</project>

# Install cloud-api-commons locally
mvn clean

mvn install

Delete the entity class package in the two microservice modules, and then add the following configuration in the pom files of the two modules

		<!--import your own defined api Universal package-->
        <dependency>
            <groupId>com.yyds</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

2. Eureka service registration and discovery

2.1 Introduction

2.1.1 What is Service Governance

​ Spring Cloud encapsulates the Eureka module developed by Netflix to implement service governance

​ In the traditional rpc remote call framework, it is more complicated to manage the dependencies between each service and the management, so it is necessary to use service governance to manage the dependencies between services and services, which can realize service calls, load balancing, Fault tolerance, etc., realize service discovery and registration.

2.2.2 What is service registration and discovery

​ Eureka adopts the design architecture of CS. Eureka Server is the server of the service registration function, which is the service registration center. Other microservices in the system use Eureka's client to connect to Eureka Server and maintain a heartbeat connection. In this way, system maintainers can use Eureka Server to monitor whether each microservice in the system is running normally.
​ In service registration and discovery, there is a registration center. When the server starts, it will register the information of the current server, such as the service address and mailing address, to the registration center in the form of an alias. The other party (consumer | service provider) uses the alias to obtain the actual service communication address from the registration center, and then realizes the local RPC call RPC remote call framework. The core design idea: lies in the registration center, because the use of the registration center Manage each service and a dependency between services (service governance concept). In any rpc remote framework, there will be a registration center (store service address related information (interface address))

2.2.3 Two components of Eureka

Eureka Server provides service registration service
After each microservice node is configured and started, it will be registered in EurekaServer, so that the service registry in EurekaServer will store the information of all available service nodes, and the information of service nodes can be seen directly in the interface.

EurekaClient accesses through the registration center
It is a Java client that simplifies the interaction with Eureka Server. The client also has a built-in load balancer that uses a round-robin load algorithm. After the application starts, a heartbeat will be sent to Eureka Server (the default period is 30 seconds). If Eureka Server does not receive a node's heartbeat within multiple heartbeat cycles, EurekaServer will remove the service node from the service registry (default 90 seconds)

2.2 Construction of stand-alone Eureka

Module name: cloud-eureka-server7001

2.2.1 The pom file is as follows

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.yyds</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-eureka-server7001</artifactId>


    <dependencies>
        <!--eureka-server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!-- import your own defined api common package, you can use Payment to pay Entity -->
        <dependency>
            <groupId>com.yyds</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--boot web actuator-->
        <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>
        <!--General general configuration-->
        <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>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>


</project>

2.2.2 yml file

server:
  port: 7001


eureka:
  instance:
    hostname: localhost #The instance name of the eureka server
  client:
    register-with-eureka: false     #false means do not register yourself with the registry.
    fetch-registry: false     #false means that my end is the registration center, and my responsibility is to maintain the service instance, and there is no need to retrieve the service
    service-url:
      defaultZone: http://localhost:7001/eureka

2.2.3 Main startup class

package com.yyds.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
// add this note
@EnableEurekaServer
public class EurekaMain7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class, args);
        System.out.println("************EurekaMain7001 Start successfully******************");
    }
}

Start the eureka test

http://localhost:7001/

2.2.4 Payment microservice cloud-provider-payment8001 register Eureka

EurekaClient cloud-provider-payment8001 will be registered into EurekaServer to become a service provider provider.

2.2.4.1 Change the pom file

       <!--Add to eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2.2.4.2 Write yml file

# Add the following configuration information
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
    register-with-eureka: true 
    fetch-registry: true

2.2.4.3 Modify the main startup class

package com.yyds.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;


@SpringBootApplication
// add this note
@EnableEurekaClient
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class, args);
        System.out.println("*******************PaymentMain8001 Start successfully********************");
    }
}

Restart, refresh the Eureka page

2.2.5 Order microservice cloud-consumer-order80 register Eureka

EurekaClient cloud-consumer-order80 will be registered into EurekaServer to become a service consumer consumer.

2.2.5.1 Change the pom file

       <!--Add to eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2.2.5.2 Write yml file

server:
  port: 80


spring:
  application:
    name: cloud-order-service


# Add the following configuration information
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
    register-with-eureka: true
    fetch-registry: true

2.2.5.3 Modify the main startup class

package com.yyds.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class, args);
        System.out.println("***************OrderMain80 Start successfully********************");
    }
}

Restart, refresh the Eureka page

C:\Users\Undo\AppData\Roaming\Typora\typora-user-images\image-20230215231436950.png

2.3 Construction of cluster Eureka

If your registration center has only one, if it fails, the entire service environment will be unavailable, so you need to build a Eureka registration center cluster to achieve load balancing + fault tolerance.

2.3.1 New module cloud-eureka-server7002

Refer to cloud-eureka-server7001 to create a new module cloud-eureka-server7002

2.3.2 modify hosts

Add to the hosts file in the C:\Windows\System32\drivers\etc path

127.0.0.1	eureka7001.com
127.0.0.1	eureka7002.com

2.3.3 Modify the yml file

server:
  port: 7001


eureka:
  instance:
    hostname: eureka7001.com #The instance name of the eureka server
  client:
    register-with-eureka: false     #false means do not register yourself with the registry.
    fetch-registry: false     #false means that my end is the registration center, and my responsibility is to maintain the service instance, and there is no need to retrieve the service
    service-url:
    #The cluster points to other eureka
      defaultZone: http://eureka7002.com:7002/eureka/
server:
  port: 7002


eureka:
  instance:
    hostname: eureka7002.com #The instance name of the eureka server
  client:
    register-with-eureka: false     #false means do not register yourself with the registry.
    fetch-registry: false     #false means that my end is the registration center, and my responsibility is to maintain the service instance, and there is no need to retrieve the service
    service-url:
    #The cluster points to other eureka
      defaultZone: http://eureka7001.com:7001/eureka/

2.3.4 Modify the yml file of payment module and order module

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service

  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.yyds.springcloud.entities

eureka:
  client:
    service-url:
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # cluster version
    register-with-eureka: true
    fetch-registry: true
server:
  port: 80

spring:
  application:
    name: cloud-order-service

# Add the following configuration information
eureka:
  client:
    service-url:
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # cluster version
    register-with-eureka: true # Whether to grab the existing registration information from EurekaServer, the default is true. Single node does not matter, the cluster must be set to true to use load balancing with ribbon
    fetch-registry: true

2.3.5 Testing

  • First start EurekaServer, 7001/7002 service

  • Then start the service provider provider, 8001

  • To start the consumer again, 80

  • Test port number: http://localhost/consumer/payment/get/1

2.3.6 Payment module service provider cluster configuration

Refer to cloud-provider-payment8001 to create a new cloud-provider-payment8002 module

And add the server.port attribute to the controller s of the two modules to facilitate testing

package com.yyds.springcloud.controller;

import com.yyds.springcloud.entities.CommonResult;
import com.yyds.springcloud.entities.Payment;
import com.yyds.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

@RestController
@RequestMapping("/payment")
@Slf4j
public class PaymentController {
    @Resource
    private PaymentService paymentService;

    @Value("${server.port}")
    private String serverPort;

    @PostMapping("/create")
    public CommonResult<Payment> create(@RequestBody  Payment payment){
        int result = paymentService.create(payment);
        if(result > 0){
            return new CommonResult(200,"Inserted into the database successfully,serverPort+" + serverPort ,result);
        }else {
            return new CommonResult(444,"Failed to insert into database",null);
        }
    }

    @GetMapping("/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){

        Payment payment = paymentService.getPaymentById(id);
        log.info("*****search result:{}",payment);
        if (payment != null) {
            return new CommonResult(200,"search successful,serverPort+" + serverPort,payment);
        }else {
            return new CommonResult(200,"no correspondence id",null);
        }
    }
}

You can see the following page from Eureka

Visit http://localhost/consumer/payment/get/1

At this time, it is found that they are all accessing the 8001 service

{"code":200,"message":"search successful,serverPort+8001","data":{"id":1,"serial":"00001a"}}

Modify the order microservice interface

package com.yyds.springcloud.controller;


import com.yyds.springcloud.entities.CommonResult;
import com.yyds.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@RequestMapping("/consumer/payment")
@Slf4j
public class OrderController {
//    public static final String PAYMENT_URL = "http://localhost:8001";
    public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/create")
    public CommonResult<Payment> create(Payment payment) {
        return restTemplate.postForObject(PAYMENT_URL +"/payment/create",payment,CommonResult.class);
    }

    @GetMapping("/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {
        return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }
}

At this time, when visiting http://localhost/consumer/payment/get/1, the following exception java.net.UnknownHostException: CLOUD-PAYMENT-SERVICE will be reported.

Need to modify the configuration class

package com.yyds.springcloud.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;


@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced  // add this note
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

}

At this point, load balancing will be performed

{"code":200,"message":"search successful,serverPort+8002","data":{"id":1,"serial":"00001a"}}
{"code":200,"message":"search successful,serverPort+8001","data":{"id":1,"serial":"00001a"}}

2.4 More usage

2.4.1 actuator microservice information improvement

Host name: service name modification

eureka:
  client:
    service-url:
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # cluster version
    register-with-eureka: true
    fetch-registry: true
  # add this configuration
  instance:
    instance-id: payment8001
    
    
eureka:
  client:
    service-url:
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # cluster version
    register-with-eureka: true
    fetch-registry: true
  # add this configuration
  instance:
    instance-id: payment8002

Access information has IP information prompt

eureka:
  client:
    service-url:
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # cluster version
    register-with-eureka: true
    fetch-registry: true
  instance:
    instance-id: payment8001
    prefer-ip-address: true  # show ip
    
eureka:
  client:
    service-url:
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # cluster version
    register-with-eureka: true
    fetch-registry: true
  instance:
    instance-id: payment8002
    prefer-ip-address: true  # show ip

2.4.2 Service discovery Discovery

For microservices registered in eureka, information about the service can be obtained through service discovery.

package com.yyds.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;


@SpringBootApplication
// add this note
@EnableEurekaClient
// add this note
@EnableDiscoveryClient
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class, args);
        System.out.println("*******************PaymentMain8001 Start successfully********************");
    }
}
	@Resource
    private DiscoveryClient discoveryClient;

    @GetMapping("/discovery")
    public Object discovery(){
        // service manifest list
        List<String> services = discoveryClient.getServices();
        for (String service : services) {
            log.info("******************service:"+service);
        }
	
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance instance : instances) {
            String host = instance.getHost();
            String serviceId = instance.getServiceId();
            URI uri = instance.getUri();
            int port = instance.getPort();

            log.info(serviceId + "\t" + host + "\t"+ port+ "\t" + uri );
        }
        return this.discoveryClient;
    }

Test http://localhost:8001/payment/discovery

{"services":["cloud-payment-service","cloud-order-service"],"order":0}
******************service:cloud-payment-service
******************service:cloud-order-service
CLOUD-PAYMENT-SERVICE	192.168.42.2	8002	http://192.168.42.2:8002
CLOUD-PAYMENT-SERVICE	192.168.42.2	8001	http://192.168.42.2:8001

2.4.3 Eureka self-protection

  • What is Self-Defense Mode?

​ By default, if EurekaServer does not receive the heartbeat of a microservice instance within a certain period of time, EurekaServer will log off the instance (90 seconds by default). However, when a network partition failure occurs (delay, freeze, congestion), the normal communication between the microservice and EurekaServer may not be possible, and the above behavior may become very dangerous-because the microservice itself is actually healthy, and it is not at this time. This microservice should be unregistered. Eureka solves this problem through the "self-protection mode"-when the EurekaServer node loses too many clients in a short period of time (a network partition failure may occur), then this node will enter the self-protection mode.

  • Why is there a Eureka self-protection mechanism?
    In order to prevent EurekaClient from running normally, but in the case of a network failure with EurekaServer, EurekaServer will not immediately remove the EurekaClient service

In self-protection mode, Eureka Server will protect the information in the service registry and no longer log out any service instances. Its design philosophy is to rather keep wrong service registration information than blindly unregister any service instance that may be healthy.

  • no self-protection
eureka:
  instance:
    hostname: eureka7001.com #The instance name of the eureka server
  client:
    register-with-eureka: false     #false means do not register yourself with the registry.
    fetch-registry: false     #false means that my end is the registration center, and my responsibility is to maintain the service instance, and there is no need to retrieve the service
    service-url:
    #The cluster points to other eureka
      defaultZone: http://eureka7002.com:7002/eureka/
    #Standalone is 7001 itself
#      defaultZone: http://localhost:7001/eureka
  server:
   #Turn off the self-protection mechanism to ensure that unavailable services are kicked out in time
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 2000
server:
  port: 8001

###service name (service registered to eureka name)
spring:
    application:
        name: cloud-provider-payment

eureka:
  client: #The service provider provider is registered in the eureka service list
    service-url:
      register-with-eureka: true
      fetch-registry: true
      # cluster version
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
      # singleton version
      defaultZone: http://eureka7001.com:7001/eureka
#Heartbeat detection and renewal time
#Set smaller during development to ensure that the registration center can remove the service even after the service is closed
  instance:
  #The time interval for the Eureka client to send heartbeats to the server, in seconds (the default is 30 seconds)
    lease-renewal-interval-in-seconds: 1
  #The Eureka server waits for the upper limit of the time after receiving the last heartbeat, in seconds (the default is 90 seconds), and the timeout will remove the service
    lease-expiration-duration-in-seconds: 2

After closing 8001, Eureka will remove it.

2.4.4 Eureka stopped updating

https://github.com/Netflix/eureka/wiki

C:\Users\Undo\AppData\Roaming\Typora\typora-user-images\image-20230216223537190.png

3. Zookeeper service registration and discovery

  • zookeeper is a distributed coordination tool that can realize the registration center function

  • The zookeeper server replaces the Eureka server, and zk serves as the service registry

3.1 Service provider cloud-provider-payment8004

3.1.1 pom file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.yyds</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8004</artifactId>

    <dependencies>


        <!--to integrate zk client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <!--First exclude the built-in zookeeper3.5.3-->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--Add your own installed zookeeper3.4.6 cluster-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
            <!-- Exclude log dependencies, otherwise log conflicts will occur -->
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </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>
    </dependencies>


</project>

3.1.2 yml file

server:
  port: 8004


spring:
  application:
    name: cloud-payment-service
  cloud:
    zookeeper:
      connect-string: 192.168.42.101:2181,192.168.42.102:2181,192.168.42.103:2181

3.1.3 Main startup class

package com.yyds.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;



@SpringBootApplication
//This annotation is used to register services when using consul or zookeeper as a registry
@EnableDiscoveryClient
public class PaymentMain8004 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8004.class, args);
        System.out.println("*******************PaymentMain8004 Start successfully********************");
    }
}

3.1.4 Business class

package com.yyds.springcloud.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/payment")
@Slf4j
public class PaymentController {

    
    @Value("${server.port}")
    private String serverPort;
    
    @GetMapping("/zk")
    public String paymentZk(){
        return "spring cloud with zk:" + serverPort + "\t" + System.currentTimeMillis();
    }

}

3.1.5 Testing

http://localhost:8004/payment/zk

spring cloud with zk:8004 1676560104626


# Check in zk and find that it has been registered
[zk: localhost:2181(CONNECTED) 3] ls /services
[cloud-payment-service]


[zk: localhost:2181(CONNECTED) 6] get /services/cloud-payment-service/25db342b-6426-47f5-9bc6-6c084a245723
{
    "name":"cloud-payment-service",
    "id":"25db342b-6426-47f5-9bc6-6c084a245723",
    "address":"DESKTOP-6CM5A7S",
    "port":8004,
    "sslPort":null,
    "payload":{
        "@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance",
        "id":"application-1",
        "name":"cloud-payment-service",
        "metadata":{

        }
    },
    "registrationTimeUTC":1676560096304,
    "serviceType":"DYNAMIC",
    "uriSpec":{
        "parts":[
            {
                "value":"scheme",
                "variable":true
            },
            {
                "value":"://",
                "variable":false
            },
            {
                "value":"address",
                "variable":true
            },
            {
                "value":":",
                "variable":false
            },
            {
                "value":"port",
                "variable":true
            }
        ]
    }
}

Note: When killing the registered service, zk will delete the service information.

3.2 Service provider cloud-consumerzk-order80

3.2.1 pom file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.yyds</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumerzk-order80</artifactId>

    <dependencies>

        <!--to integrate zk client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <!--First exclude the built-in zookeeper3.5.3-->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--Add to zookeeper3.4.6 Version-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
            <!-- Exclude log dependencies, otherwise log conflicts will occur -->
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </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>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

3.2.2 yml file

server:
  port: 80


spring:
  application:
    name: cloud-consumer-order
  cloud:
    zookeeper:
      connect-string: 192.168.42.101:2181,192.168.42.102:2181,192.168.42.103:2181

3.2.3 Main Boot

package com.yyds.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ZkOrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(ZkOrderMain80.class, args);
        System.out.println("***************ZkOrderMain80 Start successfully********************");
    }
}

3.2.4 Business class

package com.yyds.springcloud.controller;


import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@RequestMapping("/consumer/zk")
@Slf4j
public class OrderController {
    
    public static final String PAYMENT_URL = "http://cloud-payment-service";
    
    @Resource
    private RestTemplate restTemplate;
    
    @GetMapping()
    public String paymentInfo() {
        return restTemplate.getForObject(PAYMENT_URL +"/payment/zk",String.class);
    }
    
}

package com.yyds.springcloud.config;


import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;


@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

}

3.2.5 Testing

http://localhost/consumer/zk

spring cloud with zk:8004 1676562116384


[zk: localhost:2181(CONNECTED) 28] ls /services
[cloud-payment-service, cloud-consumer-order]


[zk: localhost:2181(CONNECTED) 30] get /services/cloud-consumer-order/8d13f36d-0697-4e98-a7f5-8d16169b4588

{
    "name":"cloud-consumer-order",
    "id":"8d13f36d-0697-4e98-a7f5-8d16169b4588",
    "address":"DESKTOP-6CM5A7S",
    "port":80,
    "sslPort":null,
    "payload":{
        "@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance",
        "id":"application-1",
        "name":"cloud-consumer-order",
        "metadata":{

        }
    },
    "registrationTimeUTC":1676561841585,
    "serviceType":"DYNAMIC",
    "uriSpec":{
        "parts":[
            {
                "value":"scheme",
                "variable":true
            },
            {
                "value":"://",
                "variable":false
            },
            {
                "value":"address",
                "variable":true
            },
            {
                "value":":",
                "variable":false
            },
            {
                "value":"port",
                "variable":true
            }
        ]
    }
}

4. Consul service registration and discovery

Consul is an open source distributed service discovery and configuration management system developed by HashiCorp in Go language.

Provides functions such as service governance, configuration center, and control bus in the microservice system. Each of these functions can be used individually as needed, or they can be used together to build a full range of service grids. In short, Consul provides a complete service grid solution.

Official website address: https://www.consul.io/intro/index.html

Download address: https://www.consul.io/downloads.html

Chinese documentation: https://www.springcloud.cc/spring-cloud-consul.html

4.1 Consul installation

The installation is relatively simple, directly unzip, only one exe file

consul --version

# start up
consul agent -dev


It can be accessed through the following address Consul 's homepage: http://localhost:8500

4.2 Payment service cloud-providerconsul-payment8006

4.2.1 pom file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.yyds</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-providerconsul-payment8006</artifactId>

    <dependencies>
        <!--to integrate consul-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </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>
    </dependencies>
</project>

4.2.2 yml file

server:
  port: 8006

spring:
  application:
    name: cloud-provider-payment
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
        heartbeat:
          enabled: true

4.2.3 Main startup class

package com.yyds.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
//This annotation is used to register services when using consul or zookeeper as a registry
@EnableDiscoveryClient
public class ConsulPaymentMain8006 {
    public static void main(String[] args) {
        SpringApplication.run(ConsulPaymentMain8006.class, args);
        System.out.println("*******************ConsulPaymentMain8006 Start successfully********************");
    }
}

4.2.4 Business class

package com.yyds.springcloud.controller;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/payment")
@Slf4j
public class PaymentController {

    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/consul")
    public String paymentZk(){
        return "spring cloud with consul:" + serverPort + "\t" + System.currentTimeMillis();
    }

}

4.2.5 Testing

http://localhost:8006/payment/consul

spring cloud with consul:8006 1676563822227

4.3 service consumer cloud-consumerconsul-order80

4.3.1 pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.yyds</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumerconsul-order80</artifactId>

    <dependencies>

        <!--to integrate consul-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </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>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

4.3.2 yml

server:
  port: 80

spring:
  application:
    name: cloud-consumer-order
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
        heartbeat:
          enabled: true

4.3.3 Master Boot

package com.yyds.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConsulOrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(ConsulOrderMain80.class, args);
        System.out.println("***************ConsulOrderMain80 Start successfully********************");
    }
}

4.3.4 Business class

package com.yyds.springcloud.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@RequestMapping("/consumer/consul")
@Slf4j
public class OrderConsulController {

    public static final String PAYMENT_URL = "http://cloud-provider-payment";

    @Resource
    private RestTemplate restTemplate;

    @GetMapping()
    public String paymentInfo() {
        return restTemplate.getForObject(PAYMENT_URL +"/payment/consul",String.class);
    }
}

4.3.5 Testing

http://localhost/consumer/consul

spring cloud with consul:8006 1676564785406

Tags: Spring Cloud eureka java-consul

Posted by egorig on Fri, 17 Feb 2023 23:21:37 +0530