赞
踩
基于SpringBoot提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件
SpringCloud为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等,它们都可以用SpringBoot的开发风格做到一键启动和部署。
SpringCloud=分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶
相关项目
SpringCloud要与SpringBoot版本相对应
查看网址:https://spring.io/projects/spring-cloud#overview
更详细的:https://start.spring.io/alctuator/info
本次课程版本选择
pom
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> </parent> <properties> <spring-cloud.version>Hoxton.SR1</spring-cloud.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
版本选择推荐
服务注册中心
服务调用
服务调用2
服务降级
Hystrix 维护 抛弃
resilience4j 可使用
sentienl 可使用
服务网关
服务配置
服务总线
Maven中DependencyManagement和Dependencies区别
maven跳过单元测试
建工程五步
相关细节
配置允许容器中相同名字bean覆盖的配置
main :
allow-bean-definition-overriding: true
官网地址:
https://docs.spring.io/spring-framewprk/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html
使用
相关方法
作用:实现服务的自动注册、发现、状态监控。
单机步骤
导包
配置yml
#服务端 eureka: client: service-url: defaultZone: http://127.0.0.1:${server.port}/eureka fetch-registry: false #不注册到自己这里 register-with-eureka: false #不注册到自己这里 server: enable-self-preservation: false #关闭自我保护 eviction-interval-timer-in-ms: 5000 #失效时间 --- #客户端 eureka: client: service-url: defaultZone: http://127.0.0.1:${server.port}/eureka
主启动类
高可用
步骤
先搭建好单机步骤
修改yml
#客户端 server: port: ${PORT:50101} spring: application: name: xc‐govern‐center eureka: client: register-with-eureka: true fetch-registry: true service-url: defaultZone: ${EUREKA_SERVER:http://eureka02:50102/eureka/} server: enable-self-preservation: false eviction-interval-timer-in-ms: 60000 instance: hostname: ${EUREKA_DOMAIN:eureka01} #需要设置好主机名
对应yml设置启动参数
修改客户端yml
修改客户端yml
instance:
instance-id: payment8002
prefer-ip-address: true #访问路径可以显示P地址
主启动类加@EnableDiscoverClient
通过discoveryClient对象得到服务相关信息
概述
基本使用
centOS7上启动zookeeper
导包:spring-cloud-starter-zookeeper-discovery
配置yml
cloud :
zookeeper:
connect-string: 192.168. 111.144:2181
主启动类加上@EnableDiscoverClient
获得微服务信息命令
其微服务结点为临时结点
jar版本和zookeeper版本jar包不符
解决步骤
排除自带的zookeeper包
导入我们正确版本的zookeeper包
<dependency> <groupId>org.springframework.cloud</ groupId> <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId> <!--先排除自带的zookeeper3.5.3--> <exclusions> <exclusion> <groupId>org.apache.zookeeper</ groupId> <artifactId>zookeeper</artifactId> </ exclusion> </exclusions> </dependency> <!--添加zookeeper3.4.9版本--> <dependency> <groupId>org.apache.zookeeper</ groupId> <artifactId>zookeeper</ artifactId> <version>3.4.9</version> </dependency>
概述
使用步骤
cmd 执行consul agent -dev
启动consul
8500端口访问首页
导包spring-cloud-starter-consul-discovery
配置yml
cloud:
consul:
host: localhost
port: 8500
discovery:
#hostname: 127.0.0.1
service-name: ${spring. application.name}
CAP理论
已有可选择方式
切换方法
代码配置方法
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule() {
return new RandomRule() ;
}
@Bean
public IPing ping(){
return new PingUrl() ;
}
}
@Configuration .
@RibbonClient(name = "user-center", configuration = MySelfRule.class)
pubLic class UserCenterRibbonConfiguration {
}
配置类配置
user-center: #微服务名
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.Random
方法对比
全局配置
@Configuration
@RibbonClients(defaultConfiguration = RibbonConfiguration.class)
public class UserCenterRibbonConfiguration {
}
饥饿加载
ribbon:
eager-load:
enabLed: true
clients: user-center
其他配置
为什么要在componentScan扫描不到的地方
核心api
写负载均衡算法类
继承AbstractLoadBalancerRule 类
@Slf4j public class NacosWeigbtedRule extends AbstractLoadBalancerRule { @Autowired private NacosDiscoveryProperties nacosDiscoveryProperties; @Override public void initWithNiwsConfig ( IClientConfig clientConfig) { //读取配置文件,并初始化NacosWeightedRule } @Override public Server choose(Object key) { try { BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer(); log. info("Zb = {}", loadBalancer); //想要请求的微服务的名称 String name = loadBalancer.getName( ) ; // 拿到服务 发现的相关API NamingService namingService = nacosDiscoveryProperties.namingMaintainServiceInstance(); // nacos client自动通过基于权重的负载均衡算法,给我们选择一 个实例。 NamingService namingService = nacosDiscoveryProperties.namingServiceInstance(); Instance instance = namingService.selectOneHealthyInstance(name); log.info("选择的实例是:{}",instance); return new NacosServer( instance) ; } catch (NacosException e) { return null; } } }
@Slf4j public class NacosClusterRule extends AbstractLoadBalancerRule { @Autowired private NacosDiscoveryProperties nacosDiscoveryProperties; @Override public void initWithNiwsConfig (IClientConfig clientConfig) { // 1。找到指定服务的所有实例A List<Instance> instances = namingService.seLectInstance; // 2.过滤出相同集群下的所有实例B List<Instance> sameClusterInstances = instances.stream ( .filter( instance -> 0bjects.equals(instance.getCluster() .collect(Collectors. toList()); // 3。如果B是空,就用A List<Instance> instancesToBeChosen = new ArrayList<>( ) ; if (CollectionUtils. isEmpty( sameClusterInstances)) { instancesToBeChosen = instances ; Zog.warn("发生跨集群的调用, name = {},ClusterName ={}", name , ClusterName ,instances); } else{ instancesToBeChosen = sameClusterInstances ; } // 4.基于权重的负载均衡算法,这回1个买例 Instance instance = ExtendBalancer . getHos tByRandomWeight2( i) log. info("选择的实例是port = {}, instance = {}", instance. get return new NacosServer(instance) ; } catch ( NacosException e) { Log.error("发生异常了",e) ; return nulL; } } class ExtendBalancer extends Balancer { public staticInstance getHostByRandomWeight2(List<Instance> hosts ) return getHostByRandomWeight (hosts) ; }
概述
使用方法
请求超时机制
OpenFeign默认等待1秒,超过后报错
默认支持Ribbon
yml中可修改超时时间设置
#没置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
#指的是建立连接所用的时间,适用于网络状况正E常的情况下,两端连接所用的时间
ReadTimeout: 5000
#指的是建立连接后从服务器读取到可用资源所用的时间
ConnectTimeout: 5000
其他相关配置
#1 hystrix可配置的部分 hystrix.command.default.execution.timeout.enable=true #为false则超时控制有ribbon控制,为true则hystrix超时和ribbon超时都是用,但是谁小谁生效,默认为true hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000#熔断器的超时时长默认1秒,最常修改的参数 circuitBreaker.requestVolumeThreshold=20 #触发熔断的最小请求次数,默认为20 circuitBreaker.sleepWindowInMilliseconds=5000 #休眠时长,默认为5秒 circuitBreaker.errorThresholdPercentage=50 #触发熔断的失败请求最小占比,默认50% #2 ribbon的可配置部分 ribbon.ReadTimeout=1000 #处理请求的超时时间,默认为1秒 ribbon.ConnectTimeout=1000 #连接建立的超时时长,默认1秒 ribbon.MaxAutoRetries=1 #同一台实例的最大重试次数,但是不包括首次调用,默认为1次 ribbon.MaxAutoRetriesNextServer=0 #重试负载均衡其他实例的最大重试次数,不包括首次调用,默认为0次 ribbon.OkToRetryOnAllOperations=false #是否对所有操作都重试,默认false #3 Feign的可配置部分 feign.hystrix.enabled=false #Feign是否启用断路器,默认为false feign.client.config.default.connectTimeout=10000 #Feign的连接建立超时时间,默认为10秒 feign.client.config.default.readTimeout=60000 #Feign的请求处理超时时间,默认为60 feign.client.config.default.retryer=feign.Retryer.Default #Feign使用默认的超时配置,在该类源码中可见,默认单次请求最大时长1秒,重试5次
概念
分类
使用方法
代码配置方式
写一个配置类
@Configuration
public class FeignConfig{
@Bean
Logger.Level feignLoggerLevel()
{
return Logger.Level.FULL;
}
}
将这个包的日志输出等级改为debug
配置文件配置方式(单个)
feign:
client:
config:
#想要调用的微服务的名称.
user-center:
loggerLevel: full
配置文件(全局)
feign:
client:
config:
#想要调用的微服务的名称.
default:
loggerLevel: full
配置方式对比
最佳实践
概述
争议
get请求包含多个参数
@FeignClient("microservice-provider-user")
public interface UserFeignClient {
@GetMapping("/get")
public User get0(@SpringQueryMap User user);
}
如何选择
连接池(提升15%)
配置方法
feign:
client:
config :
#全局配置
default:
LoggerLevel: full
httpclient:
#让feign使用apache httpclient做请求; 而不是默认的urLc
enabled: true
# feign的最大连接数
max-connections: 2 00
# feign单 个路径的最大连接数
max-connections-per-route: 50
okhttp: #配置为okhttp
enabled: true
日志级别
分布式系统面临问题
服务雪崩
Hystrix概念
作用
概念
什么时候会引发服务降级
概念
概念
导包 :spring -cloud-starter-netflix-hystrix
使用@HystrixCommand注解,并写好兜底方法
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler" , commandProperties = {
@HystrixProperty(name=" execution.isolation.thread.timeoutInMilliseconds" , value=" 3000" )
})
public String paymentInfo_TimeOutHandler(Integer id){
return "/( ToT)/调用支付接口超时或异常: \t"+ “\t当前线程池名字" + Thread. current Thread(). getName();
}
相关解释
主启动类加上:@EnableHystrix
什么时候会执行兜底方法
@DefaultProperties(defaultFallback = "“)
feign接口系列
配置yml
feign:
hystrix:
enabled : true
写一个类实现client接口
配置@FeignClient注解
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT" , fallback = PaymentFallbackService.class)
在请求服务器超时、异常或者宕机时,会默认执行实现类的相对应方法作为兜底方法
熔断机制概述
原理图
相关状态
相关配置
/=====服务熔断
@HystrixCommand(fallbackMethod = " paymentCircuitBreaker _fallback" , commandproperties = {
@HystrixProperty(name = "circuitBreaker.enabled" ,value = "true"),// 是否开启断路器
@HystrixProperty(name = "circuitBreaker . requestvolumeThreshold" ,value ="10"),// 请求次数
@HystrixProperty(name = "circuitBreaker . sleepwindowInMilliseconds" ,value = "10000"), //时间窗口期
@HystrixProperty(name = "circuitBreaker . errorThresholdPercentage" ,value = "60"),// 失败率达到多少后跳闸
})
三个重要参数
快照时间窗 : 断路器确定是否打开需要统计一些请求和错误数据, 而统计的时间范围就是快照时间窗,默认为最近的10秒。
请求总数阀值:在快照时间窗内,必须满足请求总数阀值才有资格熔断。默认为20,意味着在10秒内,如果该hystrix命令的调用次数不足20次,即使所有的请求都超时或其他原因失败,断路器都不会打开。
错误百分比阀值:当请求总数在快照时间窗内超过了阀值,比如发生了30次调用,如果在这30次调用中,有15次发生了超时异常,也就是超过50%的错误百分比,在默认设定50%阀值情况下,这时候就会将断路器打开。
熔断与链路恢复流程
断路器打开后
原来的主逻辑如何恢复呢?
更多相关配置参数
/====================All @HystrixCommand(fallbackMethod = "str. _fallbackMethod", groupKey = " strGroupCommand" , commandKey = " strCommand" , threadPoolKey = "strThreadPool" , I commandProperties = { //设置隔离策略,THREAD 表示线程池SEMAPHORE: 信号池膈离 @HystrixProperty(name = "execution. isolation.strategy", value = "THREAD"), //当隔离策略选择信号他隔离的时候,用来没置信号他的大小(最大并发数) @HystrixProperty(name = " execution. isolation. semaphore . maxConcurrentRequests", value = "10"), //配置命令执行的超时时间 @HystrixProperty(name = "execution. isolation . thread. timeoutinMilliseconds", value = "10"), //是否启用超时时间 @HystrixProperty(name = " execution. timeout . enabled", value = "true"), //执行超时的时候是否中断 @HystrixProperty(name = "execution. isolation. thread. interruptOnTimeout", value = "true"), //执行被取消的时候是否中断 @HystrixProperty(name = "execution. isolation. thread. interruptOnCance1", value = "true"), //允许回调方法执行的最大并发数 @HystrixProperty(name = "fallback. isolation. semaphore . maxConcurrentRequests", value = "10"), //服务降級是否启用,是否执行回调西数 @HystrixProperty(name = "fallback.enabled", value = "true") , // 该属性用来没置在演动时间窗中,断路器熔断的最小请求数。例如,默认该值为20的时候, //如果熔动时间窗(默610秒)内仅收到了19个请求, 即使这19个请求都失败了,断路器也不会打开。 @HystrixProperty(name = "circuitBreaker . requestVolumeThreshold", value = "20"), //该属性用来设置在演动时间窗中,表示在演动时间窗中,在请求数量超过 // circuitBreaker. requestVolume Threshold 的情况下,如果错误请求数的百分比超过50, . //就把断路器没置为“打开”状态,否则就没置为"关闭”状态。 @HystrixProperty(name = "circuitBreaker . errorThresholdPercentage", value = "50"), //该属性用来没置当断路器打开之后的休眠时间窗。休眠时间窗结束之后, //会将断路器置为”半开”状态,尝t熔断的请求命令,如果依然失败就将断路器继续设置为“打开"状态, //如果成功就没置为"关闭”状态。 @HystrixProperty(name = "circuitBreaker . sleepWindowinMilliseconds", value = "5000"), //断路器强制打开 @HystrixProperty(name = "circuitBreaker . forceOpen", value = "false"), //断路器强制关闭 @HystrixProperty(name = "circuitBreaker . forceClosed", value = "false"), //颇动时间窗设置,该时间用于断路器判断健康度时需要收集信息的持续时间 @HystrixProperty(name = "metrics . rollingStats . timeinMilliseconds", value = "10000"), //该属性用来没置烧动时间窗统计指标信息时划分”桶”的数量,断路器在收業指标信息的时候会根据 //设置的时间窗长度拆分成多个”桶”来累计各度量值,每个”桶"记录了- 段时间内的来集指标。 //比如10秒内拆分成10个”桶"收集这样,所以timeinMilliseconds 必须能被numBuckets 整除。否则会抛异常 @HystrixProperty(name =” metrics . rollingStats . numBuckets", value = "10"), //该属性用来没置采集影响断路器状态的健康快照(请求的成功、错误 百分比)的间隔等待时间。 @HystrixProperty(name = "metrics .healthSnapshot . intervalinMilliseconds", value = "500"), //是否开启请求缓存 @HystrixProperty(name = "requestCache. enabled", value = "true"), // HystrixCommand的执行和事件是否打印日志到HystrixRequestlog中 @HystrixProperty(name = "requestLog . enabled", value = "true"), 」, threadPoolProperties = { //该参数用来没置执行命令线程池的核心线程数,该值也就是命令执行的最大并发量 @HystrixProperty(name = "coreSize", value = "10"), // 该参数用来没置线程他的最大队列大小。当改置为, -1 时,线程池将使用SynchronousQueue 实现的队列, //否则将使用LinkedBlockingQueue实现的队列。 @HystrixProperty(name = "maxQueueSize", value =“-1"), // 该参数用来为队列设置拒绝阀值。通过该参数,即使队列没 有达到最大值也能拒绝请求。 //该参数主要是对LinkedBlockingQueue队列的补充,因为LinkedBlockingQueue //队列不能动态修改它的对象大小,而通过该属性就可以调整拒绝请求的队列大小了。 @HystrixProperty(name = "queueSizeRejectionThreshold", value = "5") })
概述
基本使用
所有服务提供者都要导入spring-boot-starter-actualor包
新建监控工程
主启动类加注解@EnableHystrixDashboard
被监控的类需要加入一个配置
/**
*此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
*ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
*只要在自己的项目里配置上下面的servlet就可以了*/
@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;
}
访问网址:localhost:9001/hystrix
输入网址: localhost:9002/hystrix/stream
如何看
7色
1圈
1线
整图说明A
网关定位
概念
作用
强大之处
特性
与zuul的区别
传统servlet I/O
异步非阻塞
核心逻辑
流程
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前( “pre” )或之后( “post” )执行业务逻辑。
导包:spring-cloud-starter-gateway
配置yml
cloud: gateway: routes : - id: payment_ routh #ayment_ route #路由的ID,没有固定规则但要求唯-,建议配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates : Path=/ payment/get/** #断言,路径相匹配的进行路由 - id: payment_ routh2 #payment_ route #路由的ID,没有固定规则但要求唯- -,建议配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** #断言,路径相匹配的进行路由
需要移除jar包:
转发规律
访问${GATEWAY_ URL}/{微服务X}/**会转发到微服务X的/**路径
配置类配置方法
@Bean
public RouteLocator customRouteLocator( RouteLocatorBuilder builder)
RouteLocatorBuilder. Builder routes = builder.routes();
routes.route("path_route:patguigu", r -> r. path( "/guonei").uri("http://news.baidu.com/ guonei")).build();
return routes . build();
}
@Bean
public RouteLocator cus tomRouteLocator2(RouteLocatorBuilder builder){
RouteLocatorBuilder. Builder routes = builder.routes();
routes.route("path_ route_ atguigu2", r -> r.path(" /guoji") . uri("http://news . baidu. com/ guoji")).build();
return routes.build();
}
微服务名作为路由
改变yml
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用徽服务名进行路由
uri改成
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
作用
断言种类
使用方法
predicates:
- Path=/payment/1b/** # 断言,路径相匹配的进行路由
- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]
#断言,路径相匹配的进行路由
- Before=2020-02-05T15:10:03.685+08:00[As ia/Shanghai]
#断言,路径相匹配的进行路由
- Between=2020-02-02717:45:06.206+08: 00[Asia/Shanghai], 2020-03- 25T18:59:06.206+08:00[Asia/Shanghai]
- Cookie=username , zzyy
- Header=X-Request-Id, \d+ # 请求头要有X- Request- Id属性并且值为整数的正则表达式
- Host=**.atguigu.com
- Method=GET
- Query=username, \d+ # 要有参数名username并且羞还要是整数才能路由
得到时间格式
ZonedDateTime zbj = ZonedDateTime.now(); //默认时区
System.out.println(zbj);
//2020-02- 21[15:51:37.485+98:00[Asia/Shanghai]L
cmd命令行发送请求
curl http://localhost:9588/paymentlnfo --cookie "username=zzyy"
curl http://localhost:9527/payment/lb --cookie "username= zzyy"
创建新的类
public class DayTimeBetweenRoutePredicateFactory extends AbstractRoutePredicateFactory<DayTimeBetweenConfig> { public DayTimeBetweenRoutePredicateFactory(Class<DayTimeBetweenConfig> configClass) { super(configClass); } @Override public Predicate<ServerWebExchange> apply(DayTimeBetweenConfig config) { LocalTime start = config.getStart(); LocalTime end = config.getEnd(); return exchange->{ LocalTime now = LocalTime.now(); return now.isAfter(start)&&now.isBefore(end); }; } @Override public List<String> shortcutFieldOrder() { return Arrays.asList("start","end"); } }
创建新的配置类
属性为 断言的参数
概述
内置过滤器
作用
写一个类实现GlobalFilter ,ordered
放入spring容器
使用案例
@Component @Slf4j public class MyLogGatewayFilter implements GlobalFilter ,ordered{ @override public Mono<Void> filter(ServerwebExchange exchange, GatewayF ilterChain chain) log. info("***********come in MyLogGatewayFilter: " +new Date()); string uname = exchange.getRequest().getQueryParams().getFirst( key: "uname"); if(uname == nu1l) { log.info(*******用户名为nul1,非法用户,0(π_ π)o"); exchange.getResponse().setstatusCode(HttpStatus .NOT_ACCEPTABLE); return exchange.getResponse().setComplete(); } return chain.filter( exchange); } @override public int getorder(){ return 0; } }
过滤器 核心API
方式一:
写一个类继承AbstractGatewayFilterFactory
配置形式
filters:
- name: RequestSize
args:
maxSize: 5000000
方式二:
写一个类继承继承: AbstractNameValueGatewayFilterFactory
配置形式
filters:
- AddRequestHeader=S-Header,Bar
config. getName(),config. getValue ()来获得参数
过滤器和断言的相关源码
Gateway Handler Mapping
Gateway Web Handler :
Order越小越靠前
按配置顺序从1开始
如果配置了默认过滤器,则先执行相同Order的默认过滤器
如需自行控制Order ,可返回OrderedGatewayFilter
网关监控:http://www.imooc.com/article/290822
排错、调试方法:http://www.imooc.com/article/290824
其他配置:http://www.imooc.com/article/290825
限流方式:http://www.imooc.com/article/290828
配置流程
是什么
作用
与gitHub整合配置
先在github/gitee新建一个仓库
通过命令将clone仓库到本地
创建多个配置文件,保存格式必须为UTF-8
新建config服务端工程
导包spring-cloud-config-servers
配置yml
#新增的配置
cloud:
config:
server:
git:
uri: git@github.com:zzyybs/springcfoud-config.git #GitHub 上面的git仓库名字
####搜索目录
search-paths :
- springcloud-config
##读取分支
label: master
主启动类加注解@EnableConfigServer
修改hosts
127.0.0.1 config-3344.com
通过浏览器访问路径可看到配置文件
配置读取规则
#label为分支
#后面两项则为配置文件的前缀和后缀
/{label)/{application)-{profile}.yml
/{application}-{profile}.yml
#返回的为json字符串
/{application}/{profile}[/{label}]
总结
新建客户端config工程
导包spring-cloud-starter-config
配置bootstrap.yml
配置yml
cloud:
#Config客户端配置
config:
1abel: master #分支名称
name: config #配置文件名称
profile: dev #读取后级名称. 上述3个综合: master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
uri: http://localhost:3344 #配置中心地址
测试是否能读取到服务端的配置文件
@RestController
public class ConfigClientController
{
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo()
{
return configInfo;
}
}
此时能读取到文件,但是并不能动态刷新,client需要重启才能重新读取配置文件
修改客户端模块
pom引入监控
修改yml,配置暴露监控端口
#暴露监控端点
management :
endpoints :
web:
exposure :
include : "*"
加注解@RefreshScope
运维人员请求刷新3355
相关概念
Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架
它整合了Java的事件处理机制和消息中间件的功能。
Spring Cloud Bus目前支持RabbitMQ和Kafka.
作用
设计思想
利用消息总线触发一个客户端/bus/refresh,然后客户端继续传播,而刷新所有客户端的配置。
利用消息总线触发一个服务端ConfigServer的/bus/refresh端点,而刷新所有客户端
第二种更加适合
需要有rabbitmq先
给3344config服务端增加消息总线的支持
导包 spirng-cloud-starter-bug-amqp
配置yml
##rabbitmq相关配置,暴露bus刷新配置的端点
management:
endpoints: #暴露bus刷新配置的端点
web:
exposure:
include: ' bus-refresh'
#rabbitmq相关配置15672是Web管理界面的端口; 5672 是MQ访问的端口
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
ps:
给3355,3366config客户端增加消息总线的支持
导包 spirng-cloud-starter-bug-amqp
配置yml
spring:
cloud:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
#暴露监控端点
management :
endpoints :
web:
exposure :
include : "*"
发送请求
流程图
解决的痛点:
总结成一句话
标准MQ
作用
处理架构
遵循发布订阅模式
需要有rabbitmq环境
编写发送端
导包spring-cloud- starter-stream-rabbit
配置yml
#新增配置
cloud:
stream:
binders: #在此处配置要绑定的服务信息;
name-server: 127.0.0.1:9876
bindings: #服务的整合处理
input: #这个名字是一个通道的名称
destination: studyExchange
#如果是rocketMQ,group一定要配置
group: binder-group
#新增配置 cloud: stream: binders: #在此处配置要绑定的rabbitmq的服务信息; defaultRabbit: #表示定义的名称,用于Fbinding整合 type: rabbit #消息组件类型 environment: #设置rabbitmq的相关的环境配置 spring: rabbitmq: host: localhost port: 5672 username: guest password: guest bindings: #服务的整合处理 output: #这个名字是一个通道的名称 destination: studyExchange #表示要使用的Exchange名称定义 content-type: application/json #设置消息类型,本次为json, 文本则设置“text/plain" binder: defaultRabbit #设置要绑定的消息服务的具体设置
编写推送的类
@EnableBinding(Source.class) //定义消息的推送管道
public class MessageProviderImpl implements IMessageProvider{
@Resource
private MessageChannel output; //消息发送管道
@Override
public String send(){
String serial = UUID.randomUUID().tostring();
output.send(MessageBuilder.withPayload(serial).build());
System.out.println("******serial: "+serial);
return null;
}
}
编写消费端
导包spring-cloud- starter-stream-rabbit
编写yml
#新增配置 cloud: stream: binders: #在此处配置要绑定的rabbitmq的服务信息; defaultRabbit: #表示定义的名称,用于Fbinding整合 type: rabbit #消息组件类型 environment: #设置rabbitmq的相关的环境配置 spring: rabbitmq: host: localhost port: 5672 username: guest password: guest bindings: #服务的整合处理 input: #这个名字是一个通道的名称 destination: studyExchange #表示要使用的Exchange名称定义 content-type: application/json #设置消息类型,本次为json, 文本则设置“text/plain" binder: defaultRabbit #设置要绑定的消息服务的具体设置
编写接收消息的类
@Component
@EnableBinding(Sink.class)
public class ReceiveMessagelistenerController{
@Value("${server.port}")
private String serverPort;
@StreamListener(Sink.INPUT)
public void input(Message<String> message){
System.out.println("消费者1号----->接受到的消息:"+message.getPayload()+"\t port: "+serverPort);
}
}
此时会有两个问题
配置分组
配置方法
配置yml
bindings: #服务的整合处理
input: #这个名字是一- 个通道的名称
destination: studyExchange #表示要使用的Exchange名称定义
content-type: application/json #设置消息类型,本次为对象json, 如果是文本则设置“text/plain”
binder: defaultRabbit #设置要绑定的消息服务的具体设置
group: atguiguB
创建新接口
pubLic interface MySource {
String MY_OUTPUT = "my-output";
@Output (MY_OUTPUT)
Mes sageChannel output();
}
配置yml
my-output:
destination: stream-my-topic
加上注解
@EnableBinding ({Source.class, MySource.class})
/**
*全局异常处理
*
* @param message发生异常的消息
*/
@StreamListener("errorChanneL")
public void error(Message<?> message) {
ErrorMessage errorMessage = (ErrorMessage)message;
log.warn("发生异常,errorMessage = {}", errorMessage);
}
监控
actuator多了binding和channel端点
配置里加上
health :
show-details: always
解决痛点
是什么
名词解释
使用命令运行zipkin-server
给项目工程导包
yml新增配置
zipkin:
base-url: http://localhost :9411
sleuth:
sampler :
#采样率值介于0到1之间,1则表示全部采集
probability: 1
打开浏览器访问:http://localhost:9411
即可看到相关调用链路
出现原因
Spring Cloud Netflix进入维护
新组建功能将以其他替代品替代方式实现
诞生
提供功能
jar包
<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>
名字含义
是什么
作用
基本架构
nacos可以在AP和CP之间进行切换
何时选择使用何种模式?
一般来说,如果不需要存储服务级别的信息且服务实例是通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式。当前主流的服务如Spring cloud和Dubbo服务,都适用于AP模式,AP模式为了服务的可能性而减弱了一致性, 因此AP模式下只支持注册临时实例。
如果需要在服务级别编辑或者存储配置信息,那么CP是必须,K8S服务和DNS服务则适用于CP模式。CP模式下则支持注册持久化实例,此时则是以Raft协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误.
切换命令
curl -X PUT '$NACOS.SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
安装启动nacos
将工程注册到nacos
导包
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
改yml
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
management:
endpoints:
web:
exposure:
include: "*"
主启动类加上@EnableDiscoveryClient
导包spring-cloud-starter-alibaba-nacos-config
配置两个yml(application.yml和bootstrap.yml)
bootstrap.yml
cloud:
nacos :
discovery:
server-addr: localhost :8848 #Nacos 服务注册中心地址
config:
server-addr: localhost:8848 #Nacos 作为配置中心地址
file-extension: yaml #指定yaml 格式的配置
application.yml
spring:
profiles:
active: dev #表示开发环境
加@RefreshScope
在配置列表新增配置
dataId格式
${spring.application.name}-${spring.profile.cative}.${spring.cloud.nacos.config.file-extension}
#也可以配置${spring.cloud.nacos.config.prefix}就会变成
${spring.cloud.nacos.config.prefix}-${spring.profile.cative}.${spring.cloud.nacos.config.file-extension}
概念
级别
作用
配置方法
控制台配置
配置文件配置
cloud:
nacos:
discovery:
metadata:
instance: C
haha: hehe
version: 1
解决问题
问题1:实际开发中,通常一个系统会准备
问题2:一个大型分布式微服务系统会有很多微服务子项目,
命名空间和组名
概念
说明
默认情况
在nacos中创建一个命名空间和组
在yml中进行配置
cloud:
nacos:
discovery:
server-addr: localhost :8848 #Nacos 服务注册中心地址
config:
server-addr: localhost :8848 #Nacos 作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: DEV_ GROUP
namespace: 7d8f0f5a-6a53-4785-9686-dd460158e5d4
概述
配置步骤
nacos-server-1.1. 4\nacos\conf目录下找到sql脚本nacos-mysql.sql
nacos- server- 1.1.4\nacos\conf目录下找到application.properties 加上以下配置
spring.datasource.platform=mysql
db.num= 1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout= 1000&socketTimeout=3000&autoReconnect=true
db.user= root
db.password= 123456
推荐使用linux
需要nginx进行反向代理
基本架构
Linux服务器上将数据切换到mysql
Linux服务器上nacos的集群配置cluster.conf
192.168.111.144:3333
192.168.111.144:4444
192.168.111.144:5555
改变启动脚本
达到效果
修改部分
配置nginx,有他作为负载均衡器
架构图
概念
特征
丰富的应用场景
完备的实时监控
广泛的开源生态
完善的SPI扩展点
Sentinel提供简单易用、完善的SPI扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
解决的各种问题
与hystrix对比
两个部分
核心库(Java客户端)不依赖任何框架/库,能够运行于所有Java运行时环境,同时对Dubbo/Spring Cloud等框架也有较好的支持。
控制台(Dashboard) 基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat等应用
容器。
运行命令
java -jar sentinel-dashboard-1.7.0.jar
监控微服务模块
导包
<!--SpringCloud ailibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
配置yml
cloud:
nacos:
discovery:
#Nacos服务注册中心地址
server-addr: localhost: 8848
sentinel:
transport:
#配-Sent inel dashboard地址
dashboard: localhost:8080
#期认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
执行一次访问
访问localhost:8080/sentinel
相关解释
ps:
概念
概述
配置
相关解释
异常数
分钟统计的,所以时间窗口一定要大于60秒
作用
配置方法
controller
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey" , blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1" ,required = false) String p1,
@RequestParam(value = "p2" ,required = false) String p2){
return "testHotKey";
}
public String deal_testHotKey (String p1, String p2, BlockException exception) {
return "----deal_ testHotkey,o(π_ π)o"; //sentinel 系统默认的提示: Blocked by Sentinel (flow limiting)
}
参数例外项
概述
配置
Sentinel系统自适应限流从整体维度对应用入口流量进行控制,结合应用的Load、CPU 使用率、总体平均RT、入口QPS和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
配置
相关说明
Load自适应(仅对Linux/Unix-like机器生效)
CPU usage (1.5.0+版本)
平均RT
并发线程数
入口QPS
源码
主要属性
@RequestMapping("/consumer/fallback/{id}")
//@SentinelResource(value = "fallback") //没有配置
//@SentinelResource(value = "fallback", fallback = "handlerFallback") //fallback只负责业务异常
//@SentinelResource(value = "fallback", blockHandler = "blockHandler") //blockHandler 只负责sentinel控制台配置违规
@SentinelResource(value = "fallback",fallback = "handlerFallback" ,blockHandler="blockHandler")
配置规则时
@GetMapping( "/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class ,
blockHandler = "handlerException2")
sentinel如何获得微服务的相关信息
主机:接口/api 可以得到api接口的类型和和规则
主机:接口/acturator/sentinel 可以访问到sentinel的相关信息
相关源码
注册/心跳发送
通信API
spring.cloud.sentinel.transport:
#指定控制台的地址
dashboard: localhost:8080
#指定和控制台通信的IP
#如不配置,会自动选择一个IP注册
client-ip: 127.0.0.1
#指定和控制台通信的端口,默认值8719
#如不设置,会自动从8719开始扫描,依次+1,直到找到未被占用的端口
port: 8719
#心跳发送周期,默认值null
#但在SimpleHttpHeartbeatSender会用默认值10秒
heartbeat-interval-ms: 10000
先关闭监控
sentinel:
transport:
dashboard: localhost:8080
filter:
enabled: false
使用到了三大核心API
@GetMapping("/test-sentinel-api") public String testSentinelAPI( @RequestParam(required = false) String a) { // 定义一个sentinel保护的资源, 名称是test-sentinel-ap Entry entry = null; try { entry = SphU.entry("test-sentinel-api") //被保护的业务逻辑 return a; //如果被保护的资源被限流或者降级了,就会抛BlockExcepti() } catch (BlockException e) { Log.warn("限流,或者降级了",e); return "限流,或者降级了"; } finally { if (entry != null) { //退出entry了 entry.exit(); } } }
现在情况:代码只会统计BlockException
解决方法
} catch (IllegaLArgumentException e2) {
// 统计IllegalArgumentException [发生的次数、发生占比...]
Tracer. trace(e2) ;
} finally {
设置来源
String resourceName = "test-sentineL-api" ;
ContextUtil.enter( resourceName,"test-wfw") ;
整合restTemplate
单个配置
配置开关
相关源码
整合fegin
配置文件配置
如何得到异常
@Component
@Slf4j
pubLic class UserCenterFeignClientFallbackFactory implements FallbackFactory{
@Override
pubLic User CenterFeignClient create(Throwable cause) {
return new UserCenterFeignClient() {
@Override
pubLic UserDTO findById(Integer id) {
Log.warn( marker: "远程调用被限流/降级了",e) ;
UserDT0 userDTO = new UserDT0( ) ;
use rDTO. setWxNickname("一个默认用户") ;
return userDTO;
};
}
}
使用姿势总结
自定义异常处理
public class MyUrlBlockHandler implements UrlBlockHandler { @Override public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex){ if(ex instanceof FlowException) { }else if(ex instanceof DegradeException){ }else if(ex instanceof ParamFlowException){ } else if(ex instanceof SystemBlockException){ } else if(ex instanceof AuthorityException){ } } }
自定义识别处理来源
@Component
public class MyRequestQriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
//从请求参数中获取名为origin 的参数并返回
//如果获取不到origin参数,那么就抛异常
String origin = request.getParameter("origin");
if (StringUtils.isBlank(origin)) {
throw new IllegalArgumentException("origin must be specified");
}
return origin;
}
}
自定义处理资源名称
@Component public class MyUrlCleaner implements UrlCleaner { @Override public String clean(String originUrl) { //让/shares/I 与/shares/2的返回值相同 //返回/ shares/ {number} String[] split = originUrl.split("/"); Arrays.stream(split) .map(string -> { if (NumberUtils.isNumber(string)) { return " {number}"; } return string; }) .reduce((a, b) -> a + " /" + b) .orElse(""); return originUrl; } }
总结
推拉模式
。。。
集成阿里云AHAS
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>spring-boot-starter-ahas-sentinel-client</artifactId> <version>1.3.3</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <exclusions> <exclusion> <artifactId>spring-cloud-alibaba-sentinel</artifactId> <groupId>com.alibaba.cloud</groupId> </exclusion> </exclusions> </dependency>
ahas.namespace: default
project.name: content-center
ahas.license: f9b19cf6e26f4fca9595726a1cd7e403
是什么
Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。
相关概念
执行步骤
修改file.conf
service {
#修改部分
vgroup.mapping.my_test._tx.group ="p_tx_group"
default.grouplist = "127.0.0.1:8091"
enableDegrade = false
disable = false
max.commit.retry.timeout = "-1"
max.rollback.retry.timeout= "-1"
}
## transaction log store store { ## store mode: file、db #修改处 mode = "db" ## database store db { ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc. datasource = " dbcp" ## mysq/oracle/h2/oceanbase etc. db-type = "mysql" #修改处 driver-class-name = *com.mysql.jdbc.Driver" url = "jdbc:mysql://127.0.0.1:3306/seata” user = "root" password =“你自己密码" min-conn = 1 max-conn = 3 global.table = *global. _table* branch.table = "branch_ _table" lock-table = "lock. _table" query-limit = 100 }
新建数据库表
修改registry.conf
registry {
# file、nacos 、eureka、 redis、 zk、 consul、 etcd3、 sofa
#修改部分
type = "nacos"
nacos {
#修改部分
serverAddr = "localhost:8848"
namespace = ""
cluster = "default"
}
分布式的模块设置
导jar包
<!--seata--> <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.0.0</version> </dependency>
配置yml
cloud:
alibaba:
seata:
#自定义事务组名称需要seatg- server中的对应
tx-service-group: fspl_tx_group
将file.conf和register.conf拷贝到项目中
主启动类取消数据源的自动配置
在事务的入口方法上加上注解@GlobalTransational
补充
saeta有四大模式
概述
执行流程
概览图
一阶段加载
在一阶段, Seata 会拦截“业务SQL"
以上操作全部在一个数据库事务内完成, 这样保证了一阶段操作的原子性。
二阶段提交
顺利提交
因为“业务SQL"在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁删掉, 完成数据清理即可。
二阶段回滚
总流程
eout = “-1”
max.rollback.retry.timeout= “-1”
}
```properties ## transaction log store store { ## store mode: file、db #修改处 mode = "db" ## database store db { ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc. datasource = " dbcp" ## mysq/oracle/h2/oceanbase etc. db-type = "mysql" #修改处 driver-class-name = *com.mysql.jdbc.Driver" url = "jdbc:mysql://127.0.0.1:3306/seata” user = "root" password =“你自己密码" min-conn = 1 max-conn = 3 global.table = *global. _table* branch.table = "branch_ _table" lock-table = "lock. _table" query-limit = 100 }
新建数据库表
修改registry.conf
registry {
# file、nacos 、eureka、 redis、 zk、 consul、 etcd3、 sofa
#修改部分
type = "nacos"
nacos {
#修改部分
serverAddr = "localhost:8848"
namespace = ""
cluster = "default"
}
分布式的模块设置
导jar包
<!--seata--> <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.0.0</version> </dependency>
配置yml
cloud:
alibaba:
seata:
#自定义事务组名称需要seatg- server中的对应
tx-service-group: fspl_tx_group
将file.conf和register.conf拷贝到项目中
主启动类取消数据源的自动配置
在事务的入口方法上加上注解@GlobalTransational
补充
saeta有四大模式
概述
执行流程
概览图
[外链图片转存中…(img-hxUnTCNf-1586497723971)]
一阶段加载
在一阶段, Seata 会拦截“业务SQL"
以上操作全部在一个数据库事务内完成, 这样保证了一阶段操作的原子性。
[外链图片转存中…(img-TyVQAGlh-1586497723972)]
二阶段提交
顺利提交
因为“业务SQL"在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁删掉, 完成数据清理即可。
[外链图片转存中…(img-OYvlpwxZ-1586497723972)]
二阶段回滚
[外链图片转存中…(img-Pao8pUwu-1586497723973)]
总流程
[外链图片转存中…(img-KWAOc9ab-1586497723974)]
[外链图片转存中…(img-1qt701KB-1586497723975)]
https://gitee.com/skyfeacher/springCloud
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。