msapro-note

# 学习内容
    SpringCloud  Hoxton.SR8   耐菲
    RabbitMQ
    分布式事务
    RocketMQ
    Docker
    Elasticswarch
    Kubernetes
    Lucene Solr

# 一. idea
    plugin EditStarters, Free Mybatis Plugin, Maven Helper
    中央仓库
## STS




# 二. SpirngCloud  

## A. 本阶段内容
    SpirngCloud Hoxton.SR8      微服务
    Eureka                      注册中心
    Feign                       远程调用
    Feign + Ribbon              负载均衡
    Zuul                        网关
    Zuul + Ribbon               负载均衡
    Zuul + Hystrix              容错和限流
    HystrixDashboard + actuator          链路监控
    Turbine                     聚合日志
    Spring cloud config         配置中心

## 服务
    ItemServiceApplication
    UserServiceApplication
    OrderServiceApplication    Feign
    EurekaApplciation                          http://eureka1:2001/
    ZuulApplication                            http://localhost:3001/item-service/item/23/?token=123
    HystrixDashboardApplication                http://localhost:4001/hystrix     ->    http://localhost:3001/actuator/hystrix.stream
    TurbineApplication                         http://localhost:5001/turbine.stream聚合了3001和3002          http://localhost:4001/hystrix  ->  http://localhost:5001/turbine.stream
    SpringCloudConfigApplication               http://localhost:6001/item-service/dev
    
## 0. 集成多种工具,解决微服务中的各种问题
    - 注册和发现
    - Nacos
    - Eureka
    - 远程调用 - OpenFeign
    - 负载均衡
    - 重试
    - 系统容错和限流 - Sentinel, Hystrix
    - 降级
    - 熔断
    - 错误监控 - Hystrix Dashboard、Turbine
    - 配置中心 - Nacos、Config
    - 链路跟踪 - Sleuth、Zipkin

## 1. 依赖 pom.xml
    > 打包方式
        <packaging>pom</packaging>
    > jackson
        json互转工具
    > lombok
    > javax.servlet-api  
        创建cookie
    > slf4j-api
    > commons-lang3
        apache的工具包
    > maven-compiler-plugin
        maven插件

## 2. 项目结构
springcloud1
    sp01-commons
        pojo
        service(Interface)
        web.util
    sp02-itemservice
        service(impl)
        controller
    sp03-userservice
        service(impl)
        controller
    sp04-orderservice
        service(impl)
        controller

## 3. eureka 注册中心    --服务注册,服务发现,维护注册信息
> nacos, eureka, consul, etcd, zookeeper 

>*1* 注册中心业务:  

    把服务注册在里面, 服务注册 服务发现  
        服务A 调用 服务B, 先从注册中心获取注册表得到所有, 找到对应的服务地址. A 在注册中心得到 B 的服务地址 再调用B的业务 

>*2* eureka:

    作为springboot服务
    a. 禁用自我保护模式    --在集群中                                 ---eureka:server:enable-self-preservation: false
    b. 主机名 --                                                     ---instance:hostname: eureka1
    c. 不向自己注册, 不从自己拉取  --集群中多个eureka要互相注册拉取     ---client:register-with-eureka: false      fetch-registry: false
    

>*3* eureka服务器搭建:

    1. 新建服务 sp05-eureka
    2. pom.xml  依赖: eureka server

    3. application.yml
        eureka:
            server:
                enable-self-preservation: false
            instance:
                hostname: eureka1
            client:
                register-with-eureka: false
                fetch-registry: false
                service-url:
                    defaultZone: http://eureka1:2001/eureka/
                    # 集群节点服务器默认http://localhost:8761/eureka/

        a. 集群服务器之间, 通过hostname 区分不同的eureka
        b. eureka.server.enable-self-preservation
            eureka的自我保护状态,心跳失败的比例-15分钟内达到85%进入保护状态, 把实例注册信息保护起来, 不再注销任何微服务
        c. eureka.client.register-with-eureka=false
            不向自身注册
        d. eureka.client.fetch-registry=false
            不从自身拉取注册信息
        e. eureka.instance.lease-expiration-duration-in-seconds
            最后一次心跳后,间隔多久认定微服务不可用,默认90
        
    4. 启动类注解:
        @EnableEurekaServer  --触发eureka服务器的自动配置

### hosts: C:\Windows\System32\drivers\etc

>*4* eureka客户端搭建  

    ---在需要在注册中心注册的服务中,配置
    - 02-item 03-user 04-order 配置
    1. pom.xml  
        eureka client依赖
    2. application.yml
        配置eureka server地址

        eureka:
            client:
                service-url:
                    defaultZone: http://localhost:2001/eureka

        eureka.instance.lease-renewal-interval-in-seconds
        心跳间隔时间,默认 30 秒

        defaultZone,默认位置,可以修改为具体地理位置,比如:beiJing, shangHai, shenZhen 等,表示 eureka 服务器的部署位置, 需要云服务器提供

        eureka.client.registry-fetch-interval-seconds
        拉取注册信息间隔时间,默认 30 秒
    
    3. 启动类注解
        @EnableDiscoveryClient

>*5* eureka运行机制

    1. 注册: 客户端 反复连接服务器, 直到注册成功为止
    2. 拉取: 客户端 每30秒拉取注册表, 刷新注册表
    3. 心跳: 客户端 30秒发送一次, 服务端连续3次收不到-删除这个服务, 
    4. 自我保护模式: 15分钟内,85%服务器出现心跳异常(又一次未收到),     保护所有注册信息不删除,   服务端连续3次收不到心跳-不删除

>*6* 高可用

    1. item-service 高可用  
        启动两个服务(不同端口)  8001 8002
        a. 打包package  
            java -jar item.jar                           使用的端口是yml中的8001
            java -jar item.jar --server.port=8002        使用的是设置的8002
        b.idea启动配置
            edit configuration 
                -> program arguments -> --server.port=8001
                Sp02ItemServiceApplication-8002 -> copy configuration -> 8002
    2. eureka高可用
        a. profile配置    profile名字就是eureka1
            application-eureka1.yml
                eureka:
                    instance:
                        hostname: eureka1
                    client:
                        register-with-eureka: true  #profile的配置会覆盖公用配置
                        fetch-registry: true        #profile的配置会覆盖公用配置
                        service-url: 
                            defaultZone: http://eureka2:2002/eureka  #eureka1启动时向eureka2注册
        b. 使用配置
            打包运行: java -jar eureka.jar --spring.profiles.active=eureka1
            idea启动配置: program arguments

## 4. Feign   --远程调用
订单服务
    获取订单
        获取用户
        获取订单列表
    保存订单
        增加用户积分
        减少商品库存

>*1* 订单服务

    a. 依赖: openfeign
    b. 启动类注解: @EnableFeignClients
    c. 定义声明式客户端接口(远程调用服务接口)
        ItemClient
        UserClient
            1. 调用哪个服务  @FeignClient(name = "item-service")
            2. 调用哪个路径  @GetMapping("/{orderId}")
            3. 提交什么参数  JsonResult<List<Item>> getItems(@PathVariable String orderId);
    d. service使用feign来远程调用
        注入接口 
            @Autowired
            private ItemClient itemClient;

图标请求
@GetMapping("/favicon.ico")
public void ico(){}


## 5. Feign 集成 ribbon 
>*1* 默认实现负载均衡

    feign底层已经实现了, 

