目录
第三章 SpringCloud-HelloWorld案例开发-注册中心
第四章 SpringCloud-HelloWorld案例开发-电影服务
4.1.1 引入eureka-Discovery、web模块
.1.2 创建Movie实体类,增加id,movieName属性
第五章 SpringCloud-HelloWorld案例开发-用户服务
5.1.1 引入eureka-Discovery、web模块
5.1.2 创建User实体类,增加id,userName属性
第六章 SpringCloud-HelloWorld案例开发-Ribbon-通过RestTemplate进行远程调用
6.1 Ribbon负载均衡,可以用于远程调用(用户服务 调用 电影服务 项目)
6.1.5 在电影服务(MovieService 类)中打印服务端口,方便监控服务执行情况。
第七章 SpringCloud-HelloWorld案例开发-Feign-声明式调用
7.2 创建新User项目cloud-consumer-user-feign,引入eureka-Discovery、web、Feign模块
7.2.1开启@EnableDiscoveryClient服务发现
7.2.3 复制用户服务项目的代码:实体类,Dao,Service,Controller
7.2.4 将RestTemplate方式改成Feign方式进行远程调用
第八章 SpringCloud-HelloWorld案例开发-Ribbon+Hystrix组合
8.2 使用Ribbon+Hystrix组合(Rest调用方式):cloud-consumer-user
8.2.2 开启断路保护功能@EnableCircuitBreaker
8.2.3 在方法上标注@HystrixCommand(fallbackMethod="xxx")来指定出错时调用xx方法
8.2.5 测试正常调用&停止user服务,测试异常调用&启动user服务过一段时间测试是否正常
8.3 使用Feign+Hystrix组合:cloud-consumer-user-feign
8.3.2 开启断路保护功能@EnableCircuitBreaker
8.3.4 Feign已经集成了Hystrix,使用起来非常简单@FeignClient(name="provider-user",fallback="异常处理类")
8.3.6 测试正常调用&停止user服务,测试异常调用&启动user服务过一段时间测试是否正常
第九章 SpringCloud-HelloWorld案例开发-Hystrix Dashboard
9.1 引入actuator(cloud-consumer-user-feign)
9.1.1 actuator是用来监控SpringBoot服务的,注意路径问题,具体的版本可能不一样,参考启动日志
第一章 SpringCloud介绍
1.1 概念
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
“微服务架构”在这几年非常的火热,以至于关于微服务架构相关的开源产品被反复的提及(比如:netflix、dubbo),Spring Cloud也因Spring社区的强大知名度和影响力也被广大架构师与开发者备受关注。
那么什么是“微服务架构”呢?简单的说,微服务架构就是将一个完整的应用从数据存储开始垂直拆分成多个不同的服务,每个服务都能独立部署、独立维护、独立扩展,服务与服务间通过诸如RESTful API的方式互相调用。
1.2 为什么使用Spring Cloud?
Spring Cloud对于中小型互联网公司来说是一种福音,因为这类公司往往没有实力或者没有足够的资金投入去开发自己的分布式系统基础设施,使用Spring Cloud一站式解决方案能在从容应对业务发展的同时大大减少开发成本。同时,随着近几年微服务架构和Docker容器概念的火爆,也会让Spring Cloud在未来越来越“云”化的软件开发风格中立有一席之地,尤其是在目前五花八门的分布式解决方案中提供了标准化的、全站式的技术方案,意义可能会堪比当前Servlet规范的诞生,有效推进服务端软件系统技术水平的进步。
1.3 应用Spring Cloud
Spring Cloud Netflix项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用提供了自配置的Netflix OSS整合。通过一些简单的注解,开发者就可以快速的在应用中配置一下常用模块并构建庞大的分布式系统。它主要提供的模块包括:服务发现(Eureka),断路器(Hystrix),智能路由(Zuul),客户端负载均衡(Ribbon)等。
1.4 Spring Cloud是分布式系统的整体解决方案
- SpringBoot&Spring什么关系?
SpringBoot底层就是Spring,简化使用Spring的方式而已,多加了好多的自动配置;
2.Spring Cloud&SpringBoot什么关系?
Spring Cloud是分布式系统的整体解决方案,底层用的SpringBoot来构建项目,Cloud新增很多的分布式的starter,包括这些starter的自动配置;
1.5 官方网站
https://projects.spring.io/spring-cloud/#quick-start
SpringCloud中文网:https://springcloud.cc/
第二章 SpringCloud-HelloWorld架构图
我们以一个小型的分布式架构的demo来学习快速入门SpringCloud,很详细,听我娓娓道来~
2.1 案例图解
2.2 注册中心
要将我们所有的服务都注册到服务中心上统一管理
配置Region和Zone
第三章 SpringCloud-HelloWorld案例开发-注册中心
3.1 注册中心
新建一个Springboot项目,名为cloud-eureka-registry-center
3.1.1 引入eureka-server
导入Eureka-Server的启动器
3.1.2 编写application.yml
spring: application: name: cloud-eureka-registry-center //应用的名字
server: port: 8761
eureka: instance: hostname: localhost client: register-with-eureka: false #自己就是注册中心,不用将本服务注册到注册中心上 fetch-registry: false #要不要去注册中心获取其他服务的地址,因为看架构图我们可知是用户服务去调电影服务,所以注册重心没必要获取其他服务器的地址 service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ |
3.1.3 开启Eureka注册中心功能;
在Springboot启动类上标注@EnableEurekaServer
3.1.4 测试
Boot Dashboard视图启动
访问http://localhost:8761
注册中心注册成功!
Eureka入门配置成功!
第四章 SpringCloud-HelloWorld案例开发-电影服务
4.1 电影服务
创建一个Springboot项目,名为cloud-provider-movie
4.1.1 引入eureka-Discovery、web模块
这里引入的eureka的client,因为我们要进行服务注册。
<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-client</artifactId> </dependency> |
.1.2 创建Movie实体类,增加id,movieName属性
4.1.3 创建MovieDao
@Repository public class MovieDao { public Movie getMovieById(Integer id){ Movie movie = new Movie(); movie.setId(id); movie.setName("流浪地球-"+id); return movie; } } |
4.1.4 创建MovieService
@Service public class MovieService { @Autowired MovieDao movieDao; public Movie getMovieById(Integer id){ return movieDao.getMovieById(id); } } |
4.1.5 创建MovieController
@RestController public class MovieController { @Autowired MovieService movieService; @RequestMapping("/movie/{id}") public Movie getMovieById(@PathVariable("id") Integer id){ return movieService.getMovieById(id); } } |
4.1.6 启动测试
http://localhost:8080/movie/1,与注册中心无关,注册中心无此服务
4.1.7 编写application.yml
spring: application: name: cloud-provider-movie
server: port: 8000
# 指定注册到哪个注册中心 eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ instance: prefer-ip-address: true #注册自己服务使用ip的方式 |
4.1.8 将自己自动注册到注册中心
在该服务的启动类上标注@EnableDiscoveryClient,启用
4.1.9 启动注册中心和服务
查看注册中心,访问服务 http://localhost:8761
服务注册成功。
第五章 SpringCloud-HelloWorld案例开发-用户服务
5.1 用户服务
创建springboot项目,cloud-consumer-user
5.1.1 引入eureka-Discovery、web模块
依然引入eureka-client和web模块
5.1.2 创建User实体类,增加id,userName属性
5.1.3 创建UserDao
@Repository public class UserDao { public User getUserById(Integer id){ User user = new User(id,"席剑"); return user; } } |
5.1.4 创建UserService
拷贝Movie类
@Service public class UserService { @Autowired UserDao userDao; public User getUserById(Integer id){ return userDao.getUserById(id); } } |
5.1.5 创建UserController
@RestController public class UserController { @Autowired UserService userService; @RequestMapping("/user/{id}") public User getUserById(@PathVariable("id") Integer id){ return userService.getUserById(id); } } |
5.1.6 编写application.yml
spring: application: name: cloud-consumer-user
server: port: 9000
eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ instance: prefer-ip-address: true #注册中心保存我的ip |
5.1.7 将自己自动注册到注册中心
springboot启动类上标注 :@EnableDiscoveryClient
5.1.8 启动注册中心和服务,查看注册中心,访问服务
http://localhost:8761 查看eureka,发现该服务注册成功
http://localhost:9000/user?id=1 正常访问
第六章 SpringCloud-HelloWorld案例开发-Ribbon-通过RestTemplate进行远程调用
现在服务都注册好后,设计到了我们用户服务对电影服务的远程调用,即在用户服务的controller中添加一个buyMovie方法,进行远程调用Movie服务的功能。
远程调用有两种方式:1.RestTemplate进行远程调用 2.通过Feign进行远程调用
我们先用第一种方式进行远程调用。
6.1 Ribbon负载均衡,可以用于远程调用(用户服务 调用 电影服务 项目)
如何使用Ribbon 1)、引入Ribbon的Starter 2)、配置使用Ribbon功能;底层使用 RestTemplate 的工具来给远程发送请求 3)、当电影服务要集群部署时,要采用负载均衡策略进行轮询,需要引入Ribbon |
6.1.1 用户服务项目中引入Ribbon
<!-- 引入ribbon实现远程调用和负载均衡功能 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> |
6.1.2 RestTemplate
在Springboot的启动类中(或自己写一个配置类),给容器中注入一个RestTemplate并使用Ribbon进行负载均衡调用
@LoadBalanced //负载均衡 @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } |
6.1.3 使用RestTemplate远程调用
远程调用需要返回Movie对象,所以将Movie的bean对象复制到当前项目下
在用户服务的controller中添加buyMovie功能
@Autowired RestTemplate restTemplate; @RequestMapping("/buyMovie/{userId}/{movieId}") public Map<String,Object> buyMovie(@PathVariable("userId") Integer userId, @PathVariable("movieId") Integer movieId){ User user = userService.getUserById(userId); Map<String,Object> map = new HashMap<>(); map.put("user",user); //通过注册中心进行远程调用,通过项目名进行访问,在集群部署的时候可以做负载均衡,所以CLOUD-PROVIDER-MOVIE为注册中心中已经注册的movie服务 Movie movie = restTemplate.getForObject("http://CLOUD-PROVIDER-MOVIE/movie/" + movieId, Movie.class); map.put("movie",movie); return map; } |
6.1.4 启动注册中心和服务,访问服务
http://localhost:9000/buyMovie/1/1 显示用户和电影信息
证明我们的远程调用成功
6.1.5 在电影服务(MovieService 类)中打印服务端口,方便监控服务执行情况。
@Value("${server.port}") String port;
public Movie getMovieById(Integer id){
Movie movie = new Movie();
movie.setId(id);
movie.setName("流浪地球-"+id);
System.out.println("port:"+port);
return movie;
} |
6.1.6 将电影服务项目启动多次,测试负载均衡
将电影服务启动时在传参的时候加上 --server.port=8000
--server.port=8001
启动两个电影服务,测试负载均衡
访问几次,发现确实是两个服务被轮询访问
远程调用、负载均衡配置成功
第七章 SpringCloud-HelloWorld案例开发-Feign-声明式调用
7.1 Feign声明式调用
7.2 创建新User项目cloud-consumer-user-feign,引入eureka-Discovery、web、Feign模块
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> |
7.2.1开启@EnableDiscoveryClient服务发现
/** * 1、引入feign的starter * 2、写一个接口,和被调用的服务关联起来 * 3、开启Feign功能;@EnableFeignClients */ @EnableFeignClients @EnableDiscoveryClient @SpringBootApplication public class CloudConsumerUserFeignApplication { public static void main(String[] args) { SpringApplication.run(CloudConsumerUserFeignApplication.class, args); } } |
7.2.2 编写application.yml
spring: application: name: cloud-consumer-user-feign
server: port: 7000
eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ instance: prefer-ip-address: true #注册中心保存我的ip |
7.2.3 复制用户服务项目的代码:实体类,Dao,Service,Controller
7.2.4 将RestTemplate方式改成Feign方式进行远程调用
//增加一个Feign接口,
@FeignClient(value = "CLOUD-PROVIDER-MOVIE")
public interface MovieServiceFeign {
//方法声明要与被调用接口的controller中的方法一致
@RequestMapping("/movie/{id}")
Movie getMovieById(@PathVariable("id") Integer id);
} |
7.2.5 修改UserController代码
@RestController public class UserController { @Autowired UserService userService; //注入自定义的Feign接口 @Autowired MovieServiceFeign movieServiceFeign; @RequestMapping("/user/{id}") public User getUserById(@PathVariable("id") Integer id){ return userService.getUserById(id); } @RequestMapping("/buyMovie/{userId}/{movieId}") public Map<String,Object> buyMovie(@PathVariable("userId") Integer userId, @PathVariable("movieId") Integer movieId){ User user = userService.getUserById(userId); Map<String,Object> map = new HashMap<>(); map.put("user",user); //直接调用 Movie movie = movieServiceFeign.getMovieById(movieId); map.put("movie",movie); return map; } } |
7.2.6 开启Feign功能
在Springboot启动类上标注@EnableFeignClients
7.2.7 测试调用与负载均衡效果
http://localhost:7000/buyMovie/1/1
一切正常。Feign方式自动集成了Ribbon负载均衡,我们无需配置。
第八章 SpringCloud-HelloWorld案例开发-Ribbon+Hystrix组合
8.1 Hystrix服务熔断
目前情况:如果集群的两个电影服务都挂了,会怎样?
当我们没配置服务熔断时,电影服务全部挂掉,我们就无法正常访问,会跳到错误页面
我们可以使用Hystrix配置一个熔断器,让其就算服务挂掉,也能返回一个虚假的兜底数据,不至于报错。
8.2 使用Ribbon+Hystrix组合(Rest调用方式):cloud-consumer-user
8.2.1 引入Hystrix
<!-- 引入hystrix进行服务熔断 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> |
8.2.2 开启断路保护功能@EnableCircuitBreaker
8.2.3 在方法上标注@HystrixCommand(fallbackMethod="xxx")来指定出错时调用xx方法
@HystrixCommand(fallbackMethod = "buyMovieHystrix")
@RequestMapping("/buyMovie/{userId}/{movieId}")
public Map<String,Object> buyMovie(@PathVariable("userId") Integer userId,
@PathVariable("movieId") Integer movieId){
User user = userService.getUserById(userId);
Map<String,Object> map = new HashMap<>();
map.put("user",user);
Movie movie = restTemplate.getForObject("http://CLOUD-PROVIDER-MOVIE/movie/" + movieId, Movie.class);
map.put("movie",movie);
return map;
}
//调用出错后的熔断方法,除名字外必须与实际方法一致
public Map<String,Object> buyMovieHystrix(@PathVariable("userId") Integer userId,
@PathVariable("movieId") Integer movieId){
Map<String,Object> map = new HashMap<>();
User user = new User(-1,"无此用户");
map.put("user",user);
Movie movie = new Movie(-100,"无此电影");
map.put("movie",movie);
return map;
}
8.2.5 测试正常调用&停止user服务,测试异常调用&启动user服务过一段时间测试是否正常
结论是:当挂掉一台服务器的时候,由于心跳机制,短时间内注册中心还没有发现该服务器已经宕机,访问时依然会轮询这台宕机的服务器,因为我们配置了熔断器,所以访问得到的是兜底数据。
当过了一会后,再次访问,就会发现无论访问多少次,兜底数据都不再存在,是因为注册中心通过心跳机制已识别到该服务器宕机,这时只有一台服务器在线,轮询时只会轮询这一台服务器了。
当我们把第二台服务器也挂掉后,会发现每次访问得到的都是兜底数据,这就是熔断器的功劳。
8.2.6 熔断器原理
8.3 使用Feign+Hystrix组合:cloud-consumer-user-feign
8.3.1 引入Hystrix
<!-- 引入hystrix进行服务熔断 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> |
8.3.2 开启断路保护功能@EnableCircuitBreaker
8.3.3 开启Feign对Hystrix支持
feign: hystrix: enabled: true #默认false |
8.3.4 Feign已经集成了Hystrix,使用起来非常简单@FeignClient(name="provider-user",fallback="异常处理类")
@FeignClient(value = "CLOUD-PROVIDER-MOVIE",fallback = MovieServiceFeignExceptionHandler.class)
public interface MovieServiceFeign {
@RequestMapping("/movie/{id}")
Movie getMovieById(@PathVariable("id") Integer id);
}
写一个异常处理类实现Feign接口
@Component
public class MovieServiceFeignExceptionHandler implements MovieServiceFeign {
@Override
public Movie getMovieById(Integer id) {
Movie movie = new Movie(-1,"无此电影");
return movie;
}
}
当出现异常调用不了时,会调用异常处理类对应的该方法。
8.3.6 测试正常调用&停止user服务,测试异常调用&启动user服务过一段时间测试是否正常
兜底数据返回,测试成功。
这里针对于远程调用的方法进行了熔断处理,而通过Rest调用方式进行的熔断处理是针对于Controller中的方法的,并且熔断方法需要写在Controller层,很不优雅,所以我们重点采用的就是这种Feign+Ribbon+Hystrix的方式。
第九章 SpringCloud-HelloWorld案例开发-Hystrix Dashboard
除了隔离依赖服务的调用以外,Hystrix还提供了近实时的监控,Hystrix会实时、累加地记录所有关于HystrixCommand的执行信息,包括每秒执行多少请求,多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控 |
9.1 引入actuator(cloud-consumer-user-feign)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> |
9.1.1 actuator是用来监控SpringBoot服务的,注意路径问题,具体的版本可能不一样,参考启动日志
9.1.2 可提供的监控服务为
9.2 修改配置文件,暴露数据监控流
management: endpoints: web: exposure: include: hystrix.stream # 访问/actuator/hystrix.stream能看到不断更新的监控流 |
访问/actuator/hystrix.stream 可以看到打印
9.3 引入HystrixDashboard
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency> |