Springcloud HR1版本各组件得搭建简要记录

原文档得格式不合适CSDN,需要逐个调整,有需要的留言即可

1、简介
1.1父工程依赖

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wyq.springcloud</groupId>
    <artifactId>cloud2020</artifactId>
    <version>1.0-SNAPSHOT</version>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
    </dependencies>
    <packaging>pom</packaging>

    <!--统一管理jar包版本-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.18.10</lombok.version>
        <mysql.version>8.0.18</mysql.version>
        <druid.version>1.1.16</druid.version>
        <mybatis.spring.boot.version>2.1.1</mybatis.spring.boot.version>
    </properties>

    <!--子模块继承之后,提供作用:锁定版本+子module不用写groupId和version-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-project-info-reports-plugin</artifactId>
                <version>3.0.0</version>
            </dependency>
            <!--spring boot 2.2.2-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud Hoxton.SR1-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud 阿里巴巴-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
                <scope>runtime</scope>
            </dependency>
            <!-- druid-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.spring.boot.version}</version>
            </dependency>
            <!--junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <!--log4j-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
        </dependencies>

    </dependencyManagement>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-site-plugin</artifactId>
                <configuration>
                    <locales>en,fr</locales>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

1.2 业务模块的基础依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.wyq.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>demo</artifactId>

    <dependencies>
       
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--监控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

1.3 各服务组件pom依赖清单
<!--eureka注册中心-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

<!--openfeign服务调用-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<!--hystrix 断路器,服务熔断,降级-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

<!--hystrix-dashboard 断路器监控-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

<!--gateway 网关-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<!--bus 消息总线-->
<!--rabbitMQ-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<!--kafka-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>

<!--stream 消息驱动-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>

<!-- 包含了sleuth和zipkin  链路追踪 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-zipkin</artifactId>
</dependency>

1.4 第三方依赖服务
1.rabbitMQ或kafka
2.zipkin服务
3.restTemplate
2、服务注册与发现
2.1、Eureka
2.1.1、简介
Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。

2.1.2、eureka-server
提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到

  1. pom配置
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

  1. Yml配置
eureka:
  instance:
    hostname: eureka7001.com #euraka服务端实例名称
  client:
    register-with-eureka: false   #不向注册中心注册自己
    fetch-registry: false  #自己时注册中心
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka
  server:
    #自我保护机制,默认true;开发环境关闭,生产环境要开启,k8环境中建议不要开启,网络稳定环境中也建议不开启
    #关闭自我保护机制,保证不可用的服务被及时剔除
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 2000
  1. 启动类配置
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {

    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class,args);
    }
}

2.2.3、eureka-client
是一个java客户端,用于简化与eureka-server的交互,客户端同时也就是一个内置的、使用轮询(round-robin)负载算法的负载均衡器。

  1. pom配置
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

  1. Yml配置
eureka:
  instance:
    instance-id: payment8001
    #访问路径可以显示IP地址
    prefer-ip-address: true
    #发送心跳的间隔时间:秒
    lease-renewal-interval-in-seconds: 1
    #服务端收到心跳后等待的时间:秒
    lease-expiration-duration-in-seconds: 2
  client:
    #是否将自己注册进eureka-server 默认true
    register-with-eureka: true
    #是否从eureka-server抓取自己已有的注册信息,默认true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    #注册的服务的地址
    service-url:
      #单机配置
      #defaultZone: http://localhost:7001/eureka
      #集群配置
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
  1. 启动类配置
@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8001{
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class,args);
    }
}

3、服务调用
3.1 Ribbon+restTemplate
1)ribbon负载均衡策略配置

@Configuration
public class RibbonRuleConfig {

    @Bean
    public IRule ruleConfig(){
        return new RandomRule();//随机
//        return new RoundRobinRule();//轮询
//        return new RetryRule();//先按照RoundRobinRule获取服务,如服务失败则在指定时间内重试
//        return new WeightedResponseTimeRule();// 对RoundRobinRule的扩展,响应越快的实例选择的权重更大
//        return new BestAvailableRule();//先过滤掉由于多次访问故障而处于断路器跳闸的服务,然后选择一个并发量最小的服务
//        return new AvailabilityFilteringRule();//先过滤掉故障实例,在选择并发较少的实例
//        return new ZoneAvoidanceRule();//默认规则,符合判断server所在区域的性能和server的可用性选择服务器
    }
}

