• AlibabaCloud入坑笔记


    Nacos注册中心

    服务端安装

    官网下载地址:https://nacos.io/zh-cn/docs/quick-start.html

    解压安装包
    进入bin目录
    单机模式启动 sh startup.sh -m standalone
    访问 localhost:8848/nacos
    默认账号密码 nacos/nacos

    客户端注册与发现

    1. 添加nacos的依赖
            <!--添加nacos客户端-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
    
    
    2. 在配置文件指定注册中心地址
    spring:
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
    
    
    3. 在启动类用注解开启服务注册
    @EnableDiscoveryClient

    统一配置中心

    1. 添加代码配置

    1. 加入依赖
        <!--统一配置中心-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            </dependency>
    
    
    2. 配置bootstrap.yml  (它的优先级比application.yml高)
    spring:
      application:
        name: order-service #在noas的名称
      cloud:
        nacos:
          config:
            server-addr: 192.168.200.100:8848 #Nacos配置中心地址
            file-extension: yaml #文件拓展格式
            group: risk #分组,一般用来区分不同的服务
            namespace: test #命名空间,用来区分不同环境(默认是public)
      #profiles:
      #  active: dev  

    2. 先新建命名空间,命名空间id和namespace保持一致;配置文件名称和服务名称一致;grop也保持一致。

    3. 通过url查看配置是否生效   http://192.168.200.100:8848/nacos/v1/cs/configs?dataId=order-service.yaml&group=risk&tenant=test

    4. 代码里面通过   @RefreshScope   动态刷新Nacos配置

    Feign远程调用

    1. 引入依赖包
            <!--引入feign-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
    
    
    2. 在主函数开启feign
    @EnableFeignClients
    
    
    3. 编写远程调用接口(指定好其他服务的注册名称和路径)
    @FeignClient(value = "video-service",path = "/video")
    public interface VideoFeign {
        @RequestMapping("find_by_id")
        JsonResult findById(@RequestParam("videoId") int videoId);
    }
    
    
    4. 不设置也可以(feign默认1s超时,我们这里设置为5s)
    ribbon:
      ReadTimeout: 5000 #超时时间
      ConnectTimeout: 5000 #连接时间
      MaxAutoRetries: 0 #同一台实例最大重试次数,不包括首次调用
      MaxAutoRetriesNextServer: 0 #重试负载均衡其他的实例最大重试次数,不包括首次调用
      OkToRetryOnAllOperations: false  #是否所有操作都重试

    熔断降级

    1. 导入依赖
            <!--引入sentinel-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
    
    
    2. 开启Feign对Sentinel的支持
    feign:
      sentinel:
        enabled: true
    
    
    3. 配置feign容错类
    @FeignClient(value = "video-service",path = "/video", fallback = VideoServiceFallback.class)
    public interface VideoFeign {
    
    
    4. 创建容错类, 实现容错逻辑, 记得加注解 @Service
    @Service
    public class VideoServiceFallback implements VideoFeign {
        @Override
        public JsonResult findById(int videoId) {
            return JsonResult.error("feign的url错误,走了fallback");
        }
    }

    Sentinel流量哨兵

    中文文档    https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

    -Dserver.port=8080 控制台端口,sentinel控制台是一个spring boot程序,指定启动端口。
    -Dcsp.sentinel.dashboard.server=localhost:8080 指把控制台后当作一个客户端,然后自动向该地址发送心跳包。
    -Dproject.name=sentinel-dashboard 指定Sentinel控制台程序的名称

    启动

    nohup java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.0.jar &

    访问 localhost:8080

    默认账号密码 sentinel/sentinel

    客户端接入

    1. 导入依赖
            <!--引入sentinel-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
    
    
    2. 添加注册地址
    spring:
      cloud:       
        sentinel:
          transport:        
            port: 9999 #跟控制台交流的端口,随意指定一个未使用的端口即可,不同的服务用不同的端口     
            dashboard: localhost:8080 # 指定控制台服务的地址

    默认是懒加载的,启动后,我们调用先服务接口,然后刷新
    sentinel 面板就能看到了
    
    

    流控规则

    在簇点链路里面根据url配置,我们这是事根据qps来限流,然后快速刷新浏览器就会出现失败提示了。

    熔断降级

    慢调用比例(响应时间): 选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用
      比例阈值:修改后不生效(这是一个bug,期待官方后续修复)
      熔断时长:超过时间后会尝试恢复
      最小请求数:熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断
    异常比例:当单位统计时长内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断
      比例阈值
      熔断时长:超过时间后会尝试恢复
      最小请求数:熔断触发的最小请求数,请求数小于该值时,即使异常比率超出阈值也不会熔断
    异常数:当单位统计时长内的异常数目超过阈值之后会自动进行熔断
      异常数:
      熔断时长:超过时间后会尝试恢复
      最小请求数:熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断

    自定义异常降级

    现在失败后,默认都是返回     Blocked by Sentinel (flow limiting)     字符串,比较不容易排查。我们可以自定义项目数据交互格式。AlibabCloud版本升级,自从v2.1.0到v2.2.0后就出现了不兼容问题。

    • 【旧版】实现UrlBlockHandler并且重写blocked方法
    @Component
    public class BaseUrlBlockHandler implements UrlBlockHandler {
        @Override
        public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws IOException {
           //降级业务处理
        }
    }
    • 【新版】实现BlockExceptionHandler并且重写handle方法
    import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
    import com.alibaba.csp.sentinel.slots.block.BlockException;
    import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
    import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
    import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
    import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
    import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
    import com.alibaba.fastjson.JSON;
    import org.springframework.stereotype.Component;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.HashMap;
    import java.util.Map;
    @Component
    public class BaseBlockExceptionHandler implements BlockExceptionHandler {
    
        @Override
        public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
    
            Map<String,Object> info = new HashMap<>();
            if(e instanceof FlowException){
                info.put("code",-1);
                info.put("msg","限流异常");
            }
            else if(e instanceof DegradeException){
                info.put("code",-2);
                info.put("msg","降级异常");
            }
            else if(e instanceof ParamFlowException){
                info.put("code",-3);
                info.put("msg","热点参数异常");
            }
            else if(e instanceof SystemBlockException){
                info.put("code",-4);
                info.put("msg","系统异常");
            }
            else if(e instanceof AuthorityException){
                info.put("code",-5);
                info.put("msg","授权异常");
            }
            //设置json返回
            httpServletResponse.setStatus(200);
            httpServletResponse.setHeader("content-type","application/json;charset=UTF-8");
            httpServletResponse.getWriter().write(JSON.toJSONString(info));
        }
    }

     

    gateway网关

    动态路由

    1. 添加依赖
            <!--添加gateway-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
    
    
    
    2. 配置路由规则
    server:
      port: 7100
    
    spring:
      application:
        name: api-gateway
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true  #开启网关拉取nacos的服务
          routes: #数组形式
            - id: order-service  #路由唯一标识
              uri: lb://order-service  #从nocas进行转发到指定服务
              #order: 1 #优先级,数字越小优先级越高
              predicates: #断言 配置路由规则
                - Path=/order/**
              filters: #过滤器,请求在传递过程中通过过滤器修改
                - StripPrefix=1  #转发到具体服务时候,自动去掉第一层前缀(predicates的第一层地址)
            - id: video-service
              uri: lb://video-service
              predicates:
                - Path=/video/**
              filters:
                - StripPrefix=1
        nacos:
          discovery:
            server-addr: 192.168.200.100:8848 # nacos的地址
      zipkin:
        base-url: http://192.168.200.100:7200/ #zipkin地址
        discovery-client-enabled: false  #不用开启服务发现
        sleuth:
          sampler:
            probability: 1.0 #采样百分比

    过滤器

    import org.apache.commons.lang3.StringUtils;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.http.HttpStatus;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    /**
     * 网关不要加太多业务逻辑,否则会影响性能
     */
    @Component
    public class TestFilter implements GlobalFilter, Ordered {
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            System.out.println("TestFilter。。。。。。");
            //写业务逻辑
            String token = exchange.getRequest().getHeaders().getFirst("token");
    
            if(StringUtils.isBlank(token)){
                //停止请求
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            //继续往下执行
            return chain.filter(exchange);
        }
    
        //数字越小,优先级越高
        @Override
        public int getOrder() {
            return 0;
        }
    }

    链路追踪

    Sleuth链路追踪

    1. 各个微服务添加依赖
    
    <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-sleuth</artifactId>
    </dependency>


    参数解析:

    [order-service,6f3487a81c89682e,7db08a9ad1ea24d6,false]
    第一个值,spring.application.name的值
    第二个值,6f3487a81c89682e,sleuth生成的一个ID,叫Trace ID,用来标识一条请求链路,一条请求链路中包含一个Trace ID,多个Span ID
    第三个值,7db08a9ad1ea24d6、spanid 基本的工作单元,获取元数据,如发送一个http
    第四个值:false,是否要将该信息输出到zipkin服务中来收集和展示。

    然后进行链路调用的时候,就会出现如下日志了:

    zipkin仪表盘

    安装与持久化

    1. 官网以及服务端下载    https://zipkin.io/pages/quickstart.html

    2. 启动服务端    默认端口是9411  可以通过    http://127.0.0.1:9411/zipkin/    进行访问

      java -jar zipkin-server-2.12.9-exec.jar

    3. 持久化

      日志数据默认是存在内存中的,zipkin重启后数据就没了。我们可以持久化到mysql、es 中。

    --STORAGE_TYPE    指定外部存储源 mysql/es
    --MYSQL_HOST      mysql地址
    --MYSQL_TCP_PORT  数据库端口
    --MYSQL_DB        数据库名称
    --MYSQL_USER      账号
    --MYSQL_PASS      密码
    
    nohup java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin_log --MYSQL_USER=root --MYSQL_PASS=root &
    CREATE TABLE IF NOT EXISTS zipkin_spans (
      `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
      `trace_id` BIGINT NOT NULL,
      `id` BIGINT NOT NULL,
      `name` VARCHAR(255) NOT NULL,
      `remote_service_name` VARCHAR(255),
      `parent_id` BIGINT,
      `debug` BIT(1),
      `start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
      `duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query',
      PRIMARY KEY (`trace_id_high`, `trace_id`, `id`)
    ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
     
    ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds';
    ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames';
    ALTER TABLE zipkin_spans ADD INDEX(`remote_service_name`) COMMENT 'for getTraces and getRemoteServiceNames';
    ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range';
     
    CREATE TABLE IF NOT EXISTS zipkin_annotations (
      `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
      `trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
      `span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id',
      `a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
      `a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB',
      `a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
      `a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
      `endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null',
      `endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
      `endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null',
      `endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null'
    ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
     
    ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate';
    ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans';
    ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds';
    ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames';
    ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces and autocomplete values';
    ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces and autocomplete values';
    ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job';
     
    CREATE TABLE IF NOT EXISTS zipkin_dependencies (
      `day` DATE NOT NULL,
      `parent` VARCHAR(255) NOT NULL,
      `child` VARCHAR(255) NOT NULL,
      `call_count` BIGINT,
      `error_count` BIGINT,
      PRIMARY KEY (`day`, `parent`, `child`)
    ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
    zipkin_log

    启动客户端

    1. 加入依赖
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zipkin</artifactId>
    </dependency>
    
    
    2.
    配置地址和采样百分比配置
    spring:
      application:
        name: api-gateway
      zipkin:
        base-url: http://127.0.0.1:9411/ #zipkin地址
        discovery-client-enabled: false  #不用开启服务发现
      sleuth:
        sampler:
          probability: 1.0 #采样百分比 

    默认为0.1,即10%,这里配置1,是记录全部的sleuth信息,是为了收集到更多的数据(仅供测试用)。在分布式系统中,过于频繁的采样会影响系统性能,所以这里配置需要采用一个合适的值。

     请求过后,直接可以在面板就能看到  链路详细信息 了。

     

  • 相关阅读:
    汉字编码问题
    C语言创建UTF8编码文本文件
    Know more about shared pool subpool
    SCN Headroom与时光倒流到1988年的Oracle数据库
    Know more about Enqueue Deadlock Detection
    11g新特性:RDBMS Component TRACE
    了解你所不知道的SMON功能(十一):OFFLINE UNDO SEGMENT
    了解11g OCM
    Bulk Collect/FORALL的性能测试
    【推荐】DBA必须了解的11g中的一些变化
  • 原文地址:https://www.cnblogs.com/wlwl/p/14085708.html
Copyright © 2020-2023  润新知