Construction of spring cloud Basic test environment

1, Basic components

  • Registration Center: Eureka
  • Load balancing: Ribbon
  • Declarative call to remote method: Feign
  • Fusing, degradation and monitoring: Hystrix
  • Gateway: Zuul

2, Establishment of basic test environment

Using RestTemplate to implement remote method calls

1. Structure

2. Specific construction

2.1. Create parent project

Pro01 spring cloud parent is packaged in pom
In POM Adding dependencies to XML files

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.tianfei</groupId>
	<artifactId>pro01-spring-cloud-parent</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>


	<!-- Configuration dependency management -->
	<dependencyManagement>
		<dependencies> 
		<!-- Import SpringCloud Dependency information needed -->
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Greenwich.SR2</version>
				<type>pom</type> 
				<!-- import The dependency range indicates that the spring-cloud-dependencies Dependency information import in package -->
				<scope>import</scope>
			</dependency> 
			<!-- Import SpringBoot Dependency information needed -->
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>2.1.6.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

2.2. Create a general project

Pro02 spring cloud common is packaged in jar
① pom. The XML file configuration is as follows:

  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.tianfei</groupId>
    <artifactId>pro01-spring-cloud-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>pro02-spring-cloud-common</artifactId>
  <packaging>jar</packaging>

② Create the entity class Employee in the project

/**
 * @author tianfei
 *
 */
public class Employee {

	private Integer empId;
	private String empName;
	private Double empSalary;
	
	public Employee() {
	}

	public Employee(Integer empId, String empName, Double empSalary) {
		super();
		this.empId = empId;
		this.empName = empName;
		this.empSalary = empSalary;
	}

	public Integer getEmpId() {
		return empId;
	}

	public void setEmpId(Integer empId) {
		this.empId = empId;
	}

	public String getEmpName() {
		return empName;
	}

	public void setEmpName(String empName) {
		this.empName = empName;
	}

	public Double getEmpSalary() {
		return empSalary;
	}

	public void setEmpSalary(Double empSalary) {
		this.empSalary = empSalary;
	}

	@Override
	public String toString() {
		return "Employee [empId=" + empId + ", empName=" + empName + ", empSalary=" + empSalary + "]";
	}
	
}

2.3. Create a provider project

Pro03 spring cloud provider, which is packaged in jar
① pom. The XML configuration file is as follows

	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.tianfei</groupId>
		<artifactId>pro01-spring-cloud-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>pro03-spring-cloud-provider</artifactId>
	<packaging>jar</packaging>


	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.tianfei</groupId>
			<artifactId>pro02-spring-cloud-common</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>

② Create startup class SpringCloudProvider

@SpringBootApplication
public class SpringCloudProvider {

	public  static void main(String[] args) {
		
		SpringApplication.run(SpringCloudProvider.class, args);
	}
	
}

③ Create an application. In the Resource directory YML file and make the following configuration

server:
  port: 1000

④ Create Controller

Since the server response returns JSON data, @ RestController is used

@RestController
public class EmployeeController {
	
	@RequestMapping("/provider/get/employee/remote")
	public Employee getEmployeeRemote() {
		return new Employee(555, "tom555", 555.55);
	}
}

⑤ Start and try to access the request

2.4. Create consumer Engineering

Pro04 spring cloud consumer is packaged in jar
① pom. The XML configuration is as follows

	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.tianfei</groupId>
		<artifactId>pro01-spring-cloud-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>pro04-spring-cloud-consumer</artifactId>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.tianfei</groupId>
			<artifactId>pro02-spring-cloud-common</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>

② Create startup class SpringCloudConsumer

@SpringBootApplication
public class SpringCloudConsumer {

	public  static void main(String[] args) {
		
		SpringApplication.run(SpringCloudConsumer.class, args);
	}
	
}

③ Create application YML file, configure port number

server:
  port: 4000

④ Create a configuration class to inject RestTemplate into IOC container

@Configuration
public class SpringCloudConfig {

    @Bean
    public RestTemplate getRestTemplate(){

        return new RestTemplate();
    }
}

⑤ Write Controller

/**
 * @author: Herz
 * @date: 2021/7/24 10:30
 */