2)restTemplate配置

@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

3)启动类配置

/*
 * @Author:wuyongqiang
 * @Date:2021-01-04 15:20:15:20
 */
//对于单个服务设置自定义的负载均衡策略,且改自定义配置类不能位于启动类的下层package内,否则会被分布式架构共享
@RibbonClient(name = "CLOUD-CONSUMER-ORDER-80",configuration = RibbonRuleConfig.class)
@EnableEurekaClient
@SpringBootApplication
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }
}

4)调用示例

@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {

    public static final String createurl = "http://CLOUD-PROVIDER-PAYMENT/payment/create";
    public static final String selecturl = "http://CLOUD-PROVIDER-PAYMENT/payment/selectOneById/";


    @Autowired
    private RestTemplate restTemplate;

    @PostMapping("/create")
    public CommonResult<Payment> create(Payment payment){
        return restTemplate.postForObject(createurl+"",payment,CommonResult.class);
    }

    @GetMapping("/selectOneById/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id")Long id){
        String url =selecturl+id;
        return restTemplate.getForObject(url,CommonResult.class);
    }
}

3.2 Feign+Ribbon
1)Feign监控配置

@Configuration
public class FeignLogLevelConfig {

    @Bean
    Logger.Level feignLogLevelConfig(){
        return Logger.Level.FULL;
    }
//     * No logging.
//    NONE,
//     * Log only the request method and URL and the response status code and execution time.
//    BASIC,
//     * Log the basic information along with request and response headers.
//    HEADERS,
//     * Log the headers, body, and metadata for both requests and responses.
//    FULL
}

2)YML配置

#设置feign客户端的超时时间(feign默认集成了ribbon)
ribbon:
  #建立连接需要的时间,适用于网络状况正常的前提下,两端连接需要的时间
  ReadTimeout: 2000
  #建立连接后服务器读取到所需资源所用的时间
  ConnectTimeout: 2000

3)启动类配置

@EnableFeignClients//开启Feign服务调用
@SpringBootApplication
public class OrderFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderFeignMain80.class,args);
    }
}

4)调用示例

@RestController
@Slf4j
public class OrderFeignController {
    @Value("${server.port}")
    private String serverPort;

    @Autowired
    private PaymentFeignService paymentFeignService;

    @GetMapping("/order/feign/selectOne/{id}")
    public CommonResult<Payment> getSelectOneById(@PathVariable("id") Long id){
        Payment payment = paymentFeignService.aaa(id);
        if(payment!=null){
            return  new CommonResult(200,"feign success"+serverPort,payment);
        }else{
            return  new CommonResult(444,"feign fail"+serverPort,null);
        }
    }
}
@Component
@FeignClient(value = "CLOUD-PROVIDER-PAYMENT")//指明调用的服务
public interface PaymentFeignService {

    @GetMapping("/payment/selectOneById/{id}")//指明调用的url
    public Payment aaa(@PathVariable("id") Long id);//保证方法的参数和返回值与调用接口一致即可,本地方法名无所谓

4、断路器(服务降级,熔断,限流)

4.1、Hystrix
4.1.1 介绍
是一个用来处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等;保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,提高分布式系统的弹性。
本身是一种开关装置,当某个服务单元发生故障以后,通过断路器的故障监控(类似于熔断保险丝),向调用方法返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间,不必要的占用,从而避免了故障在分布式系统中蔓延,乃至雪崩。

服务降级

触发场景:程序运行异常、超时、服务熔断触发服务降级、线程池/信号量打满也会导致服务降级,不让客户端等待,立即返回一个友好提示页面。

服务熔断

触发场景:服务达到最大的访问量以后,调用服务降级的方法,具有自动恢复服务的作用。

服务限流

触发场景:秒杀高并发等操作,严禁请求一起过来,大家排队,一秒执行N个,有序执行。

4.1.2 生产者配置(单个接口)
1)pom依赖配置

<!--hystrix -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

2)启动类配置

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker//启用断路器
public class PaymentHystrix8003 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrix8003.class,args);
    }
}

3)业务接口配置示例

