https://start.spring.io/actuator/info
https://github.com/alibaba/spring-cloud-alibaba/
UTF-8 1.8 1.8 2.2.2.RELEASE Hoxton.SR1 2.1.0.RELEASE 4.12 1.2.17 1.16.18 5.1.47 1.1.16 1.3.0 org.springframework.boot spring-boot-dependencies ${springboot.version} pom import org.springframework.cloud spring-cloud-dependencies ${springcloud.version} pom import com.alibaba.cloud spring-cloud-alibaba-dependencies ${cloudalibaba.version} pom import mysql mysql-connector-java ${mysql.version} com.alibaba druid ${druid.version} org.mybatis.spring.boot mybatis-spring-boot-starter ${mybatis.spring.boot.version} junit junit ${junit.version} log4j log4j ${log4j.version} org.projectlombok lombok ${lombok.version} true org.springframework.boot spring-boot-maven-plugin true true
com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test
--------------------------------------------------------------------------------------------------
POM
org.springframework.cloud spring-cloud-starter-netflix-eureka-server
org.springframework.cloud spring-cloud-starter-netflix-eureka-client
主启动类
@EnableEurekaServer
// 打开服务发现
@EnableDiscoveryClient
@EnableEurekaClient
// 打开服务发现
@EnableDiscoveryClient
@Resource
private DiscoveryClient discoveryClient;
@GetMapping(value = "/payment/discovery")
public Object discovery(){List services = discoveryClient.getServices();for (String element : services) {log.info("***** element:"+element);}List instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");for (ServiceInstance instance : instances) {log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());}return this.discoveryClient;
}
主机名称:服务名称修改、访问信息增加IP、关闭自我保护
自我保护原因:某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存,属于CAP里面的AP分支。(一般生产环境中不会禁止自我保护)
eureka:instance:# 修改主机名称 将Instance ID设置成IP:端口的形式instance-id: ${spring.cloud.client.ip-address}:${server.port}# 显示IPprefer-ip-address: true# 关闭自我保护# eureka客户端向服务端发送心跳的时间间隔lease-renewal-interval-in-seconds: 1# eureka服务端在收到最后一次心跳后等待时间上限lease-expiration-duration-in-seconds: 2
eureka:server:# 关闭自我保护机制enable-self-preservation: falseeviction-interval-timer-in-ms: 2000
多服务访问报错
配置类增加@LoadBalanced
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class ApplicationContextConfig {@Bean@LoadBalancedpublic RestTemplate getRestTemplate() {return new RestTemplate();}}
POM
org.springframework.cloud spring-cloud-starter-netflix-ribbon
IRule算法
替换IRule
类不允许放在主启动类及以下(不允许被spring扫描到)
新建规则类:
package com.myrule;import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MySelfRule {@Beanpublic IRule myRule(){// 定义为随机return new RandomRule();}
}
主启动类增加注解
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
POM
org.springframework.cloud spring-cloud-starter-openfeign
主启动类
@EnableFeignClients
调用
import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import feign.Param;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {@GetMapping(value = "/payment/get/{id}")public CommonResult getPaymentById(@PathVariable("id") Long id);
}
超时配置修改
OpenFeign默认超时时间为一秒钟,超过后报错
ribbon:ReadTimeout: 5000ConnectTimeout: 5000
日志
日志级别
修改日志级别
package com.springcloud.config;import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FeignConfig {@BeanLogger.Level feignLoggerLevel(){return Logger.Level.FULL;}
}
logging:level:com.springcloud.service.PaymentFeignService: debug
POM
org.springframework.cloud spring-cloud-starter-netflix-hystrix
服务提供者
主启动类
@EnableCircuitBreaker
服务调用者
@EnableHystrix
feign:hystrix:# 如果处理自身的容错就开启。开启方式与生产端不一样。enabled: true
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500") //3秒钟以内就是正常的业务逻辑
})
public String paymentInfo_TimeOut(@PathVariable("id") Integer id){String result = paymentHystrixService.paymentInfo_TimeOut(id);return result;
}
//兜底方法
public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id){return "我是消费者80,对付支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,(┬_┬)";
}
defaultFallback
package com.springcloud.controller;import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
@Slf4j
//全局的
@DefaultProperties(defaultFallback = "global_FallbackMethod")
public class OrderHystrixController {@GetMapping("/consumer/payment/hystrix/timeout/{id}")
// @HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
// @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500") //1.5秒钟以内就是正常的业务逻辑
// })@HystrixCommandpublic String paymentInfo_TimeOut(@PathVariable("id") Integer id){int age = 10/0;String result = paymentHystrixService.paymentInfo_TimeOut(id);return result;}//兜底方法public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id){return "我是消费者80,对付支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,(┬_┬)";}// 下面是全局fallback方法public String global_FallbackMethod(){return "Global异常处理信息,请稍后再试,(┬_┬)";}
}
OpenFeigh调用fallback与业务隔离
OpenFeign调用service
package com.springcloud.service;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)
public interface PaymentHystrixService {@GetMapping("/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id);@GetMapping("/payment/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id);
}
PaymentFallbackService类实现PaymentFeignClientService接口
package com.springcloud.service;import org.springframework.stereotype.Component;@Component
public class PaymentFallbackService implements PaymentHystrixService {@Overridepublic String paymentInfo_OK(Integer id) {return "-----PaymentFallbackService fall back-paymentInfo_OK , (┬_┬)";}@Overridepublic String paymentInfo_TimeOut(Integer id) {return "-----PaymentFallbackService fall back-paymentInfo_TimeOut , (┬_┬)";}
}
服务熔断
参数配置:HystrixCommandProperties
服务监控hystrixDashboard
Unable to connect to Command Metric Stream
@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;
}
POM
org.springframework.cloud spring-cloud-starter-gateway
YML
spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由routes:- id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001 #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/** # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001 #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/** # 断言,路径相匹配的进行路由- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]# - Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]# - Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] , 2020-03-08T10:59:34.102+08:00[Asia/Shanghai]# curl http://localhost:9527/payment/lb --cookie "username=zzyy"# - Cookie=username,zzyy #Cookie=cookieName,正则表达式# 请求头要有X-Request-Id属性并且值为整数的正则表达式 curl http://localhost:9527/payment/lb --cookie "username=zzyy" -H "X-Request-Id:11"
# - Header=X-Request-Id, \d+
# - Host=**.atguigu.com # curl http://localhost:9527/payment/lb -H "Host:afae.atguigu.com"
代码实现路由
package com.springcloud.config;import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class GateWayConfig {@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();//routes.route("payment_routh", r -> r.path("/payment/get/**").uri("lb://cloud-payment-service")).build();//routes.route("payment_routh2", r -> r.path("/payment/lb/**").uri("lb://cloud-payment-service")).build();//routes.route("payment_routh2", r -> r.path("/payment/lb/**", "/payment/get/**").uri("lb://cloud-payment-service")).build();routes.route("path_rote_atguigu", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();return routes.build();}}
微服务名实现路由
uri: lb://cloud-payment-service
Predicate
说白了,Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理
https://docs.spring.io/spring-cloud-gateway/docs/4.0.4-SNAPSHOT/reference/html/#gateway-request-predicates-factories
Filter
单一Filter
https://docs.spring.io/spring-cloud-gateway/docs/4.0.4-SNAPSHOT/reference/html/#gatewayfilter-factories
全局Filter
https://docs.spring.io/spring-cloud-gateway/docs/4.0.4-SNAPSHOT/reference/html/#global-filters
自定义Filter
package com.springcloud.filter;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.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.Date;@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter,Ordered {@Overridepublic Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("*********come in MyLogGateWayFilter: "+new Date());String uname = exchange.getRequest().getQueryParams().getFirst("username");if(StringUtils.isEmpty(username)){log.info("*****用户名为Null 非法用户,(┬_┬)");exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);//给人家一个回应return exchange.getResponse().setComplete();}return chain.filter(exchange);}@Overridepublic int getOrder() {return 0;}
}
单点登录
https://blog.csdn.net/qq_67390364/article/details/126481026
POM
org.springframework.cloud spring-cloud-config-server
org.springframework.cloud spring-cloud-starter-config
YML
spring:application:name: cloud-config-center #注册进Eureka服务器的微服务名cloud:config:server:git:uri: https://gitee.com/lixiaogou/sprincloud-config.git #GitHub上面的git仓库名字search-paths: #搜索目录- springcloud-configlabel: master #读取分支#启动成功后访问的路径 http://ip:3344/{label}/{application}-{profile}.yml 能访问的配置文件 就表示成功了
spring:application:name: config-clientcloud:# master分支上config-dev.yml的配置文件config:# 分支名称label: master# 配置文件名称name: config# 读取后缀名称profile: devuri: http://localhost:3344
主启动类
@EnableConfigServer
无
@RestController
public class ConfigClientController {@Value("${config.info}")private String configInfo;@GetMapping("/configInfo")public String getConfigInfo(){return configInfo;}
}
动态刷新
POM
org.springframework.boot spring-boot-starter-actuator
YML
management:endpoints:web:exposure:include: "*"
增加@RefreshScope
@RefreshScope
@RestController
public class ConfigClientController {@Value("${config.info}")private String configInfo;@GetMapping("/configInfo")public String getConfigInfo(){return configInfo;}
}
手动刷新:需要每台都手动刷新
curl -X POST “http://localhost:3355/actuator/refresh”
自动刷新、全量刷新、指定刷新(SpringCloud Bus)
Spring Cloud Sleuth提供了一套完整的服务跟踪的解决方案
在分布式系统中提供追踪解决方案并且兼容支持了zipkin
下载安装zipkin
服务改造
POM
org.springframework.cloud spring-cloud-starter-zipkin
YML
spring:application:name: cloud-payment-servicezipkin:base-url: http://localhost:9411sleuth:sampler:probability: 1
访问
http:localhost:9411
原理
一个更易于构建云原生应用的动态服务发现,配置管理和服务管理中心
因官网文档很好,这里不做说明,仅给出几个文档
nacos-github:https://github.com/alibaba/Nacos
nacos官网:https://nacos.io/zh-cn/docs/quick-start.html
springcloud-nacos文档:https://spring-cloud-alibaba-group.github.io/github-pages/2021/en-us/index.html#_spring_cloud_alibaba_nacos_discovery
nacos-example-github:https://github.com/alibaba/spring-cloud-alibaba/tree/2022.x/spring-cloud-alibaba-examples/nacos-example
因官网文档很好,这里不做说明,仅给出几个文档
sentinel-文档-中文:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
sentinel-github:https://github.com/alibaba/Sentinel
sentinel-example-github:https://github.com/alibaba/spring-cloud-alibaba/tree/2022.x/spring-cloud-alibaba-examples/sentinel-example
持久化:
https://blog.csdn.net/qq_17522211/article/details/129689938?spm=1001.2014.3001.5502
一次业务操作需要跨多个数据源或需要跨多个系统进行远程调用,就会产生分布式事务问题
因官网文档很好,这里不做说明,仅给出几个文档
seata-文档:http://seata.io/zh-cn/
因官网文档很好,这里不做说明,仅给出几个文档
文档:https://rocketmq.apache.org/
因官网文档很好,这里不做说明,仅给出几个文档
文档:https://www.aliyun.com/product/oss
因官网文档很好,这里不做说明,仅给出几个文档
文档:https://www.aliyun.com/product/sms
因官网文档很好,这里不做说明,仅给出几个文档
文档:https://www.aliyun.com/aliware/schedulerx?spm=5176.10695662.784137.1.4b07363dej23L3