springcloud
SpringCloud
1.概念
Spring Cloud
是一系列框架的有序集合。它利用Spring Boot
的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册
、配置中心
、消息总线
、负载均衡
、断路器
、数据监控
等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包
。
“微服务架构”在这几年非常的火热,以至于关于微服务架构相关的开源产品被反复的提及(比如:netflix、dubbo),Spring Cloud也因Spring社区的强大知名度和影响力也被广大架构师与开发者备受关注。
那么什么是“微服务架构”呢?简单的说,微服务架构就是将一个完整的应用从数据存储开始垂直拆分成多个不同的服务,每个服务都能独立部署、独立维护、独立扩展,服务与服务间通过诸如RESTful API的方式互相调用。
eureka
创建注册中心服务
创建SpringBoot工程引入eureka-server
编写配置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/
在启动类上开启Eureka注册中心功能;@EnableEurekaServer
访问http://localhost:8761
创建电影服务
创建springBoot工程引入eureka-Discovery
编写配置类
spring:
application:
name: cloud-provider-movie
server:
port: 8000
# 指定注册到哪个注册中心
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true #注册自己服务使用ip的方式
在启动程序上将自己自动注册到注册中心@EnableDiscoveryClient
添加Controller层,MovieDao. MovieService
查看注册中心,访问服务 http://localhost:8000
创建跟电影服务一样的 -- 用户服务
添加UserDao UserService UserController
配置文件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
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并使用Ribbon进行负载均衡调用
@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;
}
Feign - 声明式调用
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
在启动类中开启@EnableDiscoveryClient服务发现
开启Feign功能@EnableFeignClients
/**
* 1、引入feign的starter
* 2、写一个接口,和被调用的服务关联起来
* 3、开启Feign功能;@EnableFeignClients
*/
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class CloudConsumerUserFeignApplication {
public static void main(String[] args) {
SpringApplication.run(CloudConsumerUserFeignApplication.class, args);
}
}
将RestTemplate方式改成Feign方式进行调用
/**
* 调用指定服务名称 “CLOUD-PROVIDER-MOVIE” 的 @GetMapping("/movie") 映射方法
* 这个方法声明与电影服务端Controller映射的方法声明一致即可。
*/
@FeignClient(value="CLOUD-PROVIDER-MOVIE") //与被调用端的服务名称一致
public interface MovieServiceFeign {
@GetMapping("/movie")
public Movie getNewMovie(); //与被调用服务端的映射方法一致
}
Ribbon + Hystrix
引入Hystrix
引入Hystrix
<!-- 引入hystrix进行服务熔断 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
在RestTemplate中写@HystrixCommand(fallbackMethod="xxx")来指定出错时调用xx方法
@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;
}
在同一个类中编写
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;
}
Feign + Hystrix 组合
在配置中开启Feign对Hystrix的支持
feign:
hystrix:
enabled: true #默认false
/*使用Hystrix进行服务的熔断
* 1)、引入Hystrix的starter
* 2)、开启xxx功能 :@EnableCircuitBreaker
* 3)、@FeignClient(value="CLOUD-PROVIDER-MOVIE",fallback=指定这个接口的异常处理类(异常处理类必须实现这个接口))
*/
@FeignClient(value="CLOUD-PROVIDER-MOVIE",fallback=MovieFeignExceptionHandlerService.class)
public interface MovieServiceFeign {
// 未来这个接口就会调用很多方法,定制每一个方法远程出错如何返回兜底mock数据;
@GetMapping("/movie")
public Movie getNewMovie();
}
fallback="异常处理类"指定的异常处理类实现这个类的接口即可,并且放在容器中
@Component
public class MovieFeignExceptionHandlerService implements MovieServiceFeign{
/**
* 远程这个方法调用出问题就会调用此方法
*/
@Override
public Movie getNewMovie() {
Movie movie = new Movie();
movie.setId(-100);
movie.setMovieName("无此电影呀...");
return movie;
}
}