@Service
public class PaymentService {
    /**
     * 运行超时 代码运行异常,服务调用超时会触发断路器回调
     * @param id
     * @return
     */
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
//服务调用时间
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    public String paymentInfo_TimeOut(Integer id){
        int time = id;
        try {
            TimeUnit.SECONDS.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "线程池:"+Thread.currentThread().getName()+"paymentInfo_ok,id:"+id+"\t"+"耗时:"+time+"秒";
    }
    //回调方法的参数必须与业务方法相同
    public String paymentInfo_TimeOutHandler(Integer id){
        return "线程池:"+Thread.currentThread().getName()+"paymentInfo_TimeOutHandler,超时降级";
    }
}

4.1.3 消费者配置(单个接口)
1)pom依赖配置

<!--hystrix -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

2)yml配置

#断路器负载均衡配置
feign:
  hystrix:
    enabled: true

3)启动类配置

@EnableHystrix
@SpringBootApplication
public class OrderHystrixMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderHystrixMain80.class,args);
    }
}

4)业务controller配置示例

  @GetMapping("/order/hystrix/timeout/{id}")
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
//服务调用时间
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    public String paymentInfo_timeout(@PathVariable("id") Integer id){
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return  orderService.paymentInfo_timeout(id);
    }
    //回调方法的参数必须与业务方法相同
    public String paymentInfo_TimeOutHandler(Integer id){
        return "线程池:"+Thread.currentThread().getName()+"paymentInfo_TimeOutHandler,超时降级";
    }

4.1.4 消费者全局配置(service层)
针对fe’gin组件调用接口,写实现类来回调方法,不用在controller接口写@DefaultProperties和@HystrixCommand

/*
 * @Author:wuyongqiang  消费者调用生产者支付接口
 * @Date:2021-01-08 16:05:16:05
 */
@Component
@FeignClient(value = "CLOUD-PROVIDER-PAYMENT-HYSTRIX-8003",
fallback = OrderServiceFallBackImpl.class)
public interface OrderService {

    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_timeout(@PathVariable("id")Integer id);
}
/*
 * @Author:wuyongqiang
 * @Date:2021-01-11 10:25:10:25
 */
@Component
public class OrderServiceFallBackImpl implements  OrderService{

    @Override
    public String paymentInfo_timeout(Integer id) {
        return "生产者服务不可用,全局配置实现类,超时降级";
    }
}

4.1.5 服务降级-commandProperties
示例:

@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})

Hystrix 的命令属性是由 @HystrixProperty 注解数组构成的,
HystrixProperty 由 name 和 value 两个属性,数据类型都是字符串。
以下将所有的命令属性分组来介绍。
线程隔离(Isolation)
execution.isolation.strategy: 配置请求隔离的方式,有 threadPool(线程池,默认)和 semaphore(信号量)两种,信号量方式高效但配置不灵活,我们一般采用 Java 里常用的线程池方式。
execution.timeout.enabled:是否给方法执行设置超时,默认为 true。
execution.isolation.thread.timeoutInMilliseconds:方法执行超时时间,默认值是 1000,即 1秒,此值根据业务场景配置。
execution.isolation.thread.interruptOnTimeout: execution.isolation.thread.interruptOnCancel:是否在方法执行超时/被取消时中断方法。需要注意在 JVM 中我们无法强制中断一个线程,如果 Hystrix 方法里没有处理中断信号的逻辑,那么中断会被忽略。
execution.isolation.semaphore.maxConcurrentRequests:默认值是 10,此配置项要在 execution.isolation.strategy 配置为 semaphore 时才会生效,它指定了一个 Hystrix 方法使用信号量隔离时的最大并发数,超过此并发数的请求会被拒绝。信号量隔离的配置就这么一个,也是前文说信号量隔离配置不灵活的原因。

4.1.6 服务熔断-commandProperties
示例:

@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",
commandProperties = {
        @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),//是否启用断路器
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),//最小请求次数
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "5000"),//经过多长时间允许一次请求尝试执行
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),//请求失败比例达到多少执行熔断
})

