SpringCloud介绍
概念
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
为什么使用
Spring Cloud对于中小型互联网公司来说是一种福音,因为这类公司往往没有实力或者没有足够的资金投入去开发自己的分布式系统基础设施,使用Spring Cloud一站式解决方案能在从容应对业务发展的同时大大减少开发成本。
应用
Spring Cloud Netflix项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用提供了自配置的Netflix OSS整合。通过一些简单的注解,开发者就可以快速的在应用中配置一下常用模块并构建庞大的分布式系统。它主要提供的模块包括:服务发现(Eureka),断路器(Hystrix),智能路由(Zuul),客户端负载均衡(Ribbon)等。
Spring Cloud是分布式系统的整体解决方案
-
SpringBoot&Spring什么关系?
SpringBoot底层就是Spring,简化使用Spring的方式而已,多加了好多的自动配置; -
Spring Cloud&SpringBoot什么关系?
Spring Cloud是分布式系统的整体解决方案,底层用的SpringBoot来构建项目,Cloud新增很多的分布式的starter,包括这些starter的自动配置;
SpringCloud-HelloWorld架构图
SpringCloud-HelloWorld案例开发-注册
https://waylau.com/eureke-server-register-and-server-discovery/
SpringCloud-HelloWorld案例开发-电影服务
- 电影服务
(jar工程,提供查询电影功能)cloud-provider-movie
- 引入eureka-Discovery、web模块
<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>
- 创建Movie实体类,增加id,movieName属性
- 创建MovieDao
@Repository
public class MovieDao {
public Movie getNewMovie(){
Movie movie = new Movie();
movie.setId(1);
movie.setMovieName("战狼");
return movie;
}
}
- 创建MovieService
@Service
public class MovieService {
@Autowired
MovieDao movieDao;
public Movie getNewMovie(){
return movieDao.getNewMovie();
}
}
- 创建MovieController
@RestController
public class MovieController {
@Autowired
MovieService movieService;
/**
* 获取最新电影
*/
@GetMapping("/movie")
public Movie getNewMovie(){
return movieService.getNewMovie();
}
}
- 编写application.yml
spring:
application:
name: cloud-provider-movie
server:
port: 8000
# 指定注册到哪个注册中心
eureka:
client:
service-url:
defaultZone: <u>http://</u><u>localhost</u><u>:8761/eureka/</u>
instance:
prefer-ip-address: true #注册自己服务使用ip的方式
- 将自己自动注册到注册中心@EnableDiscoveryClient
SpringCloud-HelloWorld案例开发-用户服务(与上面类似)
SpringCloud-HelloWorld案例开发-Ribbon-RestTemplate
-
Ribbon负载均衡,可以用于远程调用(用户服务 调用 电影服务 项目)
如何使用Ribbon
1)、引入Ribbon的Starter
2)、配置使用Ribbon功能;底层使用 RestTemplate 的工具来给远程发送请求 -
用户服务项目中引入Ribbon
<!-- 引入ribbon实现远程调用和负载均衡功能 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
- RestTemplate
@LoadBalanced //负载均衡
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
- 使用RestTemplate远程调用(UserService中完善代码)
@Autowired
RestTemplate restTemplate;
/**
* 购买最新的电影票
* 传入用户id
*/
public Map<String, Object> buyMovie(Integer id){
Map<String, Object> result = new HashMap<>();
//1、查询用户信息
User user = getUserById(id);
//2、查到最新电影票 restTemplate使用java代码来模拟发请求
Movie movie = restTemplate.getForObject("http://CLOUD-PROVIDER-MOVIE/movie", Movie.class);
result.put("user", user);
result.put("movie", movie);
return result;
}
SpringCloud-HelloWorld案例开发-Feign-声明式调用
- 创建新User项目cloud-consumer-user-feign,引入eureka-Discovery、web、Feign模块
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 开启@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);
}
}
- 编写application.yml
spring:
application:
name: cloud-consumer-user-feign
server:
port: 7000
eureka:
client:
service-url:
defaultZone: <u>http://localhost:8761/eureka/</u>
instance:
prefer-ip-address: true #注册中心保存我的ip
- 将RestTemplate方式改成Feign方式进行远程调用
package com.atguigu.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import com.atguigu.bean.Movie;
import com.atguigu.feign.exception.MovieFeignExceptionHandlerService;
/**
* 调用指定服务名称 “CLOUD-PROVIDER-MOVIE” 的 @GetMapping("/movie") 映射方法
* 这个方法声明与电影服务端Controller映射的方法声明一致即可。
*/
@FeignClient(value="CLOUD-PROVIDER-MOVIE") //与被调用端的服务名称一致
public interface MovieServiceFeign {
@GetMapping("/movie")
public Movie getNewMovie(); //与被调用服务端的映射方法一致
}
SpringCloud-HelloWorld案例开发-Ribbon+Hystrix组合
- 引入Hystrix
<!-- 引入hystrix进行服务熔断 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 开启断路保护功能@EnableCircuitBreaker
- 方法上标注@HystrixCommand(fallbackMethod="xxx")来指定出错时调用xx方法
/**
* 购买最新的电影票
* 传入用户id
*/
@HystrixCommand(fallbackMethod="hystrix")
public Map<String, Object> buyMovie(Integer id){
Map<String, Object> result = new HashMap<>();
//1、查询用户信息
User userById = getUserById(id);
//2、查到最新电影票 restTemplate使用java代码来模拟发请求
Movie movie = restTemplate.getForObject("http://CLOUD-PROVIDER-MOVIE/movie",
Movie.class);
result.put("user", userById);
result.put("movie", movie);
return result;
}
- 在本类编写xxx方法,方法的参数和原来一样即可
public Map<String, Object> hystrix(Integer id){
User user = new User();
user.setId(-1);
user.setUserName("未知用户");
Movie movie = new Movie();
movie.setId(-100);
movie.setMovieName("无此电影");
Map<String, Object> result = new HashMap<>();
result.put("user", user);
result.put("movie", movie);
return result;
}