SpringCloud Netfilx全家桶+ Alibaba(nacos、sentinel、seata) 快速配置,快速启动

5 篇文章 0 订阅
4 篇文章 0 订阅

Netflix

Eureka

服务注册与发现

注册中心

pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
    </dependencies>

application.yml

server:
  port: 7001

# Eureka
eureka:
  instance:
    hostname: localhost # 服务端名称
  client:
    register-with-eureka: false # 是否注册自己
    fetch-registry: false # 是否获取信息,为false表示自己为注册中心
    service-url:
      # 这里应该是其他集群的地址,如果单机部署就填自己
      defaultZone: http://127.0.0.1:7002/eureka/,http://127.0.0.1:7003/eureka/ 

启动类

@SpringBootApplication
@EnableEurekaServer	// 需要加上启动注解
public class Eureka7001 {
    public static void main(String[] args) {
        SpringApplication.run(Eureka7001.class,args);
    }
}

服务端

pom.xml

<!--eureka-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

<!--eureka监控信息-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

application.yml

server:
  port: 8001

spring:
  application:
    name: springcloud-provider-dept		# 这个name是服务的名称,也是服务的标识,多个相同的服务可以重名

# Eureka
eureka:
  client:
    service-url:
      # 所有注册中心集群的地址
      defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/,http://127.0.0.1:7003/eureka/
  instance:
    instance-id: ${spring.application.name}:${server.port} # 修改eureka默认描述

# 需要spring-boot-starter-actuator,这里的信息或出现在eureka监控详情信息里
info:
  app.name: king-springcloud
  app.company.name: king-company

启动类

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

客户端

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

application.yml

server:
  port: 8001

spring:
  application:
    name: springcloud-consumer-dept		# 这个name是服务的名称,也是服务的标识,多个相同的服务可以重名

# Eureka
eureka:
  client:
    register-with-eureka: false # 是否注册自己
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/,http://127.0.0.1:7003/eureka/

启动类

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

Discover

启动类

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

使用

@RestController
public class DeptController {
    @Autowired
    private DeptService deptService;

    /**
     * 可以用这个类获取一些信息
     * getServices
     * getInstances => instance.getServiceId()
     *                 instance.getHost() 
     *                 instance.getPort()
     *                 instance.isSecure() 
     *                 instance.getUri())
     */
    @Autowired
    private DiscoveryClient discoveryClient;
    
    /**
     * 注册进来的微服务,想办法获取一些信息
     */
    @RequestMapping("/getinfo")
    public Object getInfo() {
        List<String> services = discoveryClient.getServices();
        System.out.println("discoveryClient=>service:");
        for (String service : services) {
            System.out.println(service);
        }

        System.out.println();

        System.out.println("discoveryClient=>instance:");
        List<ServiceInstance> instances = discoveryClient.getInstances("springcloud-provider-dept-8001");
        for (ServiceInstance instance : instances) {
            System.out.println(instance.getInstanceId() + "\t" +
                    instance.getServiceId() + "\t" +
                    instance.getHost() + "\t" +
                    instance.getPort() + "\t" +
                    instance.isSecure() + "\t" +
                    instance.getUri());


        }
        return this.discoveryClient;
    }

}

Zookeeper

在服务器搭建好后

pom.xml

<!--由于zookeeper的服务端版本号可能与服务器上部署的zookeeper版本不同引起报错,我们先排除他-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!--这里必须跟zookeeper服务端版本一致-->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.5.5</version>
</dependency>

application.yml

server:
  port: 8001

spring:
  application:
    name: springcloud-provider-dept
  cloud:
    zookeeper:
      connect-string: 127.0.0.1:2181

RestTemplate

使用它首先要注册一个Bean

@Configuration
public class ConfigBean {


    /**
     * 导入ribbon后,实现客户端负载均衡,新版的Eureka集成了ribbon
     * */
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

使用

@RestController
public class DeptController {

	@Autowired
    private RestTemplate restTemplate;
    
    // 这里是要调用的服务的名,也可以是一个具体的url
	private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";