>*2* 默认实现重试

    调用远程服务时, 远程服务出错, 可以重试或者负载均衡
    a. 重试参数
        ribbon.MaxAutoRetries=0      --单台服务器的重试次数
        ribbon.MaxAutoRetriesNextServer=1    --更换服务器次数
        ribbon.ReadTimeout=1000    --发送请求后, 等待响应的超时时间
        ribbon.ConnectTimeout=1000   --与后台服务器建立网络连接的超时时间
        ribbon.OkToRetryOnAllOperations=false    --是否对所有类型请求都进行重试,默认只对get请求重试
    b. 测试
        延迟 ItemController

## 6. Zuul API网关 
    a. zuul所有的功能都是通过过滤器实现的,
        前置过滤器 pre-filtes
        路由       routing
        后置        post
        错误      error
    b. zuul的配置
        自动配置, 会从Spring容器发现这个过滤器实例, 自动完成配置


>*0* 新模块 sp06-zuul

    a. 依赖: eureka-client, zuul, sp01
    b. .yml配置
        路由-routes   --路径和后台服务之间的映射
        zuul:   # 默认配置-根据注册表设置
            routes:
                item-service: /item-service/**
                user-service: /user-service/**
                order-service: /order-service/**
    c. 启动类注解
        @EnableZuulProxy

>*1* 功能

    统一的入口         --转发
    统一的权限校验
    集成ribbon
    集成hystrix

>*2* 统一的权限校验   过滤器

    过滤器, 在过滤器中检查用户权限
        http://localhost:3001/item-service/item/fds123?token=fdjkslf13fd1s3
    
    a. 继承Zuul的过滤器    ZuulFilter, 实现方法
        filtertype() 过滤器类型, 
            FilterConstants.PRE_TYPE
        filterOrder() 过滤器顺序号, 
            前5个是默认的过滤器, 加在第6个
            在第5个过滤器中, 向上下文对象添加了serviceId属性, 后面的过滤器才能访问serviceId属性
        shouleFilter() 针对请求是否执行过滤代码, 
            实现: 判断调用的后台服务, 服务id
                获取服务id  RequestContext.getCurrentContext().get("FilterConstants.SERVICE_ID_KEY");
        run() 自定义过滤器具体代码实现
            请求可以执行 run(), 再在这里判断是否有权限
            没有权限  阻止继续调用requestContext.setSendZuulResponse(false);

    b. 注解 @Component

>*3* 网关超时 GateWay Timeout  504

## 7. zuul集成ribbon

    默认实现了负载均衡, 没有启动ribbon重试
    尽量步骤网关添加重试, 否则可能造成大面积服务器压力倍增

    启动重试(Zuul网关不推荐)
        a. 添加 spring-retry依赖
        b. yml配置 zuul.retryable=true
        c. 有默认重试参数, 可以修改配置
            对所有服务通用
                ribbon:
                    MaxAutoRetries: 1     --单台服务器的重试次数
                    MaxAutoRetriesNextServer: 1    --更换服务器次数
            只对item服务有用
                item-service:
                    ribbon:
                        MaxAutoRetries: 0

## 8. zuul集成hystrix

    容错和限流     链路监控     网关出错--会调用hystrix


    a. 容错:
        降级: 当调用后天服务出错, 执行当前服务中一段 降级 代码, 返回降级结果
    
    b. 限流:
        熔断: 调用后台服务流量过大时, 后台服务出现故障, 可以断开链路, 减轻后天服务压力
    
    c. 降级:
        调用后台服务出错:   500, 后台服务不存在, 调用超时, 默认1秒
        实现:
            依赖: 间接依赖
            配置: 无
            代码: 实现 FallbackProvider 接口  @Component
                getRoute()
                    设置针对哪个后台服务进行降级
                    */null 对所有服务应用降级类
                    item-service  只针对item服务应用降级类
                fallbackResponse()
                    向客户端发回的降级响应
                        - 错误提示
                        - 缓存数据
                    new ClientHttpResponse(){}

        zuul默认已经启动hystrix, 自动从容器中读取到实现了接口的实例, 

    d. Hysrix超时
        默认1秒超时
        ribbon重试, Hysrix超时会自动配置成ribbon的最大超时时间
        设置超时时间:
            hystrix:
                command:
                    default:
                    execution:
                        isolation:
                        thread:
                            timeoutInMilliseconds: 500

    e. 熔断:
        后台服务流量过大, 出现故障, 
        发生条件: 10秒20次请求(必须首先满足), 50%失败执行降级(), 
        断路器打开后: 一段时间后,进入半开状态,  半开状态下,会尝试向后天服务发送一次客户端调用
            调用成功: 
    
    f. zuul 降级 
        https://gitee.com/zhaoqing_lj/msapro2104/tree/master/springcloud1/sp06-zuul/src/main/java/cn/tedu/sp06/fallbackp
    
    g. 请求 报500
        http://localhost:3001/order-service/order/1
        zuul -> order -> { user, item }  

        OrderFallback.java  ---降级代码

        code: 500,msg: "后台服务出错, 请稍后重试" ------  item服务有延迟, zuul超时-降级了

## 9. Actuator
    SpringBoot提供的一个项目监控工具, 提供项目的多种监控日志
    
    a. 监控日志:
        健康状态;
        spring容器中所有的对象;
        springmvc设置的所有路径;
        环境参数, 环境变量;
        虚拟机的堆内存;
    
    b. 实现:
        依赖: 间接依赖, zuul中有, 
        yml: 暴露哪些监控日志
            m.e.w.e.i=* 暴露全部监控数据
            m.e.w.e.i=health,beans,mapping,hystrix.stream     

            management:
                endpoints:
                    web:
                    exposure:
                        include: 
                            - health
                            - beans
    
    c. 访问路径 --暴露的监控日志
        http://localhost:3001/actuator

### java虚拟机内存分析
    MAT

## 10. hystrix dashboard  链路监控
    Hystrix仪表盘: 监控Hystrix降级和熔断情况
        把一个服务的监控日志(actuator)以图表的形式展示

    a. Hystrix利用Actuator工具,暴露自己的监控日志,

    b. 搭建仪表盘:
        创建module: sp07-hystrix-dashboard
        依赖: hystrix-dashboard
        yml配置: 
            允许抓取的服务列表
        启动类注解:
            @EnableHystrixDashboard
        访问路径:
            localhost:4001/hystrix
                把路径放在 Hystrix Dashboard     http://localhost:3001/actuator/hystrix.stream
    
    可以是完全独立的项目, 不是在注册中心获取的服务

## 11. 压力测试工具
    httpd-2.4.39-o102r-x86-vc14/Apache24/bin
    
    用 ab 工具,以并发50次,来发送20000个请求
    ab -n 20000 -c 50 http://localhost:3001/item-service/item/23/?token=123
    ab -n 20000 -c 100 http://localhost:3001/user-service/user/23

## 12. Turbine
    hystrix 日志的聚合工具
        可以聚合多台服务器的Hystrix日志, Hystrix Dashboard 可以从 turbine 拉取 聚合之后的日志, 
        同时监控多台服务器
    
    实现:
        module: sp08-turbine
        依赖: eureka client, turbine
        yml:
            聚合的服务: zuul    localhost:3001 localhost:3002  从注册表获取
            给聚合的数据命名: default
                new String("default")
            turbine:
                app-config: zuul
                cluster-name-expression: new String("default")
        启动类:
            @EnableTurbine
        访问:
            http://localhost:5001/turbine.stream