circuitBreaker.enabled:是否启用熔断器,默认为 true;
circuitBreaker.forceOpen: circuitBreaker.forceClosed:是否强制启用/关闭熔断器,强制启用关闭都想不到什么应用的场景,保持默认值,不配置即可。
circuitBreaker.requestVolumeThreshold:启用熔断器功能窗口时间内的最小请求数。试想如果没有这么一个限制,我们配置了 50% 的请求失败会打开熔断器,窗口时间内只有 3 条请求,恰巧两条都失败了,那么熔断器就被打开了,5s 内的请求都被快速失败。此配置项的值需要根据接口的 QPS 进行计算,值太小会有误打开熔断器的可能,值太大超出了时间窗口内的总请求数,则熔断永远也不会被触发。建议设置为 QPS * 窗口秒数 * 60%。
circuitBreaker.errorThresholdPercentage:在通过滑动窗口获取到当前时间段内 Hystrix 方法执行的失败率后,就需要根据此配置来判断是否要将熔断器打开了。 此配置项默认值是 50,即窗口时间内超过 50% 的请求失败后会打开熔断器将后续请求快速失败。
circuitBreaker.sleepWindowInMilliseconds:熔断器打开后,所有的请求都会快速失败,但何时服务恢复正常就是下一个要面对的问题。熔断器打开时,Hystrix 会在经过一段时间后就放行一条请求,如果这条请求执行成功了,说明此时服务很可能已经恢复了正常,那么会将熔断器关闭,如果此请求执行失败,则认为服务依然不可用,熔断器继续保持打开状态。此配置项指定了熔断器打开后经过多长时间允许一次请求尝试执行,默认值是 5000。

4.1.7 工作流程

4.1.8 服务监控 hystrixDashborad
除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控,Hystrix会持续地记录所有通过Hystrix发起请求的执行信息,并以统计报表和图形的形式展现给用户,包括每秒执行多少请求,成功多少,失败多少等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Sreingcloud也提供了Hystrix Dashborad的整合,把监控内容转化正可视化界面。

1)监控服务依赖配置

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
启动类开启:@EnableHystrixDashboard  //启动断路器监控

2)被监控的服务依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
/**
 * 此配置是为了服务监控配置,与服务容错本身无关,Springcloud升级后的坑
 * 因为springboot的默认路径不是"/hystris.stream",
 * 只要在自己的项目里配置上下面的servlet就可以了
 * @return
 */
@Bean
public ServletRegistrationBean getServlet(){
    HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
    ServletRegistrationBean servletRegistrationBean =  new ServletRegistrationBean(streamServlet);
    servletRegistrationBean.setLoadOnStartup(1);
    servletRegistrationBean.addUrlMappings("/hystrix.stream");
    servletRegistrationBean.setName("HystrixMetricsStreamServlet");
    return servletRegistrationBean;
}

3)断路器监控访问地址

http://localhost:9001/hystrix

5、服务网关
5.1 Gateway
5.1.1 简介
作用:不暴露内部服务,对请求的路径进行映射到服务的匹配

该项目提供了一个在Spring生态系统之上构建的API网关,包括:Spring 5,Spring Boot 2和Project Reactor。Spring Cloud Gateway旨在提供一种简单而有效的方法来路由到API,并为它们提供跨领域的关注点,例如:安全性,监视/指标和弹性。
Spring Cloud Gateway需要Spring Boot和Spring Webflux提供的Netty运行时。它不能在传统的Servlet容器中或作为WAR构建时使用。

Route:网关的基本构建块。它由ID,目标URI,Predicate集合和过滤器集合定义。如果聚合Predicate为true,则匹配路由。

Predicate:这是Java 8 Function谓词。输入类型是Spring FrameworkServerWebExchange。这使您可以匹配HTTP请求中的所有内容,例如标头或参数。

Filter:这些是使用特定工厂构造的Spring FrameworkGatewayFilter实例。在这里,您可以在发送下游请求之前或之后修改请求和响应。

5.1.2 pom配置

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

5.1.3 路由配置的两种方式
1)yml配置路由

