博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Cloud (1)
阅读量:6603 次
发布时间:2019-06-24

本文共 8913 字,大约阅读时间需要 29 分钟。

SpringCloud

微服务定义

  1. 是一种架构风格
  2. 一系列微小的服务共同组成
  3. 每个服务跑在自己的进程里
  4. 每个服务为独立的业务开发
  5. 独立部署
  6. 分布式的管理

image-20180920185214111

架构形态

单体架构

image-20180920185310014

特点:
  1. 打包成一个war包,没有外部依赖
  2. 共用一个db
  3. 容易测试
  4. 容易部署
  5. 开发效率低
  6. 代码维护困难
  7. 部署不够灵活

    • 构建时间特别长
  8. 稳定性不高
  9. 扩展性不够,不能满足高并发需求

基于ajax的前后端分离

image-20180920185619575

分布式架构

定义:支持应用程序和服务的开发,可以利用物理架构和多个自制的处理元素(多节点),不共享主内存,但通过网络发送消息

简单的微服务

image-20180920185838902

基础框架组件

服务注册发现

服务网关

  • 连接内外大门
  • 屏蔽后台细节,让用户无感知
  • 路由功能,外部请求反向路由到内部某个服务
  • 网关功能,控制流量,监控和日志

    • 用户认证
    • 授权
    • 服务网关

前端服务(边缘服务)

聚合

把两个接口聚合在一起返回出去

裁剪

通过不同需求返回不同数据,pc和手机端淘宝返回详情数据不一致

后端通用服务(中间层服务)

阿里系

Dubbo

Zookeeper

Spring MVC or SpringBoot

Spring Cloud

定义

  • 是一个开发工具集
  • 利用spring boot的开发遍历
  • 基于对netflix 开源组件的进一步封装
  • 简化了分布式开发

来源

基于Netflix Eureka做了二次封装

文档

版本查看

image-20180920192026017

Eureka Server(注册中心)

-Dserver.port=

pom文件

org.springframework.cloud
spring-cloud-starter-netflix-eureka-server

配置方式

image-20180920204856378

image-20180920204912734

eureka:  client:    service-url:      defaultZone: http://localhost:8080/eureka/    # 不把自己注册到注册中心    register-with-eureka: false# 设置应用名spring:  application:    name: eureka

打包

mvn clean package install

Eureka Client(服务注册)

pom文件

org.springframework.cloud
spring-cloud-starter-netflix-eureka-client

yml配置方式

eureka:  client:    service-url:      defaultZone: http://localhost:8761/eureka/    # 不把自己注册到注册中心    register-with-eureka: false    #关闭心跳监测  server:    enable-self-preservation: false# 设置应用名spring:  application:    name: eurekaserver:  port: 8761

image-20180920231533665

开启注解

@EnableDiscoveryClient@EnableEurekaClient区别