## 13. 部署分布式服务  (多台主机)
    A. eureka                一台主机          172.18.6.73:2001
    B. zuul                  一台主机          172.18.6.74:3001
    C. dashboard,turbine     一台主机          172.18.6.75:4001/hystrix    172.18.6.75:5001/turbine.stream
    D. item 业务模块         所有主机
    E. hosts
        172.18.6.73 eureka1   
        172.18.6.73 eureka2
    F.访问 
        http://172.18.6.73:2001   注册表
        http://172.18.6.74:3001/item-server/item/23?token=sdf    访问item服务
        http://172.18.6.75:4001/hystrix  --填写-->  http://172.18.6.75:5001/turbine.stream    仪表盘

## 14. vmware 
> net 虚拟网络

    vmnet8 -> 子网ip 192.168.64.0

> centos-8-2105

    阿里yum安装源/扩展源, python, pip, ansible, ip-static(配置固定ip)/ip-dhcp(自动获取ip){脚本文件-方便配置ip地址}
    
    已复制虚拟机
    登录: root root

## 15. spring cloud config 配置中心  
    spring cloud config   放到   git仓库中/文件/数据库,  使用时拉取配置
    git仓库 --github,gitee,gitlab,csdn的chinacode
    
    a.配置文件:
        文件夹: config  
        文件: 服务2,3,4的application
        文件名: item-service-dev.yml   user-service-dev.yml    order-service-dev.yml 
    b.git仓库:
        https://gitee.com/zhaoqing_lj/msapro2104.git
        配置用户名/密码:
            qingjing20140614@163.com   997z185q123f1fgfd8fdsf1fds5
        路径: 
             msapro2104/springcloud1/config
        端口:
        java -jar i.jar --server.port=8002
        .yml
            spring.cloud.config.override-none: true    远程下载配置 不会 覆盖本地配置
    c.配置中心
        仓库的地址
        存放配置文件的文件夹
    
    D. 搭建配置中心
        module: sp09-config
        依赖: eureka client, config server
        yml:
            git仓库地址:
            存放配置文件文件夹:

            spring:
            application:
                name: config-server
            cloud:
                config:
                server:
                    git:
                    uri: https://gitee.com/zhaoqing_lj/msapro2104.git
                    search-paths: springcloud1/config
                    username: qingjing20140614@163.com
                    password: zq1815

        启动类注解:
            @EnableConfigServer
        
        访问:
            http://localhost:6001/item-service-dev.yml
            http://localhost:6001/item-service/dev
        
        服务注册到eureka, 目的服务配置需要放到git的服务 要从eureka中获取配置中心服务, 再从配置中心服务中获取远程配置 到自己的服务
    
    E. 2,3,4 服务 从配置中心获取 配置信息
        依赖: spring-cloud-starter-config
        yml:  bootstrap.yml
            . 连接eureka
            . 指定配置中心 服务id
            . 指定下载的配置文件
            eureka:
                client:
                    service-url:
                    defaultZone: http://eureka1:2001/eureka
            spring:
                cloud:
                    config:
                    discovery:
                        enabled: true
                        service-id: config-server
                    name: user-service
                    profile: dev