spring:
  application:
    name: cloud-gateway-9527
  cloud:
    gateway:
      routes:
      - id: payment_route  #路由的id,没有固定的规则,要求唯一,一般会配合服务名见名知意
        uri: http://localhost:8001  #匹配后提供服务的路由地址
        predicates:
        - Path=/payment/selectList  #断言,路径相匹配的进行路由
      - id: payment_route2
        uri: http://localhost:8001
        predicates:
        - Path=/payment/selectOneById/**

2)java类配置路由

@Configuration
public class RouteConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder locatorBuilder){
        RouteLocatorBuilder.Builder routes =  locatorBuilder.routes();
        routes.route("path-8001",r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
        routes.route("path-8002",r -> r.path("/guoji").uri("http://news.baidu.com/guoji")).build();
        return routes.build();
    }
}

5.1.4 动态路由
配合注册中心获取服务地址uri

spring:
  application:
    name: cloud-gateway-9527
  cloud:
    gateway:
      #开启从注册中心动态创建路由的功能,利用我服务的名进行路由
      discovery:
        locator:
          enabled: true
      routes:
      - id: payment_route  #路由的id,没有固定的规则,要求唯一,一般会配合服务名见名知意
        #uri: http://localhost:8001  #匹配后提供服务的路由地址
        uri: lb://CLOUD-PROVIDER-PAYMENT  #匹配注册中心的服务名,必须是lb:标识
        predicates:
        - Path=/payment/selectList  #断言,路径相匹配的进行路由
      - id: payment_route2
        uri: lb://CLOUD-PROVIDER-PAYMENT
        predicates:
        - Path=/payment/selectOneById/**

5.1.5 断言predicate
详见gateway官网:
https://cloud.spring.io/spring-cloud-gateway/reference/html/#gateway-request-predicates-factories

  1. After
spring: 
cloud: 
gateway: 
routes: 
- id: after_route 
uri: https://example.org 
predicates: 
#在此时间之后的请求有效
- After=2017-01-20T17:42:47.789-07:00[America/Denver]

  1. Before
spring: 
cloud: 
gateway: 
routes: 
- id: before_route 
uri: https://example.org 
predicates: 
#在此时间之前的请求有效
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
  1. Between
    spring:
    cloud:
    gateway:
    routes:
  • id: between_route
    uri: https://example.org
    predicates:
    #在此时间段之间的请求有效
    -Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
  1. Cookie
    spring:
    cloud:
    gateway:
    routes:
  • id: cookie_route
    uri: https://example.org
    predicates:
    #此路由匹配具有名称为chocolate与ch.p正则表达式匹配的cookie的请求
  • Cookie=chocolate, ch.p
  1. Host
    spring:
    cloud:
    gateway:
    routes:
  • id: host_route
    uri: https://example.org
    predicates:
    #如果请求的Host标头值为www.somehost.org或beta.somehost.org或,则此路由匹配www.anotherhost.org。
  • Host=.somehost.org,.anotherhost.org
  1. Header
    spring:
    cloud:
    gateway:
    routes:
  • id: header_route
    uri: https://example.org
    predicates:
    #如果请求具有名为X-Request-Id其值与\d+正则表达式匹配的标头(即,其值为一个或多个数字),则此路由匹配。
  • Header=X-Request-Id, \d+
  1. Method
    spring:
    cloud:
    gateway:
    routes:
  • id: method_route
    uri: https://example.org
    predicates:
    #如果请求方法是GET或POST,则此路由匹配。
  • Method=GET,POST
  1. Path
    spring:
    cloud:
    gateway:
    routes:
  • id: path_route
    uri: https://example.org
    predicates:
    #如果请求的路径是/red/1 or /red/blue or /blue/green,匹配这个Path则请求通过
  • Path=/red/{segment},/blue/{segment}
  1. Query
    spring:
    cloud:
    gateway:
    routes:
  • id: query_route
    uri: https://example.org
    predicates:
    #如果请求参数包含green则匹配这个路由
  • Query=green
    #如果请求包含red参数,且参数的值匹配gree,则匹配该路由
  • Query=red,gree.

5.1.6 GatewayFilter
详见:
https://cloud.spring.io/spring-cloud-gateway/reference/html/#gatewayfilter-factories

1)自定义配置

package com.wyq.springcloud.config;

/**
 * 自定义网关过滤器
 * @Author:wuyongqiang
 * @Date:2021-01-12 16:03:16:03
 */

import lombok.extern.slf4j.Slf4j;
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;

import java.util.Date;

