SpringBoot和SpringCloud

文章目录

  • SpringBoot
    • 单体应用的优缺点:
    • 微服务架构的特点
  • SpringCloud
    • 相关概念
    • 重构过程
      • 使用RestTemplate调用其他模块的方法
      • 服务注册
      • Ribbon实现负载均衡
      • Feign实现服务消费,负载均衡
      • Zuul实现智能网关
      • Config实现集中配置以及版本管理
      • 消息总线
      • Hystrix实现容错保护
    • 微服务应用Demo
      • Ribbon和Feign的区别:

SpringBoot

单体应用的优缺点:

优点:
易于开发调试,也易于部署,通过负载均衡后端运行多个拷贝也使其易于扩展
缺点:
复杂性高:模块边界模糊,修改bug可能会带来隐含缺陷
技术负债:随着时间推移,“不坏不修”的技术负载越积愈多
部署频率低:每次功能变更都会导致重新部署整个应用,全量部署耗时长,影响范围大,风险高
可靠性差:某个功能出现问题可能会出现连环效应,造成OOM,或整个应用的雪崩
扩展能力受限:不同类型的功能模块不能按需扩展
阻碍技术创新:单体应用使用统一的技术方案解决所有问题,引入新框架相当于重写代码

微服务架构的特点

  1. 每个微服务独立开发,而且只关注某个特定的功能
  2. 每个微服务独立运行在自己的进程里,多个微服务共同构建起整个系统
  3. 微服务之间通过轻量级的通信机制进行通信
  4. 可使用不同语言与数据存储机制
  5. 可实现全自动部署

SpringCloud

SpringCloud是一个基于Spring Boot实现的微服务架构开发工具。

相关概念

  1. 服务注册和发现(Eureka):负责服务发现的。当应用启动时,Eureka Client将服务注册到Eureka Server,而且Eureka Client还可以从Eureka Server拉取注册表,从而知道其他服务在哪里
  2. 配置服务:集中存储所有应用的配置文件。
  3. 路由网关(Zuul):让所有微服务对外暴露一个接口,客户端只需访问一个网关地址,就可以访问到所有微服务。 Zuul支持自动路由映射,SpringCloud使用@EnableZuulPeoxy注解启用路由代理。
  4. 负载均衡(Ribbon+Feign):使用Feign组件构造和发起对其他服务的请求,并进行解析和响应;使用Ribbon组件注入RestTemplate实现负载均衡,每次请求都会通过负载算法在多台机器选择一台
  5. 断路器(Hystrix):进行熔断,降级和隔离,对每个请求构造线程池,实现了服务调用的隔离和容错,避免了级联错误甚至雪崩

重构过程

商品模块——>调用商品模块

使用RestTemplate调用其他模块的方法

okhttp封装了http,是比HttpClient友好易用的工具

# 添加okhttp依赖
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.9.0</version>
</dependency>

注入RequestTemplate对象进行方法调用

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
# 订单模块
@Service
public class ItemService {

    // Spring框架对RESTful方式的http请求做了封装,来简化操作
    @Autowired
    private RestTemplate restTemplate;

    @Value("${myspcloud.item.url}")
    private String itemUrl;

    public Item queryItemById(Long id) {
        return this.restTemplate.getForObject(itemUrl, Item.class);
    }
}

问题:1. 如果有多个商品服务,订单该怎么调用呢
2. 商品服务ip地址变更,订单服务配置文件也要跟着修改

服务注册

Eureka2.0已经闭源了。
a) 服务提供者注册到注册中心
b) 服务消费者从注册中心拉取服务列表,并缓存到本地缓存
c) 消费者根据服务列表调用相应提供者的服务 提供了服务提供者 和 ip地址的映射
d) 客户端通过发送心跳和注册中心保持连接,一旦地址发生变更,注册中心会通知消费者,一旦服务提供者下线,注册中心会将其从服务列表移除

Eureka通过复制机制,心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。客户端缓存机制,即使Eureka挂掉,客户端依然正常运行;应用启动后,会向Eureka Server发送心跳,若超过超时时间,则将其从服务列表移除,

Ribbon实现负载均衡