### 16. MQ 自动刷新配置
    nacos, 更改配置后, 后端服务自动刷新配置
    springcloudconfig, 需要MQ, 通过消息给服务 刷新配置
        更改配置后, 配置中心发送消息要求服务器更新配置信息,   配置中心把消息发送给MQ,  MQ再把消息给各个服务 服务刷新配置
    
    RabbitMQ 添加到 springcloud中

    A.Bus 辅助完成配置刷新指令的收发操作
    B.业务服务, 配置中心添加 Bus 组件 RabbitMQ-api
        a. 依赖: Bus, Binder-rabbit, spring-boot-starter-amqp, spring-rabbit-test
        b. yml:
            配合rabbitmq连接信息 
            spring:
                  rabbitmq:
                    host: 192.168.64.140
                    port: 5672
                    username: admin
                    password: admin

    C.配置中心暴露刷新 端点
        a. 依赖: actuator(已有)
        b. yml:
            暴露刷新端点   
            management:
                endpoints:
                    web:
                    exposure:
                        include: bus-refresh
    
    D.访问Bus
        刷新所有服务
        post --->   http://localhost:6001/actuator/bus-refresh    --->   Bus发送消息给RabbitMQ, 刷新配置, 业务服务重新连接了配置中心拉取了配置
        只刷新item-service
        post --->   http://localhost:6001/actuator/bus-refresh/item-service
    
    E.修改配置, 服务自动刷新配置
        使用User服务, 添加用户注入到userJson   
        a. 注解: @RefreshScope  // 需要注入(@Value()) 的业务层 添加注解  // 配置刷新到新的用户配置, 可以重新注入到对象中
        b. 使用Bus( post --->   http://localhost:6001/actuator/bus-refresh/user-item )  刷新业务配置-使业务重新在配置中心拉取配置
            刷新配置, 从配置中心拉取了配置,  (不是重启了服务)


### 17. Bus 工具/组件 消息总线
    发送消息
    组件







# 三. RabbitMQ 
    传递消息
## 1. 消息服务器 / 消息队列 Message Queue / 消息中间件 Broker

## 2. 市场上的消息服务器 
    RabbitMQ, 
    RocketMQ(阿里事务消息), 
    TubeMQ(腾讯万亿级别), 
    Kafka, 
    ActiveMQ,

## 3. Docker环境
    A. 克隆centos-8-2105  docker-base
    B. 设置ip
        ./ip-dhcp   ifconfig
    C. Mobaxterm连接服务器
    D. Docker在线/离线安装
    E. 安装Docker

    F. 克隆docker-base   rabbitmq
       设置ip  ./ip-static    ip:192.168.64.140

## 4. 搭建RabbitMQ服务器    docker运行
    A. RabbitMQ镜像
        在线   docker pull rabbitmq:management   
        离线   docker load -i rabbit-image.gz
    B. docker
        防火墙:
            systemctl stop firewalld / disable
        重启docker:
            systemctl restart docker
    C. 从镜像启动RibbitMQ  --在线拉取的新版本 3.9 以上 
        配置文件: 
            mkdir /etc/rabbitmq  
            vim /etc/rabbitmq/rabbitmq.conf  
                default_user = admin 
                default_pass = admin  
        运行:
            docker run -d --name rabbit -p 5672:5672 -p 15672:15672 \
            -v /root/msapro/rabbitmq/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf \
            -e RABBITMQ_CONFIG_FILE=/etc/rabbitmq/rabbitmq.conf rabbitmq:management

## 5. RabbitMQ 六种模式
    简单模式
    工作模式
    发布订阅模式
    路由模式
    主题模式
    RPC模式

## 6. RabbitMQ使用场景
    A.服务与服务之间  解耦
        服务之间互相调用           直接调用   耦合高
        服务之间 插入rabbitmq服务  间接调用   降低耦合
        服务A  -> rabbitmq服务  {服务B, 服务C, 服务D, 服务E}  增加减少只需要从rabbitmq获取消息就行
    B.流量削锋
        大量的请求 -> rabbitmq服务器 -> 数据库
        rabbitmq 暂时缓存数据   原来: 并发的请求数据库     rabbitmq: 没有并发,一条一条处理
    C.异步调用
        服务器A(a,b,c,d) 请求 服务器B
        A把a 发给rabbitmq rabbitmq给B, A可以继续执行b,c..下面的业务

## 7. 搭建maven项目
    A.依赖: amqp-client(com.rabbitmq)

    B.消息
        消息发送成功 channel.basicPublish()
        http://192.168.64.140:15672/ 获取到消息队列中的消息
        消息接收成功 channel.basicConsume()
        http://192.168.64.140:15672/ 消息队列中 就是空了
        取走了消息就没有了, 

    C.模式
        https://gitee.com/zhaoqing_lj/msapro2104/tree/master/rabbitmq/rabbitmq-api/src/main/java/rabbitmq

        简单模式 : m1
           1.连接 ConnectionFactory factory = new ConnectionFactory();factory.setHost("192.168.64.140");  factory.newConnection()  connection.createChannel(); 
           2.创建 helloWorld 队列         channel.queueDeclare("helloWorld",false,false,false,null);
           3.向 helloWorld 队列发生消息           channel.basicPublish("","helloWorld",null,in.getBytes());
        工作模式 : m2
            多个消费者, 轮循接收, 负载均衡提高效率
        发布订阅模式/群发模式 : m3
            交换机 fanout
            发送给所有 consumer 每个consumer收到所有消息,    使用交换机,fanout 扇形发布
            rabbitmq 交换机 ( Direct Fanout Topic )   
        路由模式 : m4
            交换机 direct, 
            绑定键, 给拥有绑定键的队列发送消息, 

            路由关键词:匹配    
                producer -routingKeyOne-> exchanges     
                consumer -routingKeyTwo-> exchanges
                发送消息+routingKeyOne     当routingKeyTwo=routingKeyOne时的consumer才能接收到消息
        主题模式 : m5
            交换机 Topic
            关键词  (和路由一样)
            关键词有特殊规则, aa.bb.cc.dd   *.*.cc.dd   aa.#

    D.消息合理分发
        a. 手动 Ack -> 手动回执
            接收消息 参数 第二个 false 
                channel.basicConsume(Common.name,false,deliverCallback,cancelCallback);
            Ack中手动回执  回执位置 message{ envelope{ tag-int } }
                channel.basicAck(message.getEnvelope().getDeliveryTag(),false);
        b. 手动 qos (只在手动Ack时有效) 预抓取
            channel.basicQos(1);  --接收消息前    --每次接收一条,处理完之前不接受下一条

    E.回滚消息
        当接收消息服务 Consumer 宕机/停机 时, 消息会回滚到RabbitMQ服务器 内存

    F.消息持久化
        队列持久化,
            channel.queueDeclare(name,true,false,false,null);   第二个参数 持久队列
        消息持久化
            发送消息, 添加持久参数
            channel.basicPublish("",Common.name, MessageProperties.PERSISTENT_TEXT_PLAIN,s.getBytes());

    G.方法
        new ConnectionFactory();        --RabbitMQ的工厂连接 (com.rabbitmq.client.ConnectionFactory;)
        factory.newConnection();        --从工厂获取一个连接
        connection.createChannel();     --创建通信的通道

        创建队列
        channel.queueDeclare(queueName,durable,exclusive,autoDelete,arguments)          --队列声明
        创建交换机
        channel.exchangeDeclare(exchangesName, BuiltinExchangeType.FANOUT-交换机类型);         --交换机声明
        向队列发消息
        channel.basicPublish(exchange,routingkey,props,body-消息内容);         --基础发布

        接收消息
        channel.basicConsume(queueName,autoAck,deliverCallback-处理消息,cancelCallback-取消消息)          --基础消费
        手动qos
        channel.basicQos(1);            --预抓取,每次接收一条,处理完之前不接受下一条
        绑定交换机
        channel.queueBind(queueName,exchangesName,routingKey);          --队列捆绑

## 8. RabbitMQ使用案例
    A.Bus配置刷新指令  
        主题模式
        解耦,异步调用
    B.sleuth+zipkin联络跟踪
        简单模式
        解耦,流量削峰
    C.购物系统 产生订单 到数据库
        订单的流量削峰
        购物系统生成订单发送到 rabbitmq
        后台消费者 一个一个 顺序处理订单存储

    D.






# 四. sleuth 
    在各个模块中产生链路跟踪日志
    A -> B -> C -> D     
    A, 4F5D6S7RE3SF4, 4F5D6S7RE3SF4, TRUE
        请求服务时产生id(A-id), 
        A-id作为整条链路的id(说明是同一条链路,一次调用过程)
        TRUE(true把日志发送到zipkin,抽样10%发到zipkin)

## 1. 添加sleuth
    依赖: spring-cloud-starter-sleuth
    配置: 自动配置

## 2. 请求
    A.报500
        zuul 06 -> order 03 -> { user 04, item 02 }
        code: 500,msg: "后台服务出错, 请稍后重试"   item服务有延迟, zuul超时-降级了

    B.后台输出日志   sleuth
         INFO [zuul,c2013aea7e6c21aa,c2013aea7e6c21aa,true] 






# 五. sleuth + zipkin
    链路跟踪

## 1. sleuth 产生的日志 发送给 zipkin
    A.直接连接zipkin, 提交数据
        紧耦合
    B.通过消息服务,发送日志
        a.解耦
        b.流量削峰

## 2. 添加zipkin  客户端
    A.通过消息服务发送日志 需要RabbitMQ
    B.依赖: 
        zipkin客户端--spring-cloud-starter-zipkin, 
        rabbitMQ--spring-boot-starter-amqp
    C.yml: 
        日志发送方式
        rabbitmq连接配置
        spring:
            rabbitmq:
                host: 192.168.64.140
                port: 5672
                username: admin
                password: admin
            zipkin:
                sender:
                    type: rabbit

## 3. zipkin服务
    A.下载服务
        https://github.com/openzipkin/zipkin   Quick-start -> latest released server
    B.启动服务
        java -jar zipkin-server-2.23.2-exec.jar --zipkin.collector.rabbitmq.uri=amqp://admin:admin@192.168.64.140:5672
    C.访问
        http://localhost:9411/zipkin







# 六. 拼多商城 购物系统 RabbitMQ
    购物系统产生大量订单   存储   到数据库
    使用 RabbitMQ 做流量削峰, 在rabbitmq中排队处理(缓存在rabbitmq中)

## 1. 导入项目  pd-web   提交订单 saveOrder
    pom.xml -> make as maven
    jdk1.8

## 2. 导入数据库
    删除数据 pd_user, pd_order, pd_order_item

## 3. 启动项目
    配置项目的启动配置 
        项目配置(configuration) -> 
            working directory 设置到 pd-web 模块目录,然后重启项目
            或者  program arguments -> $%MODULE_WORKING_DIR%$

## 4. 修改订单, 向 rabbitmq 发送订单数据    ------------------------------
    A.依赖: rabbitmq---spring-boot-starter-amqp
    B.yml: 连接rabbitmq
    C.创建 队列orderQueue 参数的封装对象, 
        在 启动类    创建    orderQueue,true,false,false
            org.springframework.amqp.core.Queue 包 封装队列
        自动配置类-RabbitAutoConfiguration 使用参数创建队列
    D.在OrderServiceImpl 注入spring提供的rabbintmq工具: AmqpTemplate
    E.amqpTemplate.convertAndSend() 发送订单
        转换并发送方法, order对象会自动转换成byte[]数组再 发送  --序列化
    
    F. 发送订单 到 购物车  支付-保存订单 到了 RabbitMQ

## 5. 项目 pd-web-consumer   消费订单    ------------------------------------
    接收消息, 把订单存储到数据裤   

    类 OrderConsumer
    A. 注解: @RabbitListener(queue="orderQueue")通过注解配置, 接收消息
        @Component
    B. 处理消息的方法, @RabbitHandler,  具有这个注解的方法接收消息
    C. 调用业务方法完成订单存储

    Z. 总结
        接收消息 注解@RabbitListener(queues="orderQueue")  queues指定队列
            接收队列消息, 反序列化 成一个订单实例给方法参数
        @RabbitHandler 配合@RabbitListener注解, 指定处理消息的方法

## 6. 订单   生成-用户支付   消费-订单保存到数据库            ------------------------------
    -----由把订单保存到数据库      改变为     先把订单发消息给rabbitmq,然后消费者接收消息 ---------

    A.生成订单   
        (1)商品添加到购物车 
        (2)添加收货地址--原因:如果没有地址后端会判断报空指针异常  
        (3)用户支付订单-保存订单到RabbitMQ

    B.保存订单
        (1)consumer 从RabbitMQ中获取到队列中的消息
        (2)执行service业务, 保存到数据库





# 七. rabbitmq 整合 springboot
    依赖: spring-boot-starter-amqp, spring-rabbit-test
    yml: spring.rabbitmq.host port username password
## 1. 模式
    简单模式 : m1
        发送: amqpTemplate.convertAndSend("helloworld","Hello World ZhaoQing");  // 自动转换byte数组再转换
        接收: @RabbitListener(queues = "helloworld")  public void receive(String msg){  // 参数接收到注解传过来的参数     System.out.println("收到 : "+msg);    }
        main: 配置queue参数: @Bean return  new Queue("helloworld",false);  手动执行发送消息: 执行方法

    工作模式 : m2
        多个消费者, 轮循接收, 负载均衡提高效率
        合理分发: spring默认ack自动回执, qos=1 yml prefetch=1
        持久化: 队列 new Queue("task_queue",true);  消息 spring默认持久

    发布订阅模式/群发模式 : m3
        交换机 fanout    
        producer: amqpTemplate.convertAndSend("logs","",info); 
        consumer:     @RabbitListener(bindings = @QueueBinding(value = @Queue,exchange = @Exchange(name = "logs",declare = "false")))
        main: 创建交换机, 执行send
        
    路由模式 : m4
        交换机 direct, 
        绑定键, 给拥有绑定键的队列发送消息,   : key

    主题模式 : m5
        交换机 Topic
        关键词  (和路由一样)
        关键词有特殊规则, aa.bb.cc.dd   *.*.cc.dd   aa.#




# 八. 数据库初始化工具/模块
    重置所有数据库表
        SpringBoot db-init
## 1. 新建
    依赖: jdbc api, mysql driver
    yml: 数据源datasource
    resource:
        sql/ 1.sql,2.sql,3.sql,..
    启动来: 执行sql脚本-初始化数据库
## 2. jdbc 脚本执行器
    A.Spring 提供的    ScriptUtils.executeSqlScript()
        参数: 数据库的链接 java.sql.Connection , 文件资源对象

    B. 文件资源对象
        路径资源: new ClassPathResource(文件路径String, DatabaseInitApplication.class.getClassLoader());
        编码转换: new EncodedResource(classPathResource, "utf-8");






# 九. 分布式事务 部署服务    案例 (无事务处理)    seata-at

## 1. 数据库初始化

## 2. eureka 注册中心
    搭建 8761 模块 eureka
        依赖: eureka server
        yml: 禁用保护模式, 单台服务器(不注册,不拉去), 
        启动类注解: @EnableEurekaServer

## 3. 父子项目
    父: order-parentTwo
        pom.xml
    子: account  实现扣减账户金额, storage 减少库存, order 保存订单 调用s和c 
        依赖: 清空(都在父项目里)
        yml: 
            app.name, port, eureka, datasource, mybatisp, logging
        pojo, Dao, Service, Controller
    

## 4. 全局唯一id发号器
    https://github.com/lookingatstarts/easyIdGenerator ,下载发号器项目
    依赖: eureka
    yml: eureka
            配置详情:
                两个算法
                easy-id-generator.snowflake

                easy-id-generator.segment   数据库方式
                    db-list: seata_order     数据库列表,  使用配置文件seata_order.properties


    访问: http://localhost:9090/segment/ids/next_id?businessType=order_business


## 5. Feign   远程调用
    order订单添加Feign,调用库存和账户服务
        a.调用发号器获得全局唯一id
        b.调用库存服务减少商品库存
        c.调用账户服务扣减用户金额

    A.依赖:
        spring-cloud-starter-openfeign
    B.yml配置
        超时时长: ribbon.ReadTimeout=10000
    C.注解
        @EnableFeignClients
    D.声明式客户端接口
        @FeignClient(name="easy-id-generator") 描述接口(指定被调用服务名)
        @GetMapping("/segment/ids/next_id")   描述方法(执行被调用服务的方法)

        @FeignClient(name = "EASY-ID-GENERATOR")
        public interface EasyIdGeneratorClient {
            @GetMapping("/segment/ids/next_id")
            String nextId(@RequestParam String businessType);
        }






# 十. 分布式事务  
    分布式事务: Seata  AT,   TCC,  SAGA,   XA,  可靠消息最终一致性(异步确保),   最大努力通知

    A B C 分布式服务    A -> B   A -> C
        B 发生事务  C 知道不了

        解决: 事务协调器

## 1.Seata分布式事务框架
    提供高性能和简单易用的分布式事务服务
    支持: AT,  TCC,  SAGA,  XA





# 十一. Seata AT

## 1. Seata AT 基本原理

### 1.1 事务协调器  Transaction Coordinator
    A. 第一阶段: 
        执行各分支事务   @Transactional
    B. 第二阶段:
        控制全局事务最终提交或回滚    

### 1.2 第一阶段
#### 1.2.1 事务管理器  Transaction Manager
    事务管理器 向 事务协调器 申请开启全局事务(产生XID)     TM 向 TC 申请开启全局事务, TC 产生全局事务id(XID)
#### 1.2.2 资源管理器 Resource Manager
    执行业务,  开启 资源管理器并把XID给它, 
    职责: 管理分支事务(本地事务), 与TC通信,上报分支事务的执行状态,接收全局事务的提交和回滚指令
    RM 向 TC 注册分支事务, 把分支事务纳入对应的全局事务管理
    分支事务执行成功, RM 发送事务状态给 TC, TC 将事务状态给TM

### 1.3 第二阶段 提交
    全部分支事务执行完毕,  TM 收集了所有分支事务的 事务状态 -> 做做种决策, 让RM 发送提交指令完成提交操作

### 1.4 事务协调器 第一阶段/第二阶段  执行流程总结
    TC 事务协调器         全局事务,分支事务
    TM 事务管理器         收集分支事务的事务状态, 决策全局事务提交/回滚
    RM 资源管理器         管理分支事务, 发送分支事务状态, 全局事务的提交/回滚指令/操作
#### 1.4.1 第一阶段
    a. TM 向 TC 申请开启全局事务, TC 产生 XID 并发给 TM
    b. 执行事务, 启动 RM 并把 XID 给 RM, RM 携带 XID 向 TC 注册分支事务
    c. 事务成功, RM 上报事务状态给 TC, TC 把事务状态发送给 TM,
    d. 执行其他事务, 注册分支事务, 最终 TM 手机所以分支事务的事务状态
#### 1.4.2 第二阶段
    a. TM 收集到所有分支事务的事务状态, 决策全局事务状态,
    b. TM 把全局事务状态发送给 TC 
    c. TC 根据全局事务状态给 RM 发送指令, RM 执行 提交/回滚 指令/操作


## 2. 具体工作机制
### 2.1 第一阶段
    库存表 库存 50 改为 40
    a. 把表中原来的数据取出来
    b. 进行修改操作
    c. 取出表中的新数据
    d. 把旧数据和新数据 合并, 存放到 事务回滚日志表
    e. 第一阶段完成, 将状态上报给 TC
### 2.2 第二阶段
    事务失败--回滚
    a. TC 发送回滚指令 给 RM
    b. 根据事务回滚日志表, 将库存表中的数据恢复
    c. 删除事务回滚日志, 完成回滚操作
    事务成功--提交
    a. TC 发送提交指令 给 RM
    b. 删除事务回滚日志, 完成第二阶段提交操作

## 3.TM TC RM
    TC 全局协调     单独的服务
    TM 全局管理/存储事务状态日志      调用服务的服务--添加
    RM 分支事务     被调用服务--添加

    A->B    A->C    
    TC seata-server服务
    TM 在A中添加
    RM B,C中添加






# 十二. 微服务添加 Seata AT 分布式事务
## 1. Seata Server - TC 全局事务协调器
    A. 下载 https://github.com/seata/seata/releases
    B. 配置文件
        conf/registry.conf
            连接eureka注册中心
        conf/file.conf
            seata server 运行时记录日志的数据库
        bin/seata-server.bat
            降低虚拟机内存大小(默认2G)
    C. 启动
        双击 seata-server.bat
    
## 2. 业务中添加 Seata AT 事务
    A.依赖: 
        seata
    B.配置:
        application.yml    --事务组的组名
            spring.cloud.alibaba.seata.tx-service-group=order_tx_group
        registry.conf      --注册中心地址                   新建
            type=eureka
        file.conf          --事务组使用哪个协调器           新建
            vgroupMapping.order_tx_group(组名) = "seata-server"(协调器)    要使用的协调器 
    C.自动配置类
        创建数据源代理对象
        DSAutoConfiguration  @Configuration
            a. 注入数据源配置 yml中的datasource        
                @ConfigurationProperties(prefix = "spring.datasource")
            b. 数据源 @Bean
                new HikariDataSource();   
                hikari的url是jdbcUrl(修改yml添加jdbcUrl,datasource下jdbcUrl: ${spring.datasource.url})
            c. 数据源代理 @Bean
                new DataSourceProxy(dataSource);
            d. 指定注入spring哪个数据源对象
                @Primary  首选对象

                        数据源配置类
                        @Configuration
                        public class DSAutoConfiguration {
                        注入数据源配置 yml中的datasource
                            @ConfigurationProperties(prefix = "spring.datasource")
                        数据源
                        指定连接池 new HikariDataSource();
                            @Bean
                            public DataSource dataSource(){return new HikariDataSource();}
                        数据源代理
                            @Primary
                            @Bean
                            public DataSource dataSourceProxy(DataSource dataSource){return new DataSourceProxy(dataSource);}
                        }
            e. 排除spring默认数据源自动配置类,使用自己的 DSAutoConfiguration
                @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

    D.业务方法注解
        @Transactional  控制本地事务
        @GlobalTransactionsl   启动全局事务  seata提供
            业务模块创建TM 向TC 申请开启全局事务, TC 向 TM 发送 XID
            第一个模块中添加
        
        a. 本地事务注解 @Transactional   全局事务注解 @GlobalTransactional
            添加到 调用其他服务的服务 方法上
                @Transactional
                @GlobalTransactional
                public void create(Order order) {}  // 创建订单order 调用 account账户 和 storage库存

    E.被调用服务添加 Seata AT
        依赖 seata
        配置文件  application.yml  registry.conf  file.conf
        自动配置类
            数据源代理 DSAutoConfiguration
        启动类注解
            @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
        业务方法注解
            @Transactional 本地事务








# 十三. 分布式事务  TCC
    one. 每个阶段的数据操作要自己进行编码, 事务框架无法自动处理
    two. 效率高, 不对数据加全局锁, 允许多个事务同时操作数据
## 1. 基本原理
    A.第一阶段   
        Try --预留资源, 冻结数据
        例如: 先把要扣减的金额预留(冻结)出来    --要处理的数据我先拿出来放起来,执行完我再处理数据
        
    B.第二阶段   
        Confirm --确认/提交, 使用上一阶段预留的数据, 完成业务数据处理
        Cancel  --取消/回滚, 对第一阶段预留的数据, 再回复为原始数据



# 十四. 微服务添加 Seata TCC 分布式事务
## 1.使用Seata server

## 2.添加TCC事务
    A.依赖:
        seata
    B.配置文件
        application.yml
        registry.conf
        file.conf
    C.事务自己实现   不像at事务自动配置

    D.Mapper添加新的数据库操作
        Try --冻结数据   update
            向表中插入数据状态不可见
        Confirm --确认提交
        Cancel --取消,回滚
    E.按照seata定义的规则, 添加  TccAction接口
        添加TCC三个操作的方法,调用mapper的三个数据库操作
    F.业务方法中, 手动调用第一阶段方法
        全局事务 @GlobalTransactional

    D E F  步骤
        自己写代码执行冻结, 配置冻结操作的代码, 业务调用冻结方法
    
    G.第二阶段不需要手动执行
        @GolbalTransactional 全局事务  --在调用服务的服务上添加 一次, 被调用服务不需要添加
        二阶段就会自动执行

## 3.TCC 基本原理的实现(需要自己写代码实现)
    A.对数据库的操作, 具体业务代码, OrderMapper.xml中sql
    B.OrderTccAction接口,   两个阶段要实现的业务方法
        prepare()
        commit()
        rollback()
    C.接口实现类
        prepare()  执行   创建订单操作create()
        commit()   执行   更新订单状态操作 updateStatus()
        rollback() 执行   删除订单操作 deleteById()
    D.业务
        执行prepare()方法 --TCC的Try阶段

    E.问题 ???
        第一阶段:  手动执行了 prepare()
        第二阶段:  commit() 和 rollback() 怎么调用的

        解决: @GlobalTransactional create() 方法上
            两个阶段业务注解
            @TwoPhaseBusinessAction(name = "OrderTccAction",commitMethod = "commit",rollbackMethod = "rollback")

    
    F.幂等性控制
        防止重复提交/回滚
        官方案例,赋值粘贴


## 4.幂等性控制
    如果重复执行提交或回滚,    就执行一次,结果一样
    理解: 防止重复提交回滚,    重复执行,不执行二阶段

    解决: 使用标记, 二阶段判断有没有标记,没有标记就是执行完了
        ResultHolder










# 十五. RocketMQ  消息高可用  安装
    不使用 docker 运行, 直接在linux中运行

## 1. 搭建rocketmq服务
        jdk, jdk环境变量
        rocketmq文件, rocketmq环境变量, rocketmq减小服务(name-server,broker)内存, 启动

    A.需要的资源: 
        jdk1.8, rocketmq-all-4.7.0-bin-release, rocketmq-console-ng-1.0.1

    B.jdk1.8
        tar -xf jdk-8u212-linux-x64.tar.gz -C /usr/local/   解压

        vim /etc/profile                              jdk 配置文件修改, 在/usr/local下
        # 在文件末尾添加以下内容:
        export JAVA_HOME=/usr/local/jdk1.8.0_212
        export PATH=$JAVA_HOME/bin:$PATH

        source /etc/profile                             使环境变量生效
    
    C.rocketmq 二进制文件
        a.下载 wget https://mirror.bit.edu.cn/apache/rocketmq/4.7.0/rocketmq-all-4.7.0-bin-release.zip 

        b.解压缩
            unzip rocketmq-all-4.7.0-bin-release.zip -d /usr/local/

            # 修改一下文件夹名,改成 rocketmq 方便使用
            mv /usr/local/rocketmq-all-4.7.0-bin-release /usr/local/rocketmq

        c.配置环境变量 ROCKETMQ_HOME 和 PATH
            cd /usr/lcoal
            vim /etc/profile

            # 在文件末尾添加以下内容:
            export ROCKETMQ_HOME=/usr/local/rocketmq
            export PATH=$ROCKETMQ_HOME/bin:$PATH
        
        d.让环境变量立即生效
            source /etc/profile
        
        e.减小rocketqm使用的内存
            cd /usr/local/rocketmq/
            
            修改 name server 内存改为 256m

                                # 编辑 bin/runserver.sh
                                vim bin/runserver.sh

                                # 找到文件中下面这一行:
                                JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"

                                # 将 -Xms4g -Xmx4g -Xmn2g 修改为 -Xms256m -Xmx256m -Xmn128m
                                JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
            修改 broker 内存改为 256m
                                # 编辑 bin/runbroker.sh
                                vim bin/runbroker.sh

                                # 找到文件中下面这一行:
                                JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -Xmn4g"

                                # 将 -Xms8g -Xmx8g -Xmn4g 修改为 -Xms256m -Xmx256m -Xmn128m
                                JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m"
                            
        f.启动rocketmq

            先启动 name server

                # 进入 rocketmq 目录
                cd /usr/local/rocketmq/

                # 启动 name server
                nohup sh bin/mqnamesrv &

                # 查看运行日志, 看到"The Name Server boot success."表示启动成功
                tail -f ~/logs/rocketmqlogs/namesrv.log


            再启动 broker

                # 启动 broker, 连接name server: localhost:9876
                nohup sh bin/mqbroker -n localhost:9876 &

                # 查看运行日志, 看到"The broker[......:10911] boot success."表示启动成功
                tail -f ~/logs/rocketmqlogs/broker.log 

        g.关闭防火墙
            rocketmq的通信会用到多个端口, 为了方便测试我们关闭防火墙

            # 关闭防火墙
            systemctl stop firewalld.service

            # 禁止防火墙开机启动
            systemctl disable firewalld.service
        
        h.测试
            # 通过环境变量, 告诉客户端程序name server的地址
            export NAMESRV_ADDR=localhost:9876

            /usr/local/rocketmq

            # 启动生产者来测试发送消息
            sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer

            # 启动消费者来测试接收消息
            sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

        i.rocketmq命令
            关闭 broker
            mqshutdown broker

            关闭 nameserver
            mqshutdown namesrv
        
        j.收发消息出现超时问题
                cd /usr/local/rocketmq/

                vim conf/broker.conf

                末尾添加
                brokerIP1=192.168.64.141

                关闭 broker 服务
                mqshutdown broker

                重新使用 broker.conf 配置启动 broker
                nohup sh bin/mqbroker -n localhost:9876 -c conf/broker.conf &


    D.进程查看是否运行
        jps


## 2. rocketmq注册中心,消息服务
    name server --rocketmq的注册中心
        内存 4G
    broker      --消息服务,消息中间件
        内存 8G

## 3.管理界面
    在开源项目 rocketmq-externals 中提供了rocketmq 的管理界面: 地址为: https://github.com/apache/rocketmq-externals
    github 在国内访问缓慢, 也可以使用码云的镜像项目, 地址为: https://gitee.com/mirrors/RocketMQ-Externals

    A.克隆项目
        cd /usr/local/rocketmq/

        # 克隆 rocketmq-externals 项目
        git clone https://gitee.com/mirrors/RocketMQ-Externals
    B.maven打包
        yum install -y maven

        # 进入管理界面项目的文件夹
        cd RocketMQ-Externals/rocketmq-console

        # 执行maven 打包命令, 执行时间较长, 请耐心等待
        mvn clean package -Dmaven.test.skip=true

    C.运行启动
        # 运行管理界面
        nohup java -jar rocketmq-console-ng-1.0.1.jar --server.port=8080 --rocketmq.config.namesrvAddr=localhost:9876 & 

    D.访问
        http://192.168.64.141:8080


# 十六. rocketmq 
## yi. 双主双从 同步赋值集群方案

## er. 基本原理

Topic  集群服务器
    A.生产者负载均衡
        轮循
    B.消费者负载均衡
        AllocateMessageQueueAveragely 平均分配             11,22,33
        AllocateMessageQueueAveragelyByCircle 环形分配     1,2,3,1,2,3

## san. rocketmq 原生 API 
### 0.module
    依赖: rocketmq-store, rocketmq-client
### 1.同步消息
    A.主从复制: 生发消息, 向消复制, 消返回给生
    B.生产者
        * 创建生产者, 设置 name server     ---new DefaultMQProducer("producer1")
        * 连接服务器, 启动, (从注册表中的地址连接消费者)    ---producer1.setNamesrvAddr("192.168.64.141:9876"); producer1.start();
        * 消息封装 Message    ---new Message("Topic1","Tag1",str.getBytes());
        *      Topic  --相当于一级分类     Tag    --相当于二级分类
        * 发送消息  ---producer1.send(message);
        *      返回结果 [topic=Topic1(目录), brokerName=localhost.localdomain, queueId=3(消息序列id)], queueOffset=0(消息下标)]
    C.消费者
        * 创建消费者   ---new DefaultMQPushConsumer("consumer1");
        * 设置name server   ---consumer1.setNamesrvAddr("192.168.64.141:9876");
        * 从哪里订阅消息   ---consumer1.subscribe("Topic1","Tag1");     Tag1 或 * 或 Tag1 || Tag2 || Tag3
        * 处理消息的监听器   ---consumer1.setMessageListener(new MessageListenerConcurrently(){}--启动多个线程, 并发的处理消息)
        *      new MessageListenerConcurrently() {public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
        *                 for (MessageExt messageExt : list) {
        *                     String s = new String(messageExt.getBody());
        *                     System.out.println("收到"+s);
        *                 }
        *                 return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;  // 成功
        * //                return ConsumeConcurrentlyStatus.RECONSUME_LATER; // 稍后会收到
        *             }
        * 启动消费者   ---consumer1.start();
    D.计时消息--延时消息
        判断消息时间

### 2.异步消息
    主从复制: 生发消息, 向消复制,同时返回给自己,    
    生产者
    消费者
### 3.单向消息
    生产者
    消费者
### 4.顺序消息
    A.消费者接收消息的顺序
        问题: 发送时,放到队列中(轮循放), 多个队列(存放位置),多个线程(处理的快慢)   (rocketmq 一个队列由一个消费者接收消息)    消费者接收到的消息 顺序就乱了
        解决: 把消息发送到一个队列 且 消费者由一个线程处理
    B.生产者   ---发送消息到同一个 消息序列
        * 设置队列选择器
        * producer2.send(message, new MessageQueueSelector() {}, orderId);  // 参数: message-给Selector->message, 队列选择器, 选择依据-给Selector->object
        * new MessageQueueSelector() {public MessageQueue select(List<MessageQueue> list, Message message, Object o) {  
        * // 参数: 服务器端队列列表, 正要发送的消息, 队列选择依据
        *   Long orderId = (Long) o;  int index = (int) (orderId % list.size());  return list.get(index); }
    C.消费者   ---单线程接收消息
        * 设置监听器(单线程)
        *      consumer2.setMessageListener(new MessageListenerOrderly() {}) //MessageListenerOrderly()启动的是一个单线程
         * new MessageListenerOrderly() {public ConsumeOrderlyStatus consumeMessage(List<MessageExt> list, ConsumeOrderlyContext consumeOrderlyContext) {
         *    for (MessageExt messageExt : list) {System.out.println("收到"+new String(messageExt.getBody()));}
         *    return ConsumeOrderlyStatus.SUCCESS;}
### 5.延时消息
    A.生产者发送消息之前, 进行延时,  一段时间后消费者才能收到消息
    B.时间级别
        this.messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h";

    生产者   ---message.setDelayTimeLevel(3);
    消费者
### 6.批量消息
    生产者
    消费者
### 7.消息过滤
    Tag 过滤
    对自定义属性过滤
    生产者
    消费者
### 8.事务消息  高可靠消息
    A.异步调用, 两个模块之间实现异步调用
    事务消息的原理
        发送者: 1.发送本消息(不会给消费者) 2.执行本地事务 3.提交消息
        消费者: 接收消息不允许失败, 失败会一直重试18次, 最后不行成为死消息-人工处理

    发送者: 1.发送本消息(不会给消费者) 2.执行本地事务 3.提交消息
        * 创建事务消息产生者, 设置nameserver
        *      ---new TransactionMQProducer("producer3");
        *      
        * 设置事务消息监听器 --执行本地事务, 处理服务器的回查
        *      ---producer3.setTransactionListener(new TransactionListener() {})
        * new TransactionListener() {
        *   @Override // 执行本地事务
        *   public LocalTransactionState executeLocalTransaction(Message message, Object o) {
        *   System.out.println("执行本地事务, 参数: "+message);
        *   if (Math.random()<0.5){System.out.println("本地事务执行成功"); return LocalTransactionState.COMMIT_MESSAGE;
        *   }else {System.out.println("本地事务执行失败");return LocalTransactionState.ROLLBACK_MESSAGE;}}
        *
        *    @Override  // 回查
        *    public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
        *    System.out.println("处理服务器网络中断");return LocalTransactionState.UNKNOW;}}
        *    
        * 启动
        * 发送事务消息, 会触发监听器来执行本地事务
        *      ---  producer3.sendMessageInTransaction(message,"执行本地事务的参数数据");
        *
    消费者: 接收消息不允许失败, 失败会一直重试18次, 最后不行成为死消息-人工处理
        System.out.println("处理消息成功");
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        System.out.println("处理消息失败");
        return ConsumeConcurrentlyStatus.RECONSUME_LATER;







# 十七. spirng boot 订单案例 整合 rockermq
## 1. model
    依赖: rocketmq
        rocketmq-spring-boot-starter 
    yml: name server, 生产者组组名
        rocketmq:
            name-server: 192.168.64.141:9876
            producer:
                group: order-producer
    数据库表: tx_table 记录事务执行的状态
    业务: TxInfo, TxMapper  --insert, select  记录事务执行状态,应对回查
    message: 封装消息数据的 AccountMeaage对象
    工具: 添加JsonUtil工具, 处理消息数据的格式转换
    业务代码: 先执行发送消息, 再执行订单业务
        create(Order order){
            rocketMQTemplate.sendMessageInTransaction("order-topic", msg, order); 
        }
    监听器: 执行本地事务(存储订单), 事务状态回查





#https://blog.youkuaiyun.com/weixin_38305440/article/details/108609574?spm=1001.2014.3001.5502










# 零. 知识点
## application.yml中的 profile
    springboot项目中的一小段配置, 可选择是否使用
    主配置: 提取配置共性
    profile: 相同配置属性,不同属性值
> application.yml

    server:
        port: 8001
    
    # 项目使用 prof1
    # yml中 主配置和prof1配置合并使用
    spring:
        profiles:
            active: prof1

    # profile配置
    # 启动项目时加载profile  java -jar a.jar --spring.profiles.active=prof1
    --- (三个行线之间写profile配置)
    spring:
        profiles: prof1
    eureka:
        instance:
            hostname: eureka
        client:
            register-with-eureka: true  #profile的配置会覆盖公用配置
            fetch-registry: true        #profile的配置会覆盖公用配置
            service-url:
                defaultZone: http://eureka1:2001/eureka  #eureka启动时向eureka1注册
    ---

> profile 配置名

    dev, test, prod, 

## 上下文对象  Context
    Spring Context, Spring 上下文对象, 对象池
        创建的所有对象, 实例
    程序中 通用/共用 资源 (各个组件中要使用的数据)

## bootstartp.yml 和 application.yml
    bootstrap.yml     引导配置  
    application.yml   应用配置

    优先级:   bootstrap.yml > application.yml > tomcat服务 > 


### 回答1: "Mit-Cheetah-Note"是一种学习辅助工具,旨在提高学生的学习效率和效果。它结合了MIT(麻省理工学院)的学习方法和猎豹速读技术。 首先,MIT-Cheetah-Note采用了麻省理工学院的学习方法。这些方法包括主题导图,问题解决和概念联系等。主题导图是一种可视化的学习工具,帮助学生整理和理解知识点之间的关系。问题解决则鼓励学生通过提出问题来主动思考和深入理解知识。概念联系是通过将新知识与已有知识相结合,加深学生对知识的理解。 其次,这个学习工具还集成了猎豹速读技术。速读是一种训练阅读效率和记忆力的技巧。通过使用猎豹速读技术,学生可以提高阅读速度和理解能力。这对于大量阅读任务的学生来说尤其有用,如备考、论文写作等。 MIT-Cheetah-Note采用了数码笔和智能设备相结合的方式进行学习记录和储存。学生可以使用数码笔在纸上做笔记,并通过智能设备将这些笔记同步到云端。这样一来,学生可以随时随地访问他们的学习记录,从而更好地回顾和复习。 总而言之,MIT-Cheetah-Note是将麻省理工学院的学习方法和猎豹速读技术融入一体的学习辅助工具。它帮助学生提高学习效率和效果,并通过数字化技术方便学生的学习记录和辅助复习。 ### 回答2: Mit-Cheetah-Note 是一种人工智能语音助手,最初由麻省理工学院(MIT)研发。该技术基于深度学习和自然语言处理,在提供智能语音交互的同时,还具备类似于记事本的功能。 Mit-Cheetah-Note 可以用于多个方面,例如记录会议笔记、制定待办事项、管理日程安排等。用户可以通过语音指令来创建笔记,编辑文本内容或者提醒自己日程。Mit-Cheetah-Note 还能理解自然语言,对语音指令做出准确的响应,从而提高用户的工作效率。 与其他语音助手相比,Mit-Cheetah-Note 的特点是其记事本功能。用户可以通过语音输入方式,较快地记录需要记下的信息,而无需手动键入。此外,Mit-Cheetah-Note 还有一个方便的搜索功能,可通过关键词搜索用户之前创建的笔记内容,帮助用户快速找到所需的信息。 Mit-Cheetah-Note 可以应用于多种场景,如商务会议、学术讲座、个人笔记等。它不仅可以减少记笔记的时间和工作量,还可以提高笔记的准确性和完整性。 总之,Mit-Cheetah-Note 是一种集成了语音助手和记事本功能的人工智能技术,使用户能够通过语音指令快速记录信息和管理日程,提高工作效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值