赞
踩
项目技术栈图:
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、智能路由、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包
协调各个微服务,简化分布式系统开发。
微服务的框架那么多比如:dubbo、Kubernetes,为什么就要使用Spring Cloud的呢?
目前国内主流的是nacos,eureka几乎已启用。
防止注册中心崩了,整个服务都崩了。
eureka之间相互注册,相互守望。
eureka会通过心跳来判断某个微服务是不是正常,如果某个eureakServer端在固定时间内没有收到某个微服务的心跳包,便会将该服务从服务注册列表中剔除。
我项目中主要用nacos来作服务发现,同时用作服务配置中心
配置:
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: 10.211.55.17:8848 #配置的Nacos地址(本机的写localhost:8848,服务器的写IP地址)
同时得在主启动类添加 @EnableDiscoveryClient
注解
配置:
server:
port: 3377
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: 10.211.55.17:8848 #Nacos服务注册中心地址(本机的写localhost)
config:
server-addr: 10.211.55.17:8848 #Nacos作为配置中心地址(本机的写localhost)
file-extension: yml #指定yml格式配置
spring:
profiles:
active: dev #表示开发环境
对于Feign的使用,我的理解:
在没有微服务的时候,我自己的项目都是使用HttpClient来发送请求,
在后来有了微服务后,我们使用RestTemplate对请求地址做封装处理,然后使用RestTemplate来发送请求
有了feign之后,我们可以使用feign定义一个接口,来实现请求的发送,服务的调用。
feign可以对服务调用的超时时间进行设置
可以对feign接口的调用情况进行监控和输出
feign集成了ribbon实现了负载均衡
默认Feign客户端只等待一秒钟,但是服务端处理需要超过一秒钟,导致Feign客户端不想等待了,直接返回报错,为了避免这样的情况,有时候我们需要设置Feign客户端的超时控制。
注意feign的默认超时时间,我刚开始用feign的时候因为这个问题浪费了我一天时间
feign的熔断和降级支持hystrix和sentinel两种方式,默认使用的是hystrix。
可以在配置文件中设置sentinel.enable=true来开启
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。
处理方式:服务降级。
假如服务不能使用了,我们可以进行一个友好的提示,不让用户等待太长的时间。
哪些情况会导致服务降级:
我对服务降级的理解:
当双11活动时,把无关交易的服务统统降级,如查看蚂蚁深林,查看历史订单,商品历史评论,只显示最后100条等等。把主要的流量放到双11主战场,其他的无关服务通通降级。
秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行。
熔断的目的是当A服务模块中的某块程序出现故障后为了不影响其他客户端的请求而做出的及时回应。
降级的目的是为了解决整体项目的压力,而牺牲掉某一服务模块而采取的措施。
他们相似的地方:
区别的地方:
我的理解:在发生服务雪崩等异常情况时,通过Hystrix来实现服务降级和服务熔断:停止某个服务的使用,如果有请求访问此服务,返回一个友好的提示。
主要注解:HystrixCommand
// 超时访问,演示降级 // fallbackMethod为兜底的方法, // HystrixProperty为设置线程超时时间 @HystrixCommand(fallbackMethod = "paymentInfo_TimeoutHandler",commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000") }) public String paymentInfo_TimeOut(Integer id) { int a = 5/0; // TimeUnit.SECONDS.sleep(6); return "接口调用正常"; } // 兜底方法 public String paymentInfo_TimeoutHandler(Integer id) { return "/(ToT)/调用支付接口超时或异常、\t" + "\t当前线程池名字" + Thread.currentThread().getName(); }
@EnableCircuitBreaker
注解用于代替Hystrix,
有自己的客户端
可以进行各种各样的降级规则配置
配置的限流、熔断的一些规则可以进行持久化。
主要注解:SentinelResource
yml中配置示例:
spring:
application:
name: cloudalibaba-sentinal-service
cloud:
nacos:
discovery:
#Nacos服务注册中心地址(改成自己的服务器ip地址,本地用localhost)
server-addr: 10.211.55.26:8848
sentinel:
transport:
#配置Sentin dashboard地址(改成自己的服务器ip地址,本地用localhost)
dashboard: 10.211.55.26:8858
# 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的 端口
port: 8719
在feign调用中添加回调函数:
@Component @FeignClient(value = ServerNameConstant.INTEGRITY_MOBILE, contextId = "integralServiceClient", fallbackFactory = IntegralServiceFallback.class) public interface IntegralFeignService { @PostMapping("/integral/questionnaire") void questionnaireScore(@RequestBody UserDetailInfo userInfo); } @Slf4j @Fallback public class IntegralServiceFallback implements FallbackFactory<IntegralFeignService> { @Override public IntegralFeignService create(Throwable throwable) { return new IntegralFeignService() { @Override public void questionnaireScore(UserDetailInfo userInfo) { } }; } }
基于webflux框架实现的异步非阻塞架构,而webflux框架底层则使用了高性能的Reactor模式通信框架Netty。
应用位置:
web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。predicate就是我们的匹配条件;而filter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了。
uri: ws://localhost:9000
uri: http://localhost:8130/
uri: lb://brilliance-consumer
spring: application: name: cloud-gateway cloud: gateway: routes: # 路由 - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名 #匹配后提供服务的路由地址 uri: http://localhost:8001 predicates: - Path=/payment/get/** # 断言,路径相匹配的进行路由 - id: payment_route2 uri: http://localhost:8001 predicates: - Path=/payment/lb/** #断言,路径相匹配的进行路由
通过微服务名实现动态路由:
默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。
cloud: gateway: globalcors: corsConfigurations: '[/**]': allowedOrigins: "*" allowedMethods: "*" allowedHeaders: "*" allowCredentials: false routes: - id: CREA-Auth-Social uri: lb://CREA-Auth # 匹配后提供服务的地址 predicates: - Path=/auth/social/** # 断言,路径相匹配的进行路由 filters: - name: CircuitBreaker # CircuitBreaker类型断路器 - id: CREA-Auth uri: lb://CREA-Auth predicates: - Path=/auth/** # filters: # - name: Hystrix # args: # name: attentionfallback # fallbackUri: forward:/fallback/CREA-Auth
分布式系统面临的问题:
解决方式:使用config进行统一的配置文件管理
nacos同样可以用作服务配置,我项目中使用的就是nacos。
是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。
分布式事务处理过程的1ID+三组件模型:
处理过程:
TC,TM,RM
执行流程:
屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型
不同的mq架构设计不同,如果以后我们需要修改mq,代码开发工作量巨大,使用stream就给我们一种解耦合的方式
配置:
cloud: stream: binders: #在此处配置要绑定的rabbitmq的服务信息 defaultRabbit: #表示定义的名称,用于binding整合 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 #设置要绑定的消息服务的具体设置
主要代码:
发送:
// 不需要@service注解
@EnableBinding(Source.class) //定义消息的推送管道(Source是spring的)
public class IMessageProviderImpl implements IMessageProvider {
@Resource
private MessageChannel output; //消息发送管道
@Override
public String send() {
String serial = UUID.randomUUID().toString();
output.send(MessageBuilder.withPayload(serial).build()); //MessageBuilder是spring的integration.support.MessageBuilder
System.out.println("*******serial: " + serial);
return null;
}
}
接收:
@EnableBinding(Sink.class)
@Controller
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);
}
}
服务注册组件有eureka、nacos、zookeeper。
我们想项目中使用的为nacos。
主要是临时实例和非临时实例的区别:
主要有:轮询、权重、随机
即如果一个服务的接口出现问题了,返回一个友好的提示。
通常通过feign进行配置:
我们项目中用的springboot-admin。
可以看到是哪里(在哪个服务中)很慢
使用的是漏桶算法:
seata支持三种工作模式:
如果强一致性不高,可以使用这种方式。
多次点击提交订单,此时因为第一次提交已经删除了token,所以后面的操作就获取不到这个token,就会直接返回。保证了只有一个请求执行:
如果拿到锁,再执行,拿不到就等待(或者快速失败)。
这里可以控制锁的粒度。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。