Ribbon是Netflix发步的负载均衡器,当Ribbon收到服务提供者地址列表后,Ribbon就可以基于某种负载均衡算法,为服务消费者选择某个地址去进行请求。例如轮询,随机和自定义算法。
Ribbon会根据Eureka提供的服务列表选择一个ip发起请求
SpringBoot和SpringCloud_第1张图片

#  注入Template
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
   return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
# http://+ url +/item/
public Item queryItemById(Long id) {
    String serviceId = "app-item";
    List<ServiceInstance> instances = this.discoveryClient.getInstances(serviceId);
    if(instances.isEmpty()){
        return null;
    }
    ServiceInstance serviceInstance = instances.get(0);
    String url = serviceInstance.getHost() + ":" + serviceInstance.getPort();
    return this.restTemplate.getForObject("http://" + url + "/item/" + id, Item.class);
}
# http://+ servicename +/item/,Ribbon会根据Eureka提供的服务列表选择一个ip发起请求
public Item queryItemById(Long id) {
    // 该方法走eureka注册中心调用(这种方式必须先开启负载均衡@LoadBalanced)
    String itemUrl = "http://app-item/item/{id}";
    Item result = restTemplate.getForObject(itemUrl, Item.class, id);
    System.out.println("订单系统调用商品服务,result:" + result);
    return result;
}
#  配置负载均衡策略
app-item:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

Feign实现服务消费,负载均衡

Feign是Netflix开发的Http客户端,整合了Ribbon和Eureka,支持Spring MVC注解或者JAX-RS注解,从而在服务间实现了服务消费 和 负载均衡。
流程分析

  1. 通过@EnableFeignClients启用后,spring扫描@FeignClient注解的接口并生成代理类
  2. Feign根据spring mvc注解的方法生成对应的url,然后根据ribbon的负载均衡去调用具体rest服务
#  定义Ribbon的Restmelate对象,启动负载均衡
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
## 申明这是一个Feign客户端,并且指明服务id
@FeignClient(value = "app-item")
public interface ItemFeignClient {
    @RequestMapping(value = "/item/{id}", method = RequestMethod.GET)
    Item queryItemById(@PathVariable("id") Long id);
}
#  使用Hystrix实现断路器
@Autowired
private ItemFeignClient itemFeignClient;

@HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod")
public Item queryItemById3(Long id) {
    String itemUrl = "http://+ servicename +/item/{id}";
    //Item result = restTemplate.getForObject(itemUrl, Item.class, id);
    Item result = itemFeignClient.queryItemById(id);
    return result;
}

Zuul实现智能网关

服务网关统一向外提供Rest API,具有服务路由,负载均衡,权限控制,日志收集等功能,将公用的业务逻辑迁移到服务器路由层面,维护了服务功能的单一性,使其具备更高的可复用性和可测试性。除此之外,它简化了客户端访问微服务的方式,客户端只需要访问网关一个服务就可以访问到后面所有服务
Zuul是Nerflix开源的微服务网关,可以和Eureka,Ribbon,Hystrix等组件配置使用

  1. 身份认证和授权
  2. 动态路由,自动将请求路由到后端集群
  3. 压力测试,逐渐向集群增加流量以了解性能
  4. 监控,进行某些数据统计
    面向服务配置,不破坏Hystrix、Ribbon特性
    动态网关:将zuul路由规则配置在配置中心,修改路由规则,无需重启服务器

通过Nginx搭建网关集群

http {
  	upstream myhttpServer{
#配置多个zuul地址
	server localhost:8087;
	server localhost:8086;
	}
	server {
		listen       80;
       server_name  www.zpc.com;
		location / {
            proxy_pass   http://myhttpServer;
            index  index.html index.htm;
        }
	}
}

SpringBoot和SpringCloud_第2张图片

Config实现集中配置以及版本管理

当应用数量庞大,需要修改配置文件时间,都需要一一修改,然后进行重启。
Config Server是一个可横向扩展,集中式的配置服务器,可集中管理应用各个环境下的配置,可使用Git,Svn,本地文件进行存储。 bootstrap.yml配置

  1. 问题:当讲配置文件修改后push到git后,config server里的配置更新了,但是config client里的配置却没有更新
    解决:借用git的webhook(在仓库中的资源发生更新时会通知给谁)实现自动更新。
  2. 问题:虽然通过Git服务器的web hook可以实现自动更新,但是,如果Config Client有很多的话,那么需要在web hook中维护很多地址
    解决:将配置更新的消息 通过消息总线 通知所有config client
