SpringCloud


在这里插入图片描述

1 基本组件

注册中心:Eureka
负载均衡:Ribbon
声明式调用远程方法:Feign
熔断、降级、监控:Hystrix
网关:Zuul
在这里插入图片描述

2 使用版本

在这里插入图片描述

3 目标 1:准备基础测试环境

3.1结构

在这里插入图片描述

3.2创建父工程

在这里插入图片描述

配置依赖管理

<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">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.atguigu.spring.cloud</groupId>
	<artifactId>pro06-spring-cloud-parent</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>

	<dependencyManagement>
		<dependencies>
			<!-- 导入SpringCloud需要使用的依赖信息 -->
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Greenwich.SR2</version>
				<type>pom</type>
				<!-- import依赖范围表示将spring-cloud-dependencies包中的依赖信息导入 -->
				<scope>import</scope>
			</dependency>
			<!-- 导入SpringBoot需要使用的依赖信息 -->
			<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>

	<modules>
		<module>pro07-spring-cloud-common</module>
		<module>pro08-spring-cloud-provider</module>
		<module>pro09-spring-cloud-consumer</module>
		<module>pro10-spring-cloud-eureka</module>
	</modules>
</project>

3.3创建通用工程

  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.atguigu.spring.cloud</groupId>
    <artifactId>pro06-spring-cloud-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>pro07-spring-cloud-common</artifactId>
</project>
package com.atguigu.spring.cloud.entity;

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;
	}

	@Override
	public String toString() {
		return "Employee [empId=" + empId + ", empName=" + empName + ", 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;
	}

}

3.4创建提供者工程

<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">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.atguigu.spring.cloud</groupId>
		<artifactId>pro06-spring-cloud-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>pro08-spring-cloud-provider</artifactId>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.atguigu.spring.cloud</groupId>
			<artifactId>pro07-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>
</project>

创建主启动类:

package com.atguigu.spring.cloud;

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

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

}

创建application.yml配置文件:

server:
  port: 1000
  
spring:
  application:
    name: atguigu-provider    # 指定当前微服务名称,以便将来通过微服务名称调用当前微服务时能够找到
  
eureka:
  client:
    service-url:    # 配置当前微服务作为Eureka客户端访问Eureka服务器端时使用的地址
      defaultZone: http://localhost:5000/eureka

创建handler类和方法:

package com.atguigu.spring.cloud.handler;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.atguigu.spring.cloud.entity.Employee;

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

}


3.5创建消费者工程

加入如下依赖信息:

<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">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.atguigu.spring.cloud</groupId>
		<artifactId>pro06-spring-cloud-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>pro09-spring-cloud-consumer</artifactId>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.atguigu.spring.cloud</groupId>
			<artifactId>pro07-spring-cloud-common</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>
</project>

创建主启动类:

package com.atguigu.spring.cloud;

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

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

}

创建配置类提供RestTemplate:

package com.atguigu.spring.cloud.config;

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

@Configuration
public class AtguiguSpringCloudConfig {
	
	@Bean
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}

}

创建handler类:

package com.atguigu.spring.cloud.handler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.atguigu.spring.cloud.entity.Employee;

@RestController
public class HumanResourceHandler {
	
	@Autowired
	private RestTemplate restTemplate;
	
	@RequestMapping("/consumer/get/employee")
	public Employee getEmployeeRemote() {
		
		// 1.声明远程微服务的主机地址加端口号
		String host = "http://localhost:1000";
		
		// 2.声明具体要调用的功能的URL地址
		String url =  "/provider/get/employee/remote";
		
		// 3.通过RestTemplate调用远程微服务
		return restTemplate.getForObject(host + url, Employee.class);
	}

}

创建application.yml配置文件:

server:
  port: 4000

4目标2:创建Eureka注册中心

4.1子目标1:创建Eureka注册中心工程

加入如下依赖信息:

<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">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.atguigu.spring.cloud</groupId>
		<artifactId>pro06-spring-cloud-parent</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>pro10-spring-cloud-eureka</artifactId>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>
	</dependencies>
</project>

创建主启动类:

package com.atguigu.spring.cloud;

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