@Component
@Slf4j
public class CustomGatewayFilterConfig implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("***********come in CustomGatewayFilterConfig:"+new Date());
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        System.out.println("****************"+uname+"********");
        if(uname == null){
            log.info("**********用户名为null,非法请求*****");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

6、配置中心
6.1 简介
Spring Cloud Config为分布式系统中的外部化配置提供服务器和客户端支持。使用Config Server,您可以集中管理所有环境中应用程序的外部属性。
客户端和服务器上的概念与SpringEnvironment和PropertySource抽象,因此它们非常适合Spring应用程序,但可以与以任何语言运行的任何应用程序一起使用。

Spring Cloud Config Server功能:

HTTP,用于外部配置的基于资源的API(名称-值对,或等效的YAML内容)
加密和解密属性值(对称或不对称)
可轻松地使用Spring Boot应用程序嵌入 @EnableConfigServer
Config Client功能(用于Spring应用程序):
绑定到Config Server并Environment使用远程属性源初始化Spring
加密和解密属性值(对称或不对称)

配置实现的原理:

application.yml是用户级别的资源配置项

bootstrap.yml是系统级的,优先级更加高
SpringCloud 会创建一个“Bootstrap Context”,作为Spring应用“Application Context”的父上下文。初始化的时候,“Bootstrap Context”负责外部源加载配置配置属性并解析配置。这两个上下文共享一个从外部获取的“Environment”。
“Bootstrap”属性有高优先级,默认情况下,他们不会被本地配置覆盖。“Bootstrap context”和“Applicaiton Context”有着不同的约定,所以新增了一个‘Bootstrap.yml’,保证Bootstrap Context和Application Context 配置的分离。
要将Client模块下的application.yml文件改为bootstrap.yml这很关键。因为bootstrap.yml是比application.yml先加载的。Bootstrap.yml优先级高于application.yml.
6.2 搭建-服务端
注:从git拉取配置文件的内容
1)pom依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

2)application.yml配置

spring:
  application:
    name: cloud-config-server-9666
  #配置文件的存放位置,利用git构建
  cloud:
    config:
      server:
        git:
          #仓库地址
          uri: https://github.com/wyq0818/cloud2020-config-server.git
          #搜索目录
          search-paths:
            - configfile
      #读取分支
      label: master

3)启动类配置
/*

  • @Author:wuyongqiang
  • @Date:2021-01-12 17:10:17:10
    */
    @SpringBootApplication
    @EnableEurekaClient
    @EnableConfigServer //启用配置中心
    public class ConfigServerMain {
    public static void main(String[] args) {
    SpringApplication.run(ConfigServerMain.class,args);
    }
    }

6.3 搭建-客户端
注:客户端其实就是消费者服务,从注册中心获取对应的配置
1)pom依赖 与服务端依赖不同

org.springframework.cloud
spring-cloud-starter-config

2)bootstrap.yml配置
spring:
application:
name: cloud-config-client-9667
cloud:
##配置中心客户端配置
config:
label: master #分支名称
name: config #配置文件名称
profile: dev #文件后缀
uri: http://localhost:9666 #配置中心服务端地址
#上述四项综合:master分支上config-dev.yml的配置文件被读取。
#http://localhost:9666/master/config-dev.yml

3)启动类配置
@SpringBootApplication
public class ConfigClientMain9667 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientMain9667.class,args);
}
}

6.4 客户端获取配置实时刷新
1)pom必要依赖

org.springframework.boot
spring-boot-starter-actuator

2)yml必要配置
#暴漏监控端点
management:
endpoints:
web:
exposure:
include: “*”

3)刷新效果示例
需要运维人员发送post请求刷新客户端
cmd
curl -X POST “http://localhost:9667/actuator/refresh”

@RestController
@RefreshScope //实时刷新配置
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/getConfigInfo")
public String getConfigInfo(){
return configInfo;
}
}

6.5 配合cloud-bus实现通知全部模块刷新配置
7、消息总线
7.1简介
Spring Cloud Bus将轻量级消息代理程序链接到分布式系统的节点。然后可以使用此代理来广播状态更改(例如配置更改)或其他管理指令。一个关键的想法是,总线就像是横向扩展的Spring Boot应用程序的分布式执行器。但是,它也可以用作应用之间的通信渠道。该项目为AMQP经纪人或Kafka提供了入门服务。
目前支持RabbitMQ和Kafka
7.2 动态刷新配置
7.2.1 设计思想:
1)利用消息总线触发一个客户端/bus/refresh,而刷新所有的客户端配置
2)利用消息总线触发一个服务端ConfigServer的/bus/refresh端点,而刷新所有的客户端配置。