@RestController
public class HumanResourceController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/get/employee")
    public Employee getEmployeeRemote() {

        // 1. Declare the host address plus the end address of the remote microservice
        String host = "http://localhost:1000";

        // 2. Declare the URL address of the specific function to be called
        String url = "/provider/get/employee/remote";

        // 3. Call remote microservice through RestTemplate
        return restTemplate.getForObject(host + url, Employee.class);
    }
}

⑥ Try to remotely obtain the data returned by the Provider from the Consumer

2.5. Create Eureka registry

pro05-spring-cloud-eureka
① pom. The XML configuration file is as follows

    <parent>
        <artifactId>pro01-spring-cloud-parent</artifactId>
        <groupId>com.tianfei</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>pro05-spring-cloud-eureka</artifactId>

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

If an error caused by: Java is reported when starting the startup class of the project lang.IllegalStateException: StandardEngine[Tomcat]. StandardHost[localhost]. Tomcatembeddedcontext [] failed to start, in POM Add the following dependencies to XML

        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.2</version>
        </dependency>

        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>

② Create startup class SpringCloudEureka

// Enable Eureka server features
@EnableEurekaServer

@SpringBootApplication
public class SpringCloudEureka {

	public  static void main(String[] args) {

		SpringApplication.run(SpringCloudEureka.class, args);
	}

}

③ Create application YML file and make the following configuration

server:
  port: 5000

eureka:
  instance:
    hostname: localhost                 # Configure the host address of the current Eureka service
  client:
    register-with-eureka: false         # The current service itself is a registration center, so you don't have to "register yourself"
    fetch-registry: false               # The current service itself is a registry, so it is not necessary to "retrieve information from the registry"
    service-url:                        # The address where the client (referring to the consumer, provider) accesses the current registry
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

④ Launch and try to access Eureka interface

2.6. Objective 1: register the Provider with Eureka

① In the POM of pro03 spring cloud provider project Add the following dependencies to the XML file:

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

② In the yml configuration file of the pro03 spring cloud provider project, add the following configuration

server:
  port: 1000


eureka:
  client:
    service-url:
      defaultZone: http://Localhost: 5000 / eureka / # provider is used as the access address for the client to access eureka (so you need to add "/ eureka")

spring:
  application:
    name: com-provider                                # Set the application name of the current microservice so that it can be found when calling the current microservice through the microservice name in the future
                                                      # When developing in the spring cloud environment, each microservice project must set an application name

③ Restart the startup class of the Provider project
④ Refresh Eureka page to see if the registration is successful

2.7. Target 2: when the consumer accesses the provider, use the microservice name instead of localhost:1000

① Analysis

② In the POM of the Consumer project Add the following dependencies to XML:

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

③ In application Add again in the YML configuration file:

spring:
  application:
    name: com-consumer        # Specify the application name of the microservice

eureka:
  client:
    service-url:
      defaultZone: http://localhost:5000/eureka / # use the eureka registry to find the information of the microservice to be called

④ When injecting beans of RestTemplate, @ LoadBalance is added to support load balancing

@Configuration
public class SpringCloudConfig {

    // Support load balancing
    @LoadBalanced
    @Bean
    public RestTemplate getRestTemplate(){

        return new RestTemplate();
    }
}

⑤ Replace the host address and port number with the microservice application name in the Controller

/**
 * @author: Herz
 * @date: 2021/7/24 10:30
 */
@RestController
public class HumanResourceController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/get/employee")
    public Employee getEmployeeRemote() {

        // 1. Declare the host address plus the end address of the remote microservice
//        String host = "http://localhost:1000";
        // Replace "host address and port number" with "microservice name" of the provider
        String host = "http://com-provider";

        // 2. Declare the URL address of the specific function to be called
        String url = "/provider/get/employee/remote";

        // 3. Call remote microservice through RestTemplate
        return restTemplate.getForObject(host + url, Employee.class);
    }
}

2.8. Objective 3: use Ribbon's client load balancing function

1. Analysis

2. Ribbon dependency is introduced. Since target 2 has already introduced this dependency in the Consumer project, it can no longer be introduced
3. Modify the Controller method in the Provider project

@RestController
public class EmployeeController {

    @RequestMapping("/provider/get/employee/remote")
    public Employee getEmployeeRemote(HttpServletRequest request) {

        // Gets the port number of the current microservice
        int serverPort = request.getServerPort();

        return new Employee(555, "tom555 " + serverPort, 555.55);
    }
}

4. The Provider starts as a cluster
Start the first instance by port number 1000
Start the second instance according to port number 2000
Start the third instance according to port number 3000

