1.Hystrix断路器
在理想状态下,一个应用依赖的服务都是健康可用的,我们可以正常的处理所有的请求
当某一个服务出现延迟时,所有的请求都阻塞在依赖的服务Dependency I
当依赖I 阻塞时,大多数服务器的线程池就出现阻塞(BLOCK),影响整个线上服务的稳定性
解决方案
方案一:Hystrix实现(服务提供者实现)
创建一个服务提供者模块
pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.zy</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>cn.zy</groupId>
<artifactId>provider_hystrix_8003</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>provider_hystrix_8003</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.zy</groupId>
<artifactId>user_interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--eureka客户端支持 -->
<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-hystrix</artifactId>
</dependency>
</dependencies>
</project>
applicaiton.yml
server:
port: 8003
spring:
application:
name: USER-PROVIDER #不要使用下划线
eureka:
client:
service-url:
defaultZone: http://eureka-7001.com:7001/eureka,http://eureka-7002.com:7002/eureka
instance:
prefer-ip-address: true #显示客户端真实ip
Application.java
package cn.zy.provider_hystrix_8003;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
@SpringBootApplication
@EnableEurekaClient // 表示Eureka的客户端
@EnableHystrix // 断路器
public class ProviderHystrix8003Application {
public static void main(String[] args) {
SpringApplication.run(ProviderHystrix8003Application.class, args);
}
}
controller
@Controller
public class UserController {
@HystrixCommand(fallbackMethod = "failGet")
@ResponseBody
@RequestMapping("/user/{id}")
public User user(@PathVariable("id") Long id){
if (id == 2){
throw new RuntimeException("抛出一个异常");
}
User user = new User();
user.setId(id);
user.setName("xx8003");
return user;
}
// 托底方法
public User failGet(Long id){
User user = new User();
user.setName("找不到用户");
user.setId(id);
return user;
}
}
启动服务并测试
方案二:Feign实现
创建一个服务消费者模块
模块结构
pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.zy</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>cn.zy</groupId>
<artifactId>user_consumer_fegin_hystrix_9003</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>user_consumer_fegin_hystrix_9003</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.zy</groupId>
<artifactId>user_interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--eureka客户端,服务消费者也要从注册中心获取可用服务列表-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--feign的支持-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yml
server:
port: 9003
eureka:
client:
registerWithEureka: false #不注册到Eureka,不在注册中心显示
service-url:
# defaultZone: http://localhost:7001/eureka
defaultZone: http://eureka-7001.com:7001/eureka,http://eureka-7002.com:7002/eureka
feign:
hystrix:
enabled: true #开启熔断支持
client:
config:
remote-service: #服务名,填写default为所有服务
connectTimeout: 3000
readTimeout: 3000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
UserCilent.java
// @FeignClient 调用服务的名字
@FeignClient(value = "USER-PROVIDER",fallback = UserClientFall.class)
public interface UserClient {
@RequestMapping("/user/{id}") //user/1
User getUser(@PathVariable("id") Long id);
}
UserCilentFall.java
@Component
public class UserClientFall implements UserClient {
@Override
public User getUser(Long id) {
User user = new User();
user.setId(id);
user.setName("用户不存在");
return user;
}
}
Application.java
@EnableEurekaClient
@EnableFeignClients(basePackages = "cn.zy.user_consumer_fegin_hystrix_9003.fegin")
@SpringBootApplication
public class UserConsumerFeginHystrix9003Application {
public static void main(String[] args) {
SpringApplication.run(UserConsumerFeginHystrix9003Application.class, args);
}
}
2.zuul路由网关
Zuul 是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet应用。
Zuul 在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门,也要注册入Eureka.
微服务架构体系中,通常一个业务系统会有很多的微服务,比如:OrderService、ProductService、UserService...,为了让调用更简单,一般会在这些服务前端再封装一层,类似下面这样:
前面这一层俗称为“网关层”,其存在意义在于,将"1对N"问题 转换成了"1对1”问题(路由),同时在请求到达真正的微服务之前,可以做一些预处理(过滤),比如:来源合法性检测,权限校验,反爬虫之类...
基本配置
创建zuul_gatewar_9527模块
pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.zy</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>cn.zy</groupId>
<artifactId>zuul_gatewar_9527</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>zuul_gatewar_9527</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<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>
<dependency>
<groupId>cn.zy</groupId>
<artifactId>user_interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml
server:
port: 9527
spring:
application:
name: microservice-zuul
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
Application.java
@SpringBootApplication
@EnableZuulProxy // 路由网管代理
public class ZuulGatewar9527Application {
public static void main(String[] args) {
SpringApplication.run(ZuulGatewar9527Application.class, args);
}
}
启动服务并测试
直接访问地址:http://localhost:8001/user/1
路由访问地址:http://localhost:9527/user-provider/user/2
路由访问映射规则
安全加固:不用服务名,映射路径
忽略原来访问:原来模式不可以访问
加上统一前缀
server:
port: 9527
spring:
application:
name: microservice-zuul
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
zuul:
routes:
user-provider: /user/** #以/user开头的所有路径都转发给user-provider进行处理
ignored-services: "*" #忽略掉服务名访问方式 使用上面/user的方式来访问
prefix: "/services" #添加 前缀访问 localhost:9527/services/user/provider/user/2