7.2.2 全局广播
1)spring-cloud-config 添加bus依赖支持

org.springframework.cloud spring-cloud-starter-bus-amqp org.springframework.cloud spring-cloud-starter-bus-kafka 2)spring-cloud-config 添加yml配置 spring: rabbitmq: host: localhost port: 5672 username: guest password: guest #暴漏bus刷新配置的端点 management: endpoints: web: exposure: include: "bus-refresh"

3)client添加 bus支持

org.springframework.cloud spring-cloud-starter-bus-amqp 4)client添加 yml配置 spring: rabbitmq: host: localhost port: 5672 username: guest password: guest #暴漏bus刷新配置的端点 management: endpoints: web: exposure: include: "*" 5)一次发送,处处生效 运维人员对配置中心就行手动刷新配置,由bus广播到所有的业务模块刷新配置

以下两种方式均可
cmd

postman

7.2.3 定点通知
http://localhost:9666/actuator/bus-refresh/cloud-config-client-9667:9667

访问配置中心,后面参数携带业务模块的应用名称和端口
http://config-server:port/actuator/bus-refresh/spring.application.name:server.port

8、消息驱动

8.1简介
Spring Cloud Stream是一个框架,用于构建与共享消息传递系统连接的高度可扩展的事件驱动型微服务。
该框架提供了一个灵活的编程模型,该模型建立在已经建立并熟悉的Spring习惯用法和最佳实践的基础上,包括对持久性pub / sub语义,使用者组和有状态分区的支持。
总结:屏蔽底层消息中间件的差异,降低成本,统一消息的编程模式
通俗讲就是在一个消息中间件的通用容器

1)springcloudstream支持多种绑定器实现:
RabbitMQ
Apache Kafka
Kafka Streams
Amazon Kinesis
Google PubSub (partner maintained)
Solace PubSub+ (partner maintained)
Azure Event Hubs (partner maintained)
Apache RocketMQ (partner maintained)
2)Spring Cloud Stream的核心构建块是:
目标绑定器:负责提供与外部消息传递系统集成的组件。
目标绑定:外部消息传递系统和应用程序提供的消息生产者和消费者(由目标绑定器创建)之间的桥梁。
消息:生产者和消费者用来与目标绑定器(以及通过外部消息传递系统与其他应用程序)通信的规范数据结构。
8.2 设计思想
通过定义绑定器为中间件,完美实现应用程序与消息中间件细节之间的隔离。通过向应用程序暴露统一的Channel通道,使得应用程序不用再考虑各种不同消息中间件的实现。

8.3 消息生产者

1)pom依赖配置

org.springframework.cloud spring-cloud-starter-stream-rabbit 2)Yml配置 spring: application: name: cloud-stream-rabbitMQ-provider-6001 cloud: stream: binders: #配置要绑定的消息中间件 defaultmq: #表示定义的名称,用于binding整合 type: rabbit #消息组件类型 environment: #设置消息中间件的相关环境变量 spring: rabbibtmq: host: localhost port: 5762 username: guest password: guest bindings: #服务的整合处理 output: #建立通道的名称 destination: studyExchange #要使用的交换机(Exchenge)的名称 content-type: application/json #设置消息的类型 本次为json,文本则设置为"text/plain" binder: defaultmq

3)发送消息示例
package com.wyq.springcloud.service.impl;

import com.wyq.springcloud.service.IMessageProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import com.wyq.springcloud.service.IMessageProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import java.util.UUID;

/*

  • @Author:wuyongqiang

  • @Date:2021-01-15 15:13:15:13
    */
    @Service
    @EnableBinding(Source.class)//定义消息的推送管道
    public class MessageProvider implements IMessageProvider {

    @Autowired
    private MessageChannel output;//消息发送管道

    @Override
    public String send() {
    String serial = UUID.randomUUID().toString();
    output.send(MessageBuilder.withPayload(serial).build());
    System.out.println("**********serial:"+serial);
    return serial;
    }
    }

8.4 消息消费者
1)pom依赖配置