In the application of the Provider project Change the port number in YML

server:
  port: 3000   # Just change here

5. Consumer normal access



Each refresh will alternate in this order, reflecting the polling strategy of load balancing. That is, Ribbon's load balancing function has worked.

!!! Note: the microservice name of the provider must use the same name to form a cluster, otherwise it will not be recognized as belonging to the same cluster.

Using Feign to implement remote method calls

1. Analysis

2. Operation

1. In the POM of the Common project Introducing dependencies into XML

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

2. Create an interface for remote calling methods in the Common project
!!! Note: the package of this interface must be the same as the package name of the startup class of other projects or its sub package.

// @FeignClient annotation indicates that the current interface corresponds to a Provider. The value attribute in the annotation specifies the microservice name of the Provider to be called
@FeignClient( value = "com-provider")
public interface EmployeeRemoteService {

    // Interface method called remotely
    // The address in the @ RequestMapping annotation is required to be consistent with that in the Provider
    // The method statement is required to be consistent
    // The @ RequestParam, @ PathVariable, @ RequestBody used to obtain request parameters cannot be omitted. Both sides are consistent
    @RequestMapping("/provider/get/employee/remote")
    public Employee getEmployeeRemote();
}

3. Modify the Controller in the Provider project

@RestController
public class EmployeeController {

    @RequestMapping("/provider/get/employee/remote")
    public Employee getEmployeeRemote() {

        return new Employee(555, "tom555 ", 555.55);
    }
}

4. Create a new Consumer project pro04 spring cloud fegin Consumer
① In POM Adding dependencies to XML

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.tianfei</groupId>
            <artifactId>pro02-spring-cloud-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>


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

Since Feign dependencies have been added to the Common project, and Feign dependencies already contain Ribbon dependencies, according to the transitivity of dependencies, Ribbon dependencies do not need to be added to the Consumer project

② Add startup class SpringCloudFeignConsumer

// Enable client features
@EnableFeignClients
@SpringBootApplication
public class SpringCloudFeignConsumer {

	public  static void main(String[] args) {
		
		SpringApplication.run(SpringCloudFeignConsumer.class, args);
	}
}

③ Create Controller for new Consumer project

@RestController
public class FeignHumanResourceController {

    // Assemble the interface to call the remote microservice, and then use it like calling the local method
    @Autowired
    EmployeeRemoteService employeeRemoteService;

    @RequestMapping("/feign/consumer/get/employee")
    public Employee getRemoteEmployee(){

        return employeeRemoteService.getEmployeeRemote();
    }
}

④ Create application. In the resource directory YML configuration file and do the following configuration

server:
  port: 6000

spring:
  application:
    name: com-feign-consumer

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:5000/eureka/

⑤ Access the page to get the returned data

3. Transmission parameter

1. Simple type
① common interface

// @FeignClient annotation indicates that the current interface corresponds to a Provider. The value attribute in the annotation specifies the microservice name of the Provider to be called
@FeignClient( value = "com-provider")
public interface EmployeeRemoteService {

		@RequestMapping("/provider/get/employee/by/id") 
		public Employee getEmployeeById(@RequestParam("empId") Integer empId);
}

Don't forget to write the @ RequestParam annotation

② controller method of provider:

@RestController
public class EmployeeController {

		@RequestMapping("/provider/get/employee/by/id") 
		public Employee getEmployeeById(@RequestParam("empId") Integer empId) { 
				return new Employee(empId, "tom999", 999.99); 
		}
}

The method declaration part shall be consistent with that in the interface

2. Complex type
① Writing method of interface in common

// @FeignClient annotation indicates that the current interface corresponds to a Provider. The value attribute in the annotation specifies the microservice name of the Provider to be called
@FeignClient( value = "com-provider")
public interface EmployeeRemoteService {

		@RequestMapping("/provider/save/emp") 
		public Employee saveEmp(@RequestBody Employee employee);
}

Don't forget to write @ RequestBody annotation

② controller method of provider:

@RestController
public class EmployeeController {

		@RequestMapping("/provider/save/emp") 
		public Employee saveEmp(@RequestBody Employee employee) {
		 		return employee; 
		 }
}

The method declaration part shall be consistent with that in the interface

Keywords: Distribution Spring Cloud

Added by akmalsiddique on Fri, 14 Jan 2022 07:44:55 +0200