一、什么是SpringCloud
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
那么,SpringCloud有哪些主要的组件呢?先来简单说一下
1、注册中心:Eureka,Nacos
2、负载均衡:Ribbon
3、声明式服务调用:Feign
4、熔断器:Hystrix
5、网关:GateWay
二、注册中心
服务与服务之间的方法相互调用,如果直接通过接口访问是不安全的,如果一方的地址发生变化,那么调用的一方就要修 改地址,耦合性太高,所以就需要使用注册中心作为一个中间件,服务的提供者需要将自己的ip注册到注册中心, 服务的消费者只需要从注册中心拉取对应服务的ip,就可以动态的获取提供者的ip并调用,很好的实现了解耦。
如图所示,A系统要调用B系统的方法,就要将A系统的B系统都注册到eureka中,那么就可以进行跨服务之间的调用,具体需要怎么配置呢?
1、创建eureka注册中心,创建一个SpringBoot项目,配置所需要的依赖包
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com</groupId>
<artifactId>SpringCloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringCloud</name>
<description>Demo</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml配置文件:
#eureka的端口号
server:
port: 8888
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
在启动类上添加注解@EnableEurekaServer表示为eureka注册中心,启动项目
@EnableEurekaServer
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
通过网址:localhost:8888就可以进入注册成功的eureka的页面。
2、将A系统和B系统都注册到eureka注册中心中,同样创建两个Springboot项目,导包方式相同,在这里需要注意的是yml的配置,如何将两个服务都注册进去。
eureka:
client:
serviceUrl:
# eureka的注册中心地址
defaultZone: http://localhost:8888/eureka/
server:
# 此项目端口号
port: 8889
spring:
application:
# 注册进eureka的名字
name: A-server
创建Controller层。
@RestController
public class aController {
@RequestMapping("aTest")
public String aTest(){
return "this is A";
}
}
创建启动类,添加注解。
@EnableEurekaClient
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
启动服务,在此打开eureka页面,发现多了一个A-service的服务,以同样的方式将B-service注册到eureka中:B的端口号8890,B的服务名B-service。
三、负载均衡
ribbon是一个负载均衡客户端,可以很好的控制http和tcp的一些行为,如果A要调用B,在A中添加依赖,在启动类里把ribbon类注入spring:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
// 在启动类里把ribbon类注入spring
@EnableEurekaClient
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
@LoadBalanced // 开启负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
public class AService{
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/ATest")
public String ATest(){
//http://B注册的服务名称/调用B中Controller层的方法路径
String str = restTemplate.getForObject("http://B-server/bTest",String.class);
return str;
}
}
启动服务,调用localhost:8889/ATest
四、声明式服务调用
只需要创建一个接口并注解,Feign默认集成了Ribbon。
-Feign 采用的是基于接口的注解
·Feign 整合了ribbon
导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
1、A中添加Feign依赖,启动类上添加注解@EnableFeignClients
// 启动类
@EnableEurekaClient
@EnableFeignClients
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
2、定义Feign接口,接口添加注解@Service、@FeignClient(value=“调用B注册的服务名称”)。接口返回值、方法名,注解、路径要和B中要调用的方法相同。
@Service
@FeignClient("B-server")
public interface bFeign {
@RequestMapping("/bTest")
public String bTest();
}
3、A中的接口层调用:将Feign接口注入,调用Feign中的方法。
@RestController
public class memController {
@Autowired
private bFeign feign;
@RequestMapping("/aTest")
public String aTest(){
String str = feign.bTest();
return str;
}
}
启动服务,调用localhost:8889/aTest
五、熔断器
为什么需要熔断器:
- 在微服务架构中,服务与服务之间可以相互调用,为了保证高可用,单个服务又要集群部署,由于网络或者自身的原因,服务不可能保证100%可用,如果单个服务有了问题,调用这个服务就会出现网络延迟,这个时候如果有大量的网络涌入,会形成任务累计,导致服务瘫痪,甚至出现雪崩效应,所以需要熔断器。
什么是雪崩效应?应对措施?
- 雪崩效应通俗来讲就是一个方法的RPC调用并发量太大。
- 应对措施:流量控制;服务自动扩容
熔断器作用?
- 断路器机制:当请求后端服务失败的数量达到一定比例的时候,会切换到打开状态,这样所有的请求会直接失败而不会发送到后台的服务中,在一段时间后,会自动切换到半开状态,若通过的请求成功,切换为关闭状态,若失败,继续切换到打开状态
- 资源隔离:熔断器采用资源隔离的方式:将要远程调用的服务放到不同的线程池中,运行环境被隔离开了,如果一个服务挂了,请求会一直发,直到线程容量用完,就不会再调用了,也不会影响其他服务。
六、网关
用于管理客户端发起请求时的路径,一个请求可能会调用多个微服务,如果每个微服务都需要客户端去调用,就增加了客户端的压力,所以需要gateWay组件,用于管理客户端的请求,再由GateWay去调用微服务