org.springframework.cloud spring-cloud-starter-stream-rabbit 2)Yml配置 spring: application: name: cloud-stream-rabbitMQ-provider-6001 cloud: stream: binders: #配置要绑定的消息中间件 defaultmq: #表示定义的名称,用于binding整合 type: rabbit #消息组件类型 environment: #设置消息中间件的相关环境变量 spring: rabbibtmq: host: localhost port: 5762 username: guest password: guest bindings: #服务的整合处理 input: #建立通道的名称 destination: studyExchange #要使用的交换机(Exchenge)的名称 content-type: application/json #设置消息的类型 本次为json,文本则设置为"text/plain" binder: defaultmq
  1. 发送消息示例
    package com.wyq.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

/*

  • @Author:wuyongqiang

  • @Date:2021-01-15 16:09:16:09
    */
    @Component
    @EnableBinding(Sink.class)
    public class ReceiveMessageListenerController {

    @Value("${server.port}")
    private String serverPort;

    @StreamListener(Sink.INPUT)
    public void receive(Message message){
    System.out.println(“消费者”+serverPort+“接受到的消息为:”+message.getPayload());
    }
    }

8.5 分组解决重复消费

故障现象:重复消费
故障原因:默认分组group是不同的,组流水号不一样,被认为是不同的组,可以消费
解决方法:自定义分组一致,解决同一集群下的服务重复消费,
如下红字配置
spring:
application:
name: cloud-stream-rabbitMQ-consumer
cloud:
stream:
binders: #配置要绑定的消息中间件
defaultmq: #表示定义的名称,用于binding整合
type: rabbit #消息组件类型
environment: #设置消息中间件的相关环境变量
spring:
rabbibtmq:
host: localhost
port: 5762
username: guest
password: guest
bindings: #服务的整合处理
input: #建立通道的名称
destination: studyExchange #要使用的交换机(Exchenge)的名称
content-type: application/json #设置消息的类型 本次为json,文本则设置为"text/plain"
binder: defaultmq
group: wyq #group分组名,防止同一集群下的服务重复消费

8.6 消息持久化
消息在没有消费时会持久化保存,当有消费者消费时就会消费
9、链路监控
9.1 简介
在微服务的架构中,一个由客户端发起的请求在后端系统中会经过多个不同的服务节点调用来协同产生最后的请求结果,每个前端请求都会形成一条复杂的分布式服务调用链路,链路中的任何一环节出现高延时或错误都会引起整个请求最后的失败。

Spring Cloud Sleuth为分布式跟踪提供了Spring Boot自动配置。这包括将跟踪数据(跨度)报告到的位置,要保留(跟踪)多少个跟踪,是否发送了远程字段(行李)以及要跟踪哪些库。

具体来说就是Spring Cloud Sleuth …

将跟踪和跨度ID添加到Slf4J MDC,以便您可以从给定的跟踪或跨度中的日志聚合器中提取所有日志。
从Spring应用程序(Servlet过滤器,Rest模板,计划的操作,消息通道,伪装客户端)检测常见的入口和出口点。
如果spring-cloud-sleuth-zipkin可用,则该应用将通过HTTP生成并报告与Zipkin兼容的跟踪。默认情况下,它将它们发送到本地主机(端口9411)上的Zipkin收集器服务。使用来配置服务的位置spring.zipkin.baseUrl。

9.2 构建zipkin服务
9.2.1 下载
Springcloud从F版本开始已经不需要构建自己的Zipkin Server了,只需要调用jar即可。

方法一:maven仓库下载地址:
https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec

方法二:Zipkin官方的Shell下载
curl -sSL https://zipkin.io/quickstart.sh | bash -s

方法三:百度网盘
链接:https://pan.baidu.com/s/1HXjzNDpzin6fXGrZPyQeWQ 密码:aon2

9.2.2 安装使用

9.2.3 业务模块配置示例
1)pom配置

org.springframework.cloud spring-cloud-starter-zipkin

2)yml配置
spring:
application:
name:
zipkin:
base-url: http://localhost:9411 #zipkin的服务地址
sleuth:
sampler:
probability: 1 #采样比例,介于0和1之间的值

3)Zipkin控制台查看
加了链路监控的业务模块,只要出现服务调用的请求都可以在zipkin的监控台查看到

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值