    @RequestMapping("/dept/getDeptById/{id}")
    public Dept get(@PathVariable("id") Long id) {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/getDeptById/" + id, Dept.class);
    }
    
}

DiscoverClient

启动类

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

使用

@RestController
public class DeptController {
    @Autowired
    private DeptService deptService;

    /**
     * 可以用这个类获取一些信息
     * getServices
     * getInstances => instance.getServiceId()
     *                 instance.getHost() 
     *                 instance.getPort()
     *                 instance.isSecure() 
     *                 instance.getUri())
     */
    @Autowired
    private DiscoveryClient discoveryClient;
    
    /**
     * 注册进来的微服务,想办法获取一些信息
     */
    @RequestMapping("/getinfo")
    public Object getInfo() {
        List<String> services = discoveryClient.getServices();
        System.out.println("discoveryClient=>service:");
        for (String service : services) {
            System.out.println(service);
        }

        System.out.println();

        System.out.println("discoveryClient=>instance:");
        List<ServiceInstance> instances = discoveryClient.getInstances("springcloud-provider-dept-8001");
        for (ServiceInstance instance : instances) {
            System.out.println(instance.getInstanceId() + "\t" +
                    instance.getServiceId() + "\t" +
                    instance.getHost() + "\t" +
                    instance.getPort() + "\t" +
                    instance.isSecure() + "\t" +
                    instance.getUri());


        }
        return this.discoveryClient;
    }

}

consul

linux下安装后运行consul

consul agent -dev

pom.xml

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

application.yml

server:
  port: 8001

spring:
  application:
    name: springcloud-provider-dept
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
      	service-name:${spring.application.name}
      

Ribbon

替换负载均衡规则

配置类(配置类不能在主启动类同级文件夹下)

@Configuration
public class MyRule{

    @Bean
    public IRule setRule(){
        return new RandomRule();
    }
}

主启动类

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "springcloud-consumer-dept", configuration = MyRule.class)
public class DeptConsumer80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer80.class, args);
    }
}

OpenFeign

服务调用

pom.xml

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

启动类

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

使用方法

  1. 在consumer端建立一个与provider的controller层结构相同的接口,并指定从哪个服务端获取
@Service
@FeignClient(value = "springcloud-provider-dept")
public interface DeptFeignClient {
    @PostMapping("/dept/add")
    public boolean addDept(String name);

    @GetMapping("/dept/getDeptById/{id}")
    public Dept getDeptById(@PathVariable("id") Long id);

    @GetMapping("/dept/getDeptList")
    public List<Dept> getDeptList();
}
  1. 在controller层直接调用

日志增强

application.yml

logging:
  level:
    # feign日志以什么级别监听哪个接口
    com.king.springcloud.service.DeptConsumerOpenFeign80: debug

FeignConfig.java