// 启用Eureka服务器端功能
@EnableEurekaServer
@SpringBootApplication
public class AtguiguMainType {
	
	public static void main(String[] args) {
		SpringApplication.run(AtguiguMainType.class, args);
	}

}

创建application.yml:

server:
  port: 5000

eureka:
  instance:
    hostname: localhost         # 配置当前Eureka服务的主机地址
  client:
    register-with-eureka: false # 当前服务本身就是注册中心,不必“自己注册自己”
    fetch-registry: false       # 当前服务本身就是注册中心,不必“从注册中心取回信息”
    service-url:                # 客户端(指consumer、provider)访问当前注册中心时使用的地址
      defaultZone: http://${eureka.instance.hostname}/${server.port}/eureka

※关于相关注解较低版本需要使用@EnableEurekaClient注解。稍高版本也可以使用@EnableDiscoveryClient注解。当前版本可以省略。
注册的效果:
在这里插入图片描述
这里显示UNKOWN是因为provider工程没有指定应用名称,指定应用名称配置方式如下:

spring:
	application:
		name:atguigu-provider

重启provider后,再查看注册情况:
在这里插入图片描述
以后在SpringCloud环境下开发,每一个微服务工程都要设置一个应用名称。

5目标3:consumer访问provider时使用微服务名称代替localhost:1000

5.1分析

在这里插入图片描述

5.2操作

在consumer工程加入如下依赖:

<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>

在application.yml中加入如下配置:

server:
  port: 4000
spring:
  application:
    name: atguigu-consumer
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:5000/eureka/

在RestTemplate的配置方法处使用@LoadBalanced注解:

package com.atguigu.spring.cloud.config;
@Configuration
public class AtguiguSpringCloudConfig {

	// 这个注解让RestTemplate有负载均衡功能,通过调用Ribbon访问Provider集群
	@LoadBalanced
	@Bean
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}

}

修改consumer工程的handler方法:

package com.atguigu.spring.cloud.handler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.atguigu.spring.cloud.entity.Employee;

@RestController
public class HumanResourceHandler {
	
	@Autowired
	private RestTemplate restTemplate;
	
	@RequestMapping("/consumer/ribbon/get/employee")
	public Employee getEmployeeRemote() {
		
		// 1.声明远程微服务的主机地址加端口号
		// String host = "http://localhost:1000";
		
		// 将远程微服务调用地址从“IP地址+端口号”改成“微服务名称”
		String host = "http://atguigu-provider";
		
		// 2.声明具体要调用的功能的URL地址
		String url =  "/provider/get/employee/remote";
		
		// 3.通过RestTemplate调用远程微服务
		return restTemplate.getForObject(host + url, Employee.class);
	}

}

6目标4:provider以集群方式启动

6.1修改provider的handler方法

@RequestMapping("/provider/get/employee/remote")
public Employee getEmployeeRemote(HttpServletRequest request){//获取当前Web应用的端口号
	intserverPort=request.getServerPort();
	return newEmployee(555,"tom555-"+serverPort,555.55);}

6.2provider以集群方式启动

按照端口号1000启动第一个实例
按照端口号2000启动第二个实例
按照端口号3000启动第三个实例

6.3consumer正常访问

在这里插入图片描述

6.4注意

provider的微服务名称必须使用同一个名称才能构成一个集群,否则将不会认定为是属于同一个集群。

7目标5:使用Feign实现远程方法声明式

调用

7.1分析

在这里插入图片描述

7.2操作

7.2.1common工程

引入如下依赖:

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

创建远程调用方法的接口:

@FeignClient("atguigu-provider")
public interface EmployeeRemoteService {
@RequestMapping("/provider/get/employee/remote")
public Employee getEmployeeRemote();
}

7.2.2新建Feign-consumer工程

在这里插入图片描述
加入如下依赖:

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.atguigu.spring.cloud</groupId>
<artifactId>pro43-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>

主启动类:

//启用Feign客户端功能
@EnableFeignClients
@SpringBootApplication
public class AtguiguMainType{
public static void main(String[]args){
SpringApplication.run(AtguiguMainType.class,args);
}
}

application.yml