如果注册中心是eureka那么推荐使用EnableEurekaClient`

如果是其他注册中心那么推荐使用Enable

Eureka的高可用

image-20180920232137448

两个eureka都能看到client的信息

如果一个client挂掉了那么两个eureka都没有信息

解决:

image-20180920232310374

多台

image-20180920232433410

分布式中为什么需要服务发现

image-20180920232826038

a和b沟通完全通过注册中心

服务端发现

  • Nginx
  • Zookeeper
  • Kubernetes

客户端发现

  • Eureka

微服务的特点

  1. 异构
  2. 不同类型的数据库
  3. Spring Cloud通过rest方式实现服务注册
  4. Node.js的eureka-js-client

服务拆分方法

  1. 分清楚起点和终点
  2. 了解现有架构是否支持微服务架构
  3. 架构是不断引进的

不适合微服务的系统

  1. 系统中包含很多强事物场景的
  2. 业务相对稳定,迭代周期长
  3. 访问压力不大,可用性要求不高

康威定律

任何组织在设计一套系统时,所交互的设计方案在结构上都与该组织的沟通结构保持一直

微服务特点

  • 一系列微小的服务共同组成
  • 单独部署,跑在自己的进程里
  • 每个服务为独立的业务开发
  • 分布式的管理

image-20180921113617844

扩展立方模型

image-20180921113854873

  • X轴 水平复制
  • Y轴功能解耦

    • 单一职责,每个服务负责单一功能
    • 相关功能聚集在一个服务内
    • 关注点分离

      • 职责分离
      • 通用性分离

        • 基础组件划分
        • 消息服务
        • 用户服务
        • 公共组件拆分
      • 粒度分离

        • 不是越小越好
  • Z轴 数据分区

点餐业务拆分

拆分服务

image-20180921114336491

服务拆分方法论

  • 每个微服务都有单独的数据存储
  • 依据服务特点选择不同结构的数据库类型

    • 搜索->elasticsearch
    • 订单类-》mysql
  • 难点在难以确定边界

    • 针对边界设置api
    • 依据边界权衡数据冗余

应用通信

调用的三种方式

  1. 直接使用RestTemplate

    • String s = restTemplate.getForObject("http://localhost:8083/hello", String.class);
  2. 使用LoadbalanceClient

    • ServiceInstance serviceInstance = loadBalancerClient.choose("PRODUCT");String url = String.format("http://%s:%s", serviceInstance.getHost(), serviceInstance.getPort() + "/hello");String result = restTemplate.getForObject(url, String.class);
  3. 使用注解

    • @Bean@LoadBalancedpublic RestTemplate restTemplate() {    return new RestTemplate();}

客户端负载均衡器(Ribbon)

  • RestTemplate
  • Feign
  • Zuul

发现方式

  • 服务发现
  • 服务选择规则
  • 服务监听

主要组件

  • ServerList
  • IRule
  • ServerListFilter

源码解析

  1. image-20180925174557136
  2. image-20180925174625714
  3. image-20180925174655200
  4. 用来获取所有列表image-20180925174741878
  5. 轮循策略默认是roundRobinRuleimage-20180925174826179

    image-20180925175053677

    修改默认轮询策略

    1. users:  ribbon:    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
    2. 轮循策略image-20180925175858487

Feign使用(内部也使用了rabbion做负载均衡)

  1. Pom文件

    1. org.springframework.cloud
      spring-cloud-starter-feign
  2. 启动主类增加注解@FeignClient
  3. 编写接口

    1. @FeignClient("product")public interface FeignConfig {    @GetMapping("hello")    String hello();}
  4. 注入和调用

    1. @Autowired    private FeignConfig feignConfig;        @RequestMapping("/feign")    public String feign() {        String result = feignConfig.hello();        return result;    }

多模块拆分服务

问题

  1. 商品和订单dto重复定义
  2. 同一个对象多次重复定义
  3. 订单服务里面不应该知道商品服务的uri

模块拆分

  • product-server

    • 业务逻辑
  • product-client

    • 对外暴露的接口
  • Product-common

    • 公用的对象
  • 依赖关系

    • image-20180926111404689

打包命令

  • mvn -Dmaven.test.skip=true -U clean install

同步还是异步

  1. image-20180926171455253

    1. 消费者通过消息中间件进行解耦
    2. 用户调用短信服务,积分服务,其他服务,服务耦合过大,用户登录成功需要多个服务同步响应后才告诉成功
  2. image-20180926171800592

    1. 商品服务库存变化发布消息,订单服务订阅消息,比如商品信息

      1. 订单不需要查询商品服务而是查询自己服务中的信息
      2. 保证数据最终一致性,只需要订阅对应服务就能保证
  3. 常见消息队列

    • RabbitMQ
    • Kafka
    • ActiveMQ

RabbitMQ安装

5672->默认RabbitMQServer端口

15672->RabbitMQ管理页面端口,页面只需要配置这个

docker run -d --hostname my-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3.7.3-management

默认密码:guest

Docker和DevOps

  1. docker能够解决不同环境下应用程序都能运行
  2. 轻量
  3. 进程隔离和管理
  4. 可复用,版本化(tag机制)
  5. 微服务架构师核心,devops和docker是手段

统一配置中心(Spring Cloud Config)

原因

  1. 配置方式不方便维护
  2. 配置内容与权限(针对线上)
  3. 每更新一个配置都要重启项目

ConfigServer使用

image-20180926175911819

configServer从远端git拉下配置放到本地git如果远端不可用使用本地的

  • pom
  1. org.springframework.cloud
    spring-cloud-config-server
    org.springframework.cloud
    spring-cloud-starter-netflix-eureka-client
  • 开启注解

    @EnableDiscoveryClient@EnableConfigServer
  • 没有配置对应的gituriimage-20180926181337220
  • 在git上新建项目

    • image-20180926182910218
  • 在配置中填写对应git uri,username,password
  • image-20180926183121728
  • 访问对应配置文件

    1. .properties展示为properties ,.yml为yml
    2. /{label}/{name}-{profiles}

      1. label->分支(不写默认master)
      2. name->文件名
      3. profiles->环境
  • 设置配置文件基础目录

    • spring.cloud.config.server.git.basedir

ConfigClient使用

导入依赖

org.springframework.cloud
spring-cloud-config-client

更改配置

spring:  application:    name: order  cloud:    config:      discovery:        enabled: true        service-id: config      profile: dev

修改application.yml

修改为bootstrap.yml这样会优先启动

注意

配置中心会读取拼接order.yml+order-xx.yml的内容

Spring Cloud Bus

通过git hook访问配置文件变更,同步信息到消息队列,(/bus/refresh)

Config-server 通过消息队列同步到其他服务

使用

更新版本

org.springframework.boot
spring-boot-starter-parent
2.0.0.BUILD-SNAPSHOT
UTF-8
UTF-8
1.8
Finchley.BUILD-SNAPSHOT

导入jar包

org.springframework.cloud
spring-cloud-starter-bus-amqp
2.0.0.RELEASE

yml开放端口用来刷新对应变更

management:  endpoints:    web:      exposure:        include: bus-refresh

访问端口刷新配置

curl -v -X POST "http://localhost:8991/actuator/bus-refresh"

需要变更的类上面加上注解@RefreshScope

@RestController@RequestMapping("/env")@RefreshScopepublic class EnvController {    @Value("${env}")    public String env;    @GetMapping("/profile")    public String getenv() {        return env;    }}

通过 git HOOK自动访问地址

image-20180928005701388

有bug

异步和消息

定义

  1. 异步:客户端请求不会阻塞进程,服务端的响应可以是非及时的

    1. 通知
    2. 请求异步响应
    3. 客户端不会阻塞
    4. 通过消息实现一对多

      1. 客户端发送请求消息等待服务端响应

MQ

应用场景

  1. 异步处理

    1. 用户注册后需要发短信和加积分
  2. 流量削锋

    1. 秒杀场景,丢弃请求,控制活动人数
  3. 日志处理(kafka)

    1. 通过日志采集定时写入队列
  4. 应用解耦

    1. 用户下单后需要调用商品服务,使用mq用户下单后把消息写入商品服务,商品使用拉或者推的方式,订单服务写入订单后就可以不关注后续流程了

使用

导入依赖

org.springframework.boot
spring-boot-starter-amqp

yml配置

spring:  application:    name: order  cloud:    config:      discovery:        enabled: true        service-id: config      profile: test  rabbitmq:    host: localhost    port: 5672    username: guest    guest: guest

发送方式

@Autowired    private AmqpTemplate amqpTemplate;    @Test    public void send() {        amqpTemplate.convertAndSend("myQueue", "now time:" + System.currentTimeMillis());    }

接收方式

第一种(需要手动创建队列)

image-20180928173139793

@Slf4j@Componentpublic class MqReceiver {    @RabbitListener(queues = "myQueue")    public void process(String message) {        log.info("MqReceiver:{}", message);    }}
第二种 自动创建队列
/**     * 自动创建队列     *     * @param message     */    @RabbitListener(queuesToDeclare = @Queue("myQueue2"))    public void autoCreateQueue(String message) {        log.info("autoCreateQueue:{}", message);    }

第三种 Exchange和Queue绑定

@RabbitListener(bindings = {@QueueBinding(            value = @Queue("myQueueExchange"),            exchange = @Exchange("myExchange")    )})    public void exchange(String message) {        log.info("myExchange:{}", message);    }

image-20180928174927568

消息分组使用第三种方式

@RabbitListener(bindings = @QueueBinding(        exchange = @Exchange("myOrder"),        key = "computer",        value = @Queue("computerOrder")))public void computerOrder(String message) {    log.info("computerOrder:{}", message);}@RabbitListener(bindings = @QueueBinding(        exchange = @Exchange("myOrder"),        key = "fruit",        value = @Queue("fruitOrder")))public void fruitOrder(String message) {    log.info("fruitOrder:{}", message);}
@Test    public void sendToProduct() {        amqpTemplate.convertAndSend("myOrder", "computer", "now time:" + System.currentTimeMillis());    }

Spring Cloud Stream

为微服务应用构建消息能力的应用,对于消息中间件的封装,代码对于中间件的无感知,但是只支持rabbitMQ 和Kafka

image-20180929181444018

使用

导入pom
org.springframework.cloud
spring-cloud-starter-stream-rabbit
定义接口
public interface StreamClient {    @Input("myMessage")    SubscribableChannel input();    @Output("myMessage")    MessageChannel output();}
接受
@Component@EnableBinding(StreamClient.class)@Slf4jpublic class StreamReceiver {    @StreamListener("myMessage")    public void process(Object message) {        log.info("StreamReceiver:{}",message);    }}
发送
@RestControllerpublic class SendMessageController {    @Autowired    private StreamClient streamClient;    @GetMapping("/sendMessage")    public void process() {        String message = "now " + new Date();        streamClient.output().send(MessageBuilder.withPayload(message).build());    }}

参考:https://coding.imooc.com/learn/list/187.html

转载地址:http://bcwso.baihongyu.com/

你可能感兴趣的文章
APICLOUD 1.1.0 开发环境搭建
查看>>
《Cadence 16.6电路设计与仿真从入门到精通》——导读
查看>>
Confluence 6 如何让我的小组成员知道那些内容是重要的
查看>>
找到一个适合的分布式文件系统之各种分布式文件系统优缺点对比
查看>>
httpd基本配置
查看>>
索引失效的几个原因
查看>>
关于多线程中使用while做循环而不使用if的解释
查看>>
欢迎你,企业基础架构CCIE,RS CCIEv5.0的升级版新时代迎合自动化运维的网工顶级认证...
查看>>
js typoeof用法
查看>>
五险一金,你清楚吗?
查看>>
Ip核_fifo
查看>>
基础 JavaScript 实例
查看>>
自定义pageControl
查看>>
repquota命令--Linux命令应用大词典729个命令解读
查看>>
我的友情链接
查看>>
设置vs解决方案跟随右边cpp
查看>>
Linux Administration
查看>>
如何使版面富有节奏感
查看>>
rabbitmq 管理及常用命令
查看>>
iphone导航控制器的开发与使用
查看>>