package com.king.springcloud.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfig {

    @Bean
    public Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

Hystrix

pom.xml

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

服务降级

服务端

启动类

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class SpringcloudProviderDeptHystrix8001 {

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

方法

@HystrixCommand(fallbackMethod = "degradeHandler",commandProperties = {
            @HystrixProperty(name="execution.isolation.thread.timeoutInMillisecond",value="5000")
    })
    @GetMapping(value = "/timeout/ok")
    public String timeoutOk() {
        int timeout = 3;
        try {
            TimeUnit.SECONDS.sleep(timeout);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return Thread.currentThread().getName() + port + ":请求成功!!!" + "超时(s):" + timeout;
    }
    public String degradeHandler() {

        return Thread.currentThread().getName() + port + "服务异常";
    }

客户端

application.yml

feign:
	hystrix:
		enabled: true

启动类

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
public class SpringcloudProviderDeptHystrix8001 {

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

方法部分与服务端相同

全局默认配置

除了个别重要核心业务,其他的通过 @DefaultProperties(defaultFallback = “”) 统一处理

@RestController
@DefaultProperties(defaultFallback = "globalHandler")
public class DeptController {

    @Autowired
    private DeptFeignClient deptFeignClient;

    @HystrixCommand
    @RequestMapping("/dept/getDeptById/{id}")
    public Dept get(@PathVariable("id") Long id) {
        return deptFeignClient.getDeptById(id);
    }

    @HystrixCommand
    @RequestMapping("/dept/add")
    public boolean add(Dept dept) {
        return deptFeignClient.addDept(dept.getName());
    }

    @HystrixCommand
    @RequestMapping("/dept/getDeptList")
    public List<Dept> getList() {
        System.out.println(123);
        return deptFeignClient.getDeptList();
    }

    @HystrixCommand(fallbackMethod = "coreHandler", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
    })
    @GetMapping("/dept/timeout")
    public String feignTimeout() {
        return deptFeignClient.feignTimeout();
    }

    public String coreHandler() {
        return "服务器错误,请稍后重试!!!";
    }

    public String globalHandler() {
        return "服务器错误,请稍后重试.";
    }
}

Feign处理降级

先写一个类用来处理FeignClient,同时implement接口

@Component
public class DeptFeignClientFallback implements DeptFeignClient {

    @Override
    public boolean addDept(String name) {
        return false;
    }

    @Override
    public Dept getDeptById(Long id) {
        return new Dept();
    }

    @Override
    public List<Dept> getDeptList() {
        return new ArrayList<>();
    }

    @Override
    public String feignTimeout() {
        return "超时!";
    }
}

在FeignClient中配置fallback

@Service
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallback = DeptFeignClientFallback.class)
public interface DeptFeignClient {
    @PostMapping("/dept/add")
    public boolean addDept(String name);

    @GetMapping("/dept/getDeptById/{id}")
    public Dept getDeptById(@PathVariable("id") Long id);

    @GetMapping("/dept/getDeptList")
    public List<Dept> getDeptList();

    @GetMapping("/dept/timeout")
    public String feignTimeout();
}

服务熔断

服务降级->服务熔断->恢复调用链路

@HystrixCommand(fallbackMethod = "circuitBreakerHandler", commandProperties = {
     @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),//是否开启断路器
     @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),//请求次数
     @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000"),//熔断后多久半启动
     @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000"),//时间窗口
     @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")//失败率达到多少后断路
    })
    @GetMapping(value = "/breaker/{id}")
    public String circuitBreaker(@PathVariable(value = "id") String id) throws Exception {
        if (Integer.parseInt(id) < 0) {
            throw new Exception();
        }
        return Thread.currentThread().getName() + "成功" + "-id-:" + id;
    }

    public String circuitBreakerHandler(@PathVariable(value = "id") String id) {
        return Thread.currentThread().getName() + "失败" + "-id-:" + id;
    }

HystrixProperty

  • HystrixCommandProperties