server:
	port:7000
spring:
	application:
		name:atguigu-feign-consumer
eureka:
	client:
		serviceUrl:
			defaultZone:http://localhost:5000/eureka/		

handler类:

@RestController
public class EmployeeFeignHandler { 
	@Autowired
	private EmployeeRemoteService employeeRemoteService; 
	@RequestMapping("/feign/consumer/get/emp")
	public EmployeegetEmployeeRemote(){
		return employeeRemoteService.getEmployeeRemote();
		}}

7.3传参

7.3.1简单类型

接口写法:

@RequestMapping("/provider/get/employee/by/id")
public EmployeegetEmployeeById(@RequestParam("empId")IntegerempId);

别忘了写@RequestParam注解
provider的handler方法:

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

方法声明部分和接口中一致

7.3.2复杂类型

接口写法:

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

别忘了写@RequestBody
注解provider的handler方法:

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

方法声明部分和接口中一致

8Hystrix

8.1分布式系统面临的问题

在这里插入图片描述
在微服务架构体系下,服务间的调用错综复杂,交织成一张大网。如果其中某个节点突然无法正常工作,则访问它的众多服务都会被卡住,进而有更多服务被卡住,系统中的线程、CPU、内存等资源有可能被迅速耗尽,最终整个服务体系崩溃。
我们管这样的现象叫服务雪崩。

8.2Hytrix介绍

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
Hytrix能够提供服务降级、服务熔断、服务限流、接近实时的监控等方面的功能。

8.3服务熔断机制

熔断机制是应对雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速响应错误信息。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。
在这里插入图片描述

8.3.1依赖信息

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

8.3.2主启动类注解

//启用断路器功能
@EnableCircuitBreaker
@SpringBootApplication
public class AtguiguMainType{
	public static void main(String[] args){
		SpringApplication.run(AtguiguMainType.class,args);}}

8.3.3ResultEntity

package com.atguigu.spring.cloud.util;

/**
 * 整个项目统一使用这个类型作为Ajax请求或远程方法调用返回响应的数据格式
 * @author Lenovo
 *
 * @param <T>
 */
public class ResultEntity<T> {
	
	public static final String SUCCESS = "SUCCESS";
	public static final String FAILED = "FAILED";
	public static final String NO_MESSAGE = "NO_MESSAGE";
	public static final String NO_DATA = "NO_DATA";
	
	/**
	 * 操作成功,不需要返回数据
	 * @return
	 */
	public static ResultEntity<String> successWithoutData() {
		return new ResultEntity<String>(SUCCESS, NO_MESSAGE, NO_DATA);
	}
	
	/**
	 * 操作成功,需要返回数据
	 * @param data
	 * @return
	 */
	public static <E> ResultEntity<E> successWithData(E data) {
		return new ResultEntity<>(SUCCESS, NO_MESSAGE, data);
	}
	
	/**
	 * 操作失败,返回错误消息
	 * @param message
	 * @return
	 */
	public static <E> ResultEntity<E> failed(String message) {
		return new ResultEntity<>(FAILED, message, null);
	}
	
	private String result;
	private String message;
	private T data;
	
	public ResultEntity() {
		
	}

	public ResultEntity(String result, String message, T data) {
		super();
		this.result = result;
		this.message = message;
		this.data = data;
	}

	@Override
	public String toString() {
		return "ResultEntity [result=" + result + ", message=" + message + ", data=" + data + "]";
	}

	public String getResult() {
		return result;
	}

	public void setResult(String result) {
		this.result = result;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}

}

8.3.4handler方法

package com.atguigu.spring.cloud.handler;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.atguigu.spring.cloud.entity.Employee;
import com.atguigu.spring.cloud.util.ResultEntity;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@RestController
public class EmployeeHandler {
	
	private Logger logger = LoggerFactory.getLogger(EmployeeHandler.class);
	