使用actuator监控中心完成刷新功能
POST请求监控中心 http://localhost:8080/actuator/refresh

SpringBoot和SpringCloud_第3张图片

消息总线

配合Spring Cloud Config实现微服务应用配置的动态更新。
Spring Cloud Bus是通过使用轻量级消息代理来构件一个公用的消息主题,然后所有微服务实例都订阅该主题。在该主题上可以方便的广播一些配置信息变更消息,或者其他一些管理操作。
SpringBoot和SpringCloud_第4张图片

  1. 在业务模块添加spirng-cloud-starter-bus-amqp依赖
  2. 在config配置文件(bootstrap.yml)添加rabbitmq的配置
  3. 修改git的webhook地址,将http://ip/actuator/refresh修改为http://ip/actuator/bus-refresh

Hystrix实现容错保护

Hystrix是Netfix开源的一个延迟和容错库,用户隔离访问远程服务,防止级联错误的发生,从而提升系统的可用性和容错性

  1. 封装请求:使用HystrixCommand封装请求,每个命令在独立线程中执行
  2. 跳匝机制:当达到熔断阈值时,可手动或自动跳匝
  3. 资源隔离:为每个依赖的服务都维护一个线程池,若线程池已满,则请求立即被拒绝
  4. 回退和自我修复:当请求失败,超时或断路器打开时,执行回退逻辑。当达到某时间周期进入半打开状态,然后尝试发送一个请求,若成功则进入关闭状态,若失败则再进入关闭状态。如此循环往复
    实现一个类级别的回调接口

参考博客

微服务应用Demo

springcloud通过bootstrap.yml负责从外部资源加载配置属性

  1. 创建Discovery项目,添加spring-cloud-starter-eureka-server依赖,使用@EnableEurekaServer启用Eureka服务端
  2. 创建Config项目:添加spring-cloud-starter-eureka依赖,spring-cloud-config-server依赖,使用@EnableEurekaClient启用Eureka客户端,使用 @EnableConfigServer启动配置服务器。
spring.application.name:config   配置EurekaClient的应用名称
eureka.instance.non-secure-port:${server.port:8888}  若环境变量有server.port有值则使用 环境变量的值,否则使用8888
eureka.instance.metadata-map.instanceId: ${spring.application.name}:${random.value} 配置实例ID
eureka.service-url.defaultZone:http://${eureka.host:localhost}:${eureka.port:8761}/eureka/  配置Eureka Server的地址
## 其他应用配置都集中配置在  类路径的config目录下
  1. 创建Order项目:添加spring-cloud-starter-eureka依赖,添加spring-cloud-config-client依赖,实现订单的增删改查
  2. 创建Gateway项目:添加spring-cloud-starter-eureka依赖,添加spring-cloud-config-client依赖
    添加spring-cloud-starter-zuul依赖,添加spintg-cloud-starter-hystrix依赖
    添加spiring-cloud-starter-feign依赖,添加spring-cloud-starter-ribbon
    启动Eureka客户端,Zuul代理,Feign客户端,断路器
    创建一个伪服务提供者接口,然后添加@FeignClient,调用哪个接口就在RequestMapping 的value标注那个接口的url。

Ribbon和Feign的区别:

Feign的中文名称翻译过来是伪装,通过调用RPC服务提供者的功能伪装成服务提供者。。。。

Ribbon添加maven依赖 spring-starter-ribbon 使用@RibbonClient(value=“服务名称”) 使用RestTemplate调用远程服务对应的方法
Feign添加maven依赖 spring-starter-feign 服务提供方提供对外接口 调用方使用 在接口上使用@FeignClient(“指定服务名”)

  1. Ribbon是一个基于 HTTP 和 TCP 客户端 的负载均衡的工具,需要自己构建http请求,模拟http请求然后使用RestTemplate发送给其他服务,步骤相当繁琐。
  2. Feign则是在Ribbon的基础上进行了一次改进,采用接口的方式,就像是调用本地方法一样感觉不到是调用远程方法,而且不需要自己构建http,是一个使用起来更加方便的 HTTP 客户端。

你可能感兴趣的:(Spring实战)