/* --------------统计相关------------------*/ 
// 统计滚动的时间窗口,默认:5000毫秒(取自circuitBreakerSleepWindowInMilliseconds)   
private final HystrixProperty metricsRollingStatisticalWindowInMilliseconds;   
// 统计窗口的Buckets的数量,默认:10个,每秒一个Buckets统计   
private final HystrixProperty metricsRollingStatisticalWindowBuckets; // number of buckets in the statisticalWindow   
// 是否开启监控统计功能,默认:true   
private final HystrixProperty metricsRollingPercentileEnabled;   
/* --------------熔断器相关------------------*/ 
// 熔断器在整个统计时间内是否开启的阀值,默认20。也就是在metricsRollingStatisticalWindowInMilliseconds(默认10s)内至少请求20次,熔断器才发挥起作用   
private final HystrixProperty circuitBreakerRequestVolumeThreshold;   
// 熔断时间窗口,默认:5秒.熔断器中断请求5秒后会进入半打开状态,放下一个请求进来重试,如果该请求成功就关闭熔断器,否则继续等待一个熔断时间窗口
private final HystrixProperty circuitBreakerSleepWindowInMilliseconds;   
//是否启用熔断器,默认true. 启动   
private final HystrixProperty circuitBreakerEnabled;   
//默认:50%。当出错率超过50%后熔断器启动
private final HystrixProperty circuitBreakerErrorThresholdPercentage;  
//是否强制开启熔断器阻断所有请求,默认:false,不开启。置为true时,所有请求都将被拒绝,直接到fallback 
private final HystrixProperty circuitBreakerForceOpen;   
//是否允许熔断器忽略错误,默认false, 不开启   
private final HystrixProperty circuitBreakerForceClosed; 
/* --------------信号量相关------------------*/ 
//使用信号量隔离时,命令调用最大的并发数,默认:10   
private final HystrixProperty executionIsolationSemaphoreMaxConcurrentRequests;   
//使用信号量隔离时,命令fallback(降级)调用最大的并发数,默认:10   
private final HystrixProperty fallbackIsolationSemaphoreMaxConcurrentRequests; 
/* --------------其他------------------*/ 
//使用命令调用隔离方式,默认:采用线程隔离,ExecutionIsolationStrategy.THREAD   
private final HystrixProperty executionIsolationStrategy;   
//使用线程隔离时,调用超时时间,默认:1秒   
private final HystrixProperty executionIsolationThreadTimeoutInMilliseconds;   
//线程池的key,用于决定命令在哪个线程池执行   
private final HystrixProperty executionIsolationThreadPoolKeyOverride;   
//是否开启fallback降级策略 默认:true   
private final HystrixProperty fallbackEnabled;   
// 使用线程隔离时,是否对命令执行超时的线程调用中断(Thread.interrupt())操作.默认:true   
private final HystrixProperty executionIsolationThreadInterruptOnTimeout; 
// 是否开启请求日志,默认:true   
private final HystrixProperty requestLogEnabled;   
//是否开启请求缓存,默认:true   
private final HystrixProperty requestCacheEnabled; // Whether request caching is enabled. 
  • HystrixCollapserProperties
//请求合并是允许的最大请求数,默认: Integer.MAX_VALUE   
private final HystrixProperty maxRequestsInBatch;   
//批处理过程中每个命令延迟的时间,默认:10毫秒   
private final HystrixProperty timerDelayInMilliseconds;   
//批处理过程中是否开启请求缓存,默认:开启   
private final HystrixProperty requestCacheEnabled; 
  • HystrixThreadPoolProperties
/* 配置线程池大小,默认值10个 */ 
private final HystrixProperty corePoolSize; 
/* 配置线程值等待队列长度,默认值:-1 建议值:-1表示不等待直接拒绝,测试表明线程池使用直接决绝策略+ 合适大小的非回缩线程池效率最高.所以不建议修改此值。 当使用非回缩线程池时,queueSizeRejectionThreshold,keepAliveTimeMinutes 参数无效 */
private final HystrixProperty maxQueueSize; 

Dashboard

dashboard

applicatoin.yml

server:
  port: 9001

启动类

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

pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

访问的微服务地址

http://localhost:8001/hystrix.stream
被监控的微服务

​ pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

