简介
Spring Cloud是Spring旗下的项目之一,官网地址:http://projects.spring.io/spring-cloud/
Spring最擅长的就是集成,把世界上最好的框架拿过来,集成到自己的项目中。
Spring Cloud也是一样,它将现在非常流行的一些技术整合到一起,实现了诸如:配置管理,服务发现,智能路由,负载均衡,熔断器,控制总线,集群状态等等功能。其主要涉及的组件包括:
1.Eureka:注册中心
2.Zuul:服务网关
3.Ribbon:负载均衡
4.Feign:服务调用
5.Hystrix:熔断器
版本
Spring Cloud的版本命名比较特殊,因为它不是一个组件,而是许多组件的集合,它的命名是以A到Z为首字母的一些单词组成(其实是伦敦地铁站的名字):
Spring Clound 和Spring Boot版本对应关系
Release Train | Boot Version |
---|---|
Hoxton | 2.2.x |
Greenwich | 2.1.x |
Finchley | 2.0.x |
Edgware | 1.5.x |
Dalston | 1.5.x |
Spring Cloud核心组件:Eureka
Eureka是注册中心 将所有得服务都注册到这个上面
1.这就好比是网约车出现以前,人们出门叫车只能叫出租车。一些私家车想做出租却没有资格,被称为黑车。而很多人想要约车,但是无奈出租车太少,不方便。私家车很多却不敢拦,而且满大街的车,谁知道哪个才是愿意载人的。一个想要,一个愿意给,就是缺少引子,缺乏管理
Eureka做什么?
2.Eureka就好比是滴滴,负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你
同时,服务提供方与Eureka之间通过 “心跳” 机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除。
工作原理图解析
编写EurekaServer
首先要创建一个父工程,在父工程里面创建子工程 在子工程里面引入 这个jar。
Eureka是服务注册中心,只做服务注册;自身并不提供服务也不消费服务。可以搭建Web工程使用Eureka,可以使用Spring Boot方式搭建。
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
在启动类上加上@EnableEurekaServer注解 声明当前应用时Eureka服务
//声明当前应用时Eureka服务 @EnableEurekaServer @SpringBootApplication public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
在resources下创建application.yml
server:
port: 10086
spring:
4. 启动服务,并访问:http://127.0.0.1:10086/
application:
name: eureka-server
eureka:
client:
service-url:
# eureka 服务地址,如果是集群的话;需要指定其它集群eureka地址
defaultZone: HTTP://127.0.0.1:10086/eureka
# 不注册自己
register-with-eureka: false
# 不拉取服务
fetch-registry: false
启动服务,并访问:http://127.0.0.1:10086/
创建一个生产者(user-service)和消费者(consumer-demos)
首先要将生产者创建好并 注册到Eureka
首先在pom文件中引入需要的jar
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
然后在resources中创建好application.yml
spring:
datasource:
#连接数据库
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/bill-manager
application:
#服务名
name: user-service
#模板
thymeleaf:
cache: false
mybatis:
#mybatis扫描
type-aliases-package: com.kkb.entity
mapper-locations: classpath:/mybatis/*.xml
#注册到eureka
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
在中UserApplication 并启动服务 刷新注册中心(eureka) 看是否注册上
@SpringBootApplication
@MapperScan("com.kkb.mapper") //扫描
@EnableDiscoveryClient //注册eureka
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
负载均衡Ribbon
什么是Ribbon:
启动两个服务实例(9091和9092)
启动如下配置
Eureka注册中心的监控面板:
使用Ribbon负载均衡 因为Eureka中已经集成了Ribbon,所以我们无需引入新的依赖。直接修改代码:
在RestTemplate的配置方法上添加 @LoadBalanced 注解
在消费者(consumer-demos)
在消费者中(consumer-demos)的pom文件引入 注册到Eureka 然后开启 负载均衡Ribbon
<!-- Eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
创建application.yml
spring:
application:
name: consumer-demo
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
#消费者 当启动的时候 每隔10秒将会获取一些数据 然后缓存到本地
registry-fetch-interval-seconds: 10
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
ribbon:
ConnectTimeout: 1000 # 连接超时时长
ReadTimeout: 2000 # 数据通信超时时长
MaxAutoRetries: 0 # 当前服务器的重试次数
MaxAutoRetriesNextServer: 0 # 重试多少次服务
OkToRetryOnAllOperations: false # 是否对所有的请求方式都重试
接着创建一个测试负载均衡的实例可以自己调试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = UserConsumerDemoApplication.class)
public class LoadBalanceTest {
@Autowired
RibbonLoadBalancerClient client;
@Test
public void test(){
for (int i = 0; i < 100; i++) {
ServiceInstance instance = this.client.choose("user-service");
System.out.println(instance.getHost() + ":" + instance.getPort());
}
}
}