	// @HystrixCommand注解指定当前方法出问题时调用的备份方法(使用fallbackMethod属性指定)
	@HystrixCommand(fallbackMethod = "getEmpWithCircuitBreakerBackup")
	@RequestMapping("/provider/get/emp/with/circuit/breaker")
	public ResultEntity<Employee> getEmpWithCircuitBreaker(@RequestParam("signal") String signal) throws InterruptedException {
		
		if("quick-bang".equals(signal)) {
			throw new RuntimeException();
		}
		
		if("slow-bang".equals(signal)) {
			Thread.sleep(5000);
		}
		
		return ResultEntity.successWithData(new Employee(666, "empName666", 666.66));
	}
	
	public ResultEntity<Employee> getEmpWithCircuitBreakerBackup(@RequestParam("signal") String signal) {
		
		String message = "方法执行出现问题,执行断路 signal="+signal;
		
		return ResultEntity.failed(message);
	}
	
	@RequestMapping("/provider/get/emp/list/remote")
	public List<Employee> getEmpListRemote(String keyword) {
		
		logger.info("keyword="+keyword);
		
		List<Employee> empList = new ArrayList<>();
		empList.add(new Employee(33, "empName33", 333.33));
		empList.add(new Employee(44, "empName44", 444.44));
		empList.add(new Employee(55, "empName55", 555.55));
		
		return empList;
	}
	
	@RequestMapping("/provider/get/employee/remote")
	public Employee getEmployeeRemote() {
		
		return new Employee(555, "tom555 ", 555.55);
	}
	
//	@RequestMapping("/provider/get/employee/remote")
//	public Employee getEmployeeRemote(HttpServletRequest request) {
//		
//		// 获取当前服务的端口号
//		int serverPort = request.getServerPort();
//		
//		return new Employee(555, "tom555 "+serverPort, 555.55);
//	}

}

8.4服务降级机制

服务降级处理是在客户端(Consumer端)实现完成的,与服务端(Provider端)没有关系。当某个Consumer访问一个Provider却迟迟得不到响应时执行预先设定好的一个解决方案,而不是一直等待。
在这里插入图片描述

8.4.1common工程:依赖

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

8.4.2common工程:FallbackFactory

package com.atguigu.spring.cloud.factory;

import java.util.List;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;

import com.atguigu.spring.cloud.api.EmployeeRemoteService;
import com.atguigu.spring.cloud.entity.Employee;
import com.atguigu.spring.cloud.util.ResultEntity;

import feign.hystrix.FallbackFactory;

/**
 * 1.实现Consumer端服务降级功能
 * 2.实现FallbackFactory接口时要传入@FeignClient注解标记的接口类型
 * 3.在create()方法中返回@FeignClient注解标记的接口类型的对象,当Provider调用失败后,会执行这个对象的对应方法
 * 4.这个类必须使用@Component注解将当前类的对象加入IOC容器,当然当前类必须能够被扫描到
 * @author Lenovo
 *
 */
@Component
public class MyFallBackFactory implements FallbackFactory<EmployeeRemoteService> {

	@Override
	public EmployeeRemoteService create(Throwable cause) {
		return new EmployeeRemoteService() {
			
			@Override
			public Employee getEmployeeRemote() {
				return null;
			}
			
			@Override
			public ResultEntity<Employee> getEmpWithCircuitBreaker(String signal) {
				return ResultEntity.failed("降级机制生效:" + cause.getMessage());
			}
			
			@Override
			public List<Employee> getEmpListRemote(String keyword) {
				return null;
			}
		};
	}

}

8.4.3common工程:Feign接口