启动类

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class SpringcloudProviderDeptHystrix8001 {

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

    @Bean
    public ServletRegistrationBean getServlet(){
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

GateWay

路由与断言

pom.xml

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

<!--一般与注册中心一起使用-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

转发可以通过写配置文件,也可以通过写配置类实现

application.yml

spring:
  application:
    name: springcloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  					 # 通过注册中心,使用服务名转发
      routes:
        - id: dept-provider-route
          uri: lb://springcloud-provider-dept
#          uri: http://localhost:8001      # 转发地址
          predicates:
            - Path=/dept/getDeptById/**    # 断言

        - id: dept-provider-route2
          uri: lb://springcloud-provider-dept
#          uri: http://localhost:8001
          predicates:
            - Path=/dept/getDeptList

Gateway.java

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();

        routes.route("dept-provider-route",
                r -> r.path("/guonei")
                        .uri("https://news.baidu.com/guonei")).build();
        return routes.build();
    }
}

predicates常用

predicates:
	- Path=/dept/getDeptById/**   # 断言
	- After=2021-09-21T21:41:13.154920100+08:00[Asia/Shanghai]  # 在这个时间之后路由生效
	- Before=2021-09-21T21:41:13.154920100+08:00[Asia/Shanghai] # 在这个时间之前路由生效
	# 在这个时间之间路由生效
	- Between=2021-09-21T21:41:13.154920100+08:00[Asia/Shanghai],2021-09-21T22:41:13.154920100+08:00[Asia/Shanghai]
	- Cookie=username,admin   # 带有cookie可以访问,参数:name,正则
	- Header=X-Request,/d+    # 带有header可以访问,参数:name,正则
	- Host=**.baidu.com       # 指定host 例如->www.baidu.com,news.baidu.com
 	- Method=GET              # 指定访问方法
 	- Query=username,admin    # 带有指定参数可以访问,参数:key,正则

全局过滤器

MyLogGlobalFilter.java

@Component
@Slf4j
public class MyLogGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("=====================MyLogGlobalFilter====================="+new Date());
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if(uname == null){
            exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

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

Config

server

pom.xml

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

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

application.yml

server:
  port: 3344

spring:
  application:
    name: spring-cloud-config-center
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/auroranb/springcloud-config.git
          search-paths:
            - springcloud-config
          username: 772335766@qq.com
          password: favour1.
      label: master

启动类

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

client

pom.xml

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

bootstrap.yml

# master分支下的config-dev.yml
server:
  port: 3355
spring:
  cloud:
    config:
      label: master
      name: config					
      profile: dev
      uri: http://localhost:3344	# config server地址
  application:
    name: spring-cloud-cofig-client

动态刷新配置

bootstrap.yml

# master分支下的config-dev.yml
server:
  port: 3355
spring:
  cloud:
    config:
      label: master
      name: config					
      profile: dev
      uri: http://localhost:3344	# config server地址
  application:
    name: spring-cloud-cofig-client
# 暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

使用处添加@RefreshScope注解

@RestController
@RefreshScope
public class ConfigController {

    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/configInfo")
    public String getConfigInfo(){
        return configInfo;
    }
}

配置更新后向client端发送post请求更新配置

curl -X POST ""http://localhost:3355/actuator/refresh"

Bus

server

pom.xml

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

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

application.yml

management:
  endpoints:
    web:
      exposure:
        include: 'bus-refresh'
        
spring:
  rabbitmq:
    host: 8.136.225.205
    port: 5672
    username: guest
    password: guset

client

pom.xml

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

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

bootstrap.yml

management:
  endpoints:
    web:
      exposure:
        include: "*"
        
spring:
  rabbitmq:
    host: 8.136.225.205
    port: 5672 
    username: guest
    password: guset
使用

向config-server发送post

curl -X POST "http://${配置中心ip:port}/actuator/bus-refresh"

定点更新

curl -X POST "http://${配置中心ip:port}/actuator/bus-refresh/${config-client-name}:${prot}"

Stream

pom.xml

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

Provider

application.yml

spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合 可以随便写什么
          type: rabbit # 底层消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                host: 8.136.225.205
                port: 5672
                username: guest
                password: guest
                virtual-host: /
      bindings: # 服务的整合处理 消费者配置,在此绑定
        # 消息生产者配置(哪个提供者服务需要就配置)
        output: # 这个名字是一个通道的名称
          destination: my-exchange      # 表示要使用的Exchange交换机名称定义
          content-type: application/json  # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit              # 设置要绑定的消息服务的具体设置binder
management:
  health:
    rabbit:
      enable: false

使用

@EnableBinding(Source.class)		// 上文中bindings下的output对应Source类中@Output中的内容
public class DefaultMessageProviderImpl{

    @Resource
    public MessageChannel output;

    public String send() {
        String uuid = UUID.randomUUID().toString();
        output.send(MessageBuilder.withPayload(uuid).build());
        System.out.println("uuid--"+uuid);
        return uuid;
    }
}

Consumer

application.yml

spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合 可以随便写什么
          type: rabbit # 底层消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                host: 8.136.225.205
                port: 5672
                username: guest
                password: guest
                virtual-host: /
      bindings: # 服务的整合处理 消费者配置,在此绑定
        # 消息生产者配置(哪个提供者服务需要就配置)
        input: # 这个名字是一个通道的名称
          destination: my-exchange      # 表示要使用的Exchange交换机名称定义
          content-type: application/json  # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit              # 设置要绑定的消息服务的具体设置binder
management:
  health:
    rabbit:
      enable: false

使用

EnableBinding(Sink.class)		//上文中bindings下的input对应Sink.class中@Input中的参数
@Component
public class ReceiveMessageListenerController {

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

    @StreamListener(Sink.INPUT)
    public void input(Message<String> message){
        System.out.println("消费者1 --- 消息:" + message.getPayload() + "\t port:" + port  );
    }

}

分组与持久化

通过定义bindings下的每个队列的group

相同的group一起消费消息

不同的group分别消费消息

....
	bindings: # 服务的整合处理 消费者配置,在此绑定
        # 消息生产者配置(哪个提供者服务需要就配置)
        input: # 这个名字是一个通道的名称
          destination: my-exchange      # 表示要使用的Exchange交换机名称定义
          content-type: application/json  # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
          binder: defaultRabbit              # 设置要绑定的消息服务的具体设置binder
          group: mygroup

同时设置了group属性可以完成数据持久化,会消费未启动前队列中的堆存的消息

原理是,exchange数据发送到队列中,没有froup重启没有设置分组,会重新创建队列并监听,设置了group还是监听原来队列。

Sleuth

首先安装zipkin

docker安装或本地安装

docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin /bin/bash

在需要监控的服务上的application.yml上加

spring:
	zipkin:
		base-url: http://localhost:9411
	sleuth:
		sampler:
			probability: 1

pom.xml

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

打开zipkin部署地址的9411查看

Alibaba

Nacos

下载后启动进入bin目录

startup.cmd  -m standalone

打开管理页面

http://localhost:8848

服务注册与发现

pom.xml

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

启动类

package com.king.springcloud;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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

provider

application.yml

server:
  port: 9901

spring:
  application:
    name: spring-cloud-alibaba-provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

management:
  endpoints:
    web:
      exposure:
        include: '*'
consumer

pom.xml

<!--最新版本的nacos没有集成ribbon,需要手动导入才能实现负载均衡-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    <version>2.2.9.RELEASE</version>
</dependency>

application.yml

server:
  port: 9901

spring:
  application:
    name: spring-cloud-alibaba-provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

management:
  endpoints:
    web:
      exposure:
        include: '*'

config.java

@Configuration
public class BeanConfig {

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

使用

@RestController
public class ConsumerController {

    public static final String SERVICE_NAME = "http://spring-cloud-alibaba-provider";

    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/nacos/{id}")
    public String consume(@PathVariable("id") String id){
        String url = SERVICE_NAME + "/provider/nacos/" + id;
        System.out.println(url);
        return restTemplate.getForObject( url , String.class);
    }
}

配置中心

pom.xml

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

bootstrap.yml

server:
  port: 3366

spring:
  application:
    name: spring-cloud-alibaba-config-client
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
#        namespace: 此处可以填写命名空间的id来指定命名空间
#        group: 此处可以指定分组
management:
  endpoints:
    web:
      exposure:
        include: '*'

application.yml

spring:
  profiles:
    active: dev

在配置中心添加配置,Data Id格式

${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.discovery.server-addr}

持久化

nacos目前支持msql

首先找到nacos的conf目录下的sql脚本并执行

修改application.properties,加上如下配置

spring.datasource.platform=mysql

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=root

集群

在多台linux服务器上下载nacos

  1. 在conf目录下将cluster.conf.example复制为cluster.conf并添加集群的ip:端口(此处必须为实际ip)

cluster.conf

123.456.789.1:8848
123.456.789.2:8848
123.456.789.3:8848
  1. 配置mysql持久化

修改application.properties,加上如下配置

spring.datasource.platform=mysql

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://123.456.789.4:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=root

Sentinel

控制台

下载控制台:https://github.com/alibaba/Sentinel/releases

启动

java -jar -DServer.port=<port> sentinel-dashboard-<version>.jar

控制台账号密码均为sentinel

java程序

pom.xml

<!--一般sentinel与nacos一起使用, -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

application.yml

server:
  port: 8401

spring:
  application:
    name: sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
        port: 8719

management:
  endpoints:
    web:
      exposure:
        include: '*'

@SentinelResource

  • value:指定资源名
  • blockHandler:指定在控制台配置的规则生效时用来处理异常的方法(业务逻辑发生异常不会处理)
    • 处理方法要在原有参数基础上增加一个BlockException参数
  • blockHandlerClass:如果格外定义了用于处理的类,通过这个参数指定该类,此时blockHandler可以是该类下的方法
  • fallback:当业务逻辑出现错误时的兜底方法
    • 处理方法要在原有参数基础上增加一个Throwable参数
    • 如果配置了exceptionsToIgnore,fallback会不处理exceptionsToIgnore中配置的异常类型
@RequestMapping("/byResource")
@SentinelResource(value = "byResource", blockHandler = "byResourceHandler")
public CommonResult byResource() {
    return new CommonResult(0, "请求成功", new Dept(1000, "dept1"));
}

public CommonResult byResourceHandler(BlockException blockException) {
    return new CommonResult(100, "请求失败 -- " + blockException.getClass().getCanonicalName(), null);
}

@RequestMapping("/byUrl")
@SentinelResource(value = "byUrl")
public CommonResult byUrl() {
    return new CommonResult(0, "byUrl请求成功", new Dept(1000, "dept1"));
}

@RequestMapping("/byBlockHandler")
@SentinelResource(value = "byBlockHandler",
                  blockHandlerClass = CustomBlockHandler.class,
                  blockHandler = "blockHandler2"
                 )
public CommonResult byBlockHandler() {
    return new CommonResult(0, "byBlockHandler请求成功", new Dept(1000, "dept1"));
}

整合openfeign

pom.xml

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

application.yml

feign:
  sentinel:
    enabled: true

剩下部分与Netflix部分openfeign相同

持久化

pom.xml

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

application.yml

spring:
  application:
    name: spring-cloud-alibaba-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
        port: 8719
      datasource:			# 持久化配置
        ds1:
          nacos:			# 使用nacos进行持久化
            server-addr: 127.0.0.1:8848			# nacos的地址
            dataId: ${spring.application.name}	# 储存配置的名称,(nacos中要有相应的配置!!!)
            groupId: DEFAULT_GROUP				# 分组
            #namespace:.....					# 不配置则是默认命名空间
            data-type: json						# 配置文件的类型
            rule-type: flow						# 

写入nacos的配置,具体如何配置查看官网的流量控制熔断降级热点参数限流系统自适应限流的详细配置

[
	{
        ....
    },
    {
        ....
    }
]

Seata

server

下载seata:https://github.com/seata/seata/releases

  1. 打开conf目录,修改file.conf

  2. 创建相应的seata数据库

这里sql语句在conf文件夹下README.md中(标题链接)

  1. 修改registry.conf,使用nacos作为注册中心,(可以配置nacos)
registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"

  nacos {
    application = "seata-server"
    serverAddr = "127.0.0.1:8848"
    group = "SEATA_GROUP"
    namespace = ""
    cluster = "default"
    username = "nacos"
    password = "nacos"
  }
  
  .....
}
  1. 运行seata-server.bat

client

  1. 创建相关业务
  2. 创建数据库和表
  3. 创建undo_log表
-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log
CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
  1. 添加pom.xml,此处需要指定与server端一致的seata版本
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.seata</groupId>
            <artifactId>seata-all</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-all</artifactId>
    <version>1.4.2</version>
</dependency>
  1. 编写application.yml
server:
  port: 9991

spring:
  application:
    name: spring-cloud-seata-order
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    alibaba:
      seata:
        tx-service-group: my_tx_group   # 此处必须与file.conf中配置的事务组名称一致
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://47.108.93.159:3307/db_order

management:
  endpoints:
    web:
      exposure:
        include: '*'
  1. 将file.conf和registry.conf放在每个用到全局事务的微服务的resource目录下(如果配置了nacosconfig就不需要)

  2. 配置代理数据源,由于最终是由seata进行全局事务管理,所以要将数据源给seata代理

  3. 在业务代码上加上@GlobalTransactional并指定事务组

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值