//在@FeignClient注解中增加fallbackFactory属性
//指定consumer调用provider时如果失败所采取的备用方案
//fallbackFactory指定FallbackFactory类型的类,保证备用方案返回相同类型的数据
@FeignClient(value="atguigu-provider",fallbackFactory=MyFallBackFactory.class)
public interface EmployeeRemoteService{
……

8.4.4consumer工程:application.yml

feign:
	hystrix:
		enabled:true

8.4.5测试

正常访问:
在这里插入图片描述

8.5监控

8.5.1provider工程

加入如下依赖:

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

配置application.yml

management.endpoints.web.exposure.include:hystrix.stream

8.5.2监控工程

在这里插入图片描述

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
//启用Hystrix仪表盘功能
@EnableHystrixDashboard
@SpringBootApplication
public class AtguiguMainType{
	public static void main(String[]args){
		SpringApplication.run(AtguiguMainType.class,args);}}
server:
	port:8000
spring:
	application:
		name:atguigu-dashboard

8.5.3查看监控数据

直接查看监控数据本身http://localhost:3000/actuator/hystrix.stream
说明1:http://localhost:3000访问的是被监控的provider工程
说明2:/actuator/hystrix.stream是固定格式
说明3:如果从provider启动开始它的方法没有被访问过,那么显示的数据只有“ping:”,要实际访问一个带熔断功能的方法才会有实际数据。通过仪表盘工程访问监控数据
第一步:打开仪表盘工程的首页
http://localhost:8000/hystrix
第二步:填入获取监控数据的地址(上面直接查看时使用的地址)
在这里插入图片描述
在这里插入图片描述

9 Zuul网关

在这里插入图片描述

不同的微服务一般有不同的网络地址,而外部的客户端可能需要调用多个服务的接口才能完成一个业务需求。比如一个电影购票的手机APP,可能会调用电影分类微服务,用户微服务,支付微服务等。如果客户端直接和微服务进行通信,会存在以下问题:
客户端会多次请求不同微服务,增加客户端的复杂性
存在跨域请求,在一定场景下处理相对复杂
认证复杂,每一个服务都需要独立认证
难以重构,随着项目的迭代,可能需要重新划分微服务,如果客户端直接和微服务通信,那么重构会难以实施
某些微服务可能使用了其他协议,直接访问有一定困难
Zuul包含了对请求的路由和过滤两个最主要的功能:
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。
Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的信息,也即以后的访问微服务都是通过Zuul跳转后获得。
总体来说,Zuul提供了代理、路由和过滤的功能。
在这里插入图片描述

9.1创建Zuul工程

在这里插入图片描述
加入如下依赖:

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

配置applicaton.yml

server:
	port:9000
spring:
	application:
		name:zuul-gateway
eureka:
	client:
	serviceUrl:defaultZone:http://localhost:5000/eureka/

主启动类

//启用Zuul代理功能
@EnableZuulProxy
@SpringBootApplication
public class AtguiguMainType{
	public static void main(String[]args){
		SpringApplication.run(AtguiguMainType.class,args);}}

9.2访问测试

9.2.1初步访问

在这里插入图片描述

9.2.2使用指定地址代替微服务名称

zuul:
	routes:
		employee:	#自定义路由规则的名称,在底层的数据结构中是Map的键
			serviceId:atguigu-feign-consumer	#目标微服务名称,ZuulRoute类型的一个属性
			path:/zuul-emp/**	#用来代替目标微服务名称的路径,ZuulRoute类型的一个属性

		#/**表示匹配多层路径,如果没有加/**则不能匹配后续的多层路径了

效果:使用微服务名称和新配置的地址都可以访问http://localhost:9000/atguigu-feign-consumer/feign/consumer/get/emp
http://localhost:9000/zuul-emp/feign/consumer/get/emp

9.2.3让用户不能通过微服务名称访问

zuul:
	ignored-services:	#忽略指定微服务名称,让用户不能通过微服务名称访问
	-atguigu-feign-consumer
	routes:
		employee:	#自定义路由规则的名称,在底层的数据结构中是Map的键
			serviceId:atguigu-feign-consumer	#目标微服务名称,ZuulRoute类型的一个属性
			path:/zuul-emp/**	#用来代替目标微服务名称的路径,ZuulRoute类型的一个属性
				#/**表示匹配多层路径,如果没有加/**则不能匹配后续的多层路径了

效果:微服务名称不能访问,只有新配置的地址可以访问http://localhost:9000/atguigu-feign-consumer/feign/consumer/get/emphttp://localhost:9000/zuul-emp/feign/consumer/get/emp

9.2.4忽略所有微服务名称

zuul:
#ignored-services:忽略指定微服务名称,让用户不能通过微服务名称访问
#-atguigu-feign-consumer
	ignored-services:'*'#忽略所有微服务名称
	routes:
		employee:	#自定义路由规则的名称,在底层的数据结构中是Map的键	
			serviceId:atguigu-feign-consumer	#目标微服务名称,ZuulRoute类型的一个属性
			path:/zuul-emp/**	#用来代替目标微服务名称的路径,ZuulRoute类型的一个属性
			#/**表示匹配多层路径,如果没有加/**则不能匹配后续的多层路径了

9.2.5给访问路径添加统一前缀

zuul:
	#ignored-services:	忽略指定微服务名称,让用户不能通过微服务名称访问
	#-atguigu-feign-consumer
	ignored-services:'*'	#忽略所有微服务名称
	prefix:/maomi	#给访问路径添加统一前缀
	routes:
		employee:	#自定义路由规则的名称,在底层的数据结构中是Map的键							
			serviceId:atguigu-feign-consumer	#目标微服务名称,ZuulRoute类型的一个属性
			path:/zuul-emp/**	#用来代替目标微服务名称的路径,ZuulRoute类型的一个属性
			#/**表示匹配多层路径,如果没有加/**则不能匹配后续的多层路径了

http://localhost:9000/maomi/zuul-emp/feign/consumer/get/emp

9.3ZuulFilter

package com.atguigu.spring.cloud.filter;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

@Component
public class MyZuulFilter extends ZuulFilter {
	
	Logger logger = LoggerFactory.getLogger(MyZuulFilter.class);

	// 判断当前请求是否要进行过滤
	// 要过滤:返回true,继续执行run()方法
	// 不过滤:返回false,直接放行
	@Override
	public boolean shouldFilter() {
		
		// 获取RequestContext对象
		RequestContext requestContext = RequestContext.getCurrentContext();
		
		// 获取Request对象
		HttpServletRequest request = requestContext.getRequest();
		
		// 判断当前请求参数是否为signal=hello
		String parameter = request.getParameter("signal");
		
		return "hello".equals(parameter);
	}

	@Override
	public Object run() throws ZuulException {
		
		logger.info("当前请求要进行过滤,run()方法执行了");
		
		// Current implementation ignores it.
		// 当前实现会忽略这个方法的返回值,所以返回null,不做特殊处理
		return null;
	}

	@Override
	public String filterType() {
		
		// 返回当前过滤器的类型,决定当前过滤器在什么时候执行
		// pre表示在目标微服务前执行
		String filterType = "pre";
		
		return filterType;
	}

	@Override
	public int filterOrder() {
		return 0;
	}

}


9.4使用Zuul进行用户是否登录的检查大致方案

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud是一个用于构建分布式系统的开发工具集合。它提供了一些常用的组件和框架,包括服务注册和发现、负载均衡、断路器、分布式配置等等。在使用Spring Cloud时,有一些常见的错误和注意事项需要注意。 首先,关于Spring Boot和Spring Cloud版本对应错误。在使用Spring Cloud时,需要确保Spring Boot和Spring Cloud的版本兼容。不同版本之间可能存在依赖冲突或不兼容的情况,因此需要根据官方文档或者相关文档来选择合适的版本。 另外,Spring Cloud Config是一个用于集中管理和动态获取配置的工具。它支持从Git、SVN或本地文件系统中获取配置文件,并提供了服务器和客户端支持。你可以通过官方使用说明文档了解更多关于Spring Cloud Config的详细信息。 此外,关于选择使用Nacos还是Eureka作为服务注册和发现组件的问题。Nacos是一个功能更强大的服务注册和发现组件,它整合了Spring Cloud Eureka、Spring Cloud Config和Spring Cloud Bus的功能。使用Nacos可以实现配置的中心动态刷新,而不需要为配置中心新增集群或使用消息队列。另一方面,Eureka是Spring Cloud原生全家桶的一部分,相对来说更加稳定一些。选择使用哪个组件需要根据具体的需求和项目特点来决定。 综上所述,Spring Cloud是一个用于构建分布式系统的开发工具集合,它提供了一些常用的组件和框架。在使用Spring Cloud时,需要注意Spring Boot和Spring Cloud版本的兼容性,并可以使用Spring Cloud Config来动态获取配置。同时,可以选择使用Nacos或Eureka作为服务注册和发现组件,具体选择需要根据项目需求来决定。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值