spring cloud 常用方式和常见问题
1、cloud alibaba 简介
官方文档 https://gitee.com/mirrors/Spring-Cloud-Alibaba?_from=gitee_search
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。
主要功能
- 服务限流降级:默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
- 服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
- 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
- 消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
- 分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。。
- 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
- 分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。
- 阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
由于spring cloud 很多组件都停止维护,为了保证spring cloud,使用spring cloud alibaba的一些组件进行代替
组件
Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
Dubbo:Apache Dubbo™ 是一款高性能 Java RPC 框架。
Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
Alibaba Cloud ACM:一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品。
Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
Alibaba Cloud SchedulerX: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
Alibaba Cloud SMS: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
2、整合nacos服务
实现服务注册
定义Pom
<!--服务注册--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
在服务中创建bootstrap.properties
# nacos服务 spring.cloud.nacos.server-addr=127.0.0.1:8848 # 服务名 spring.application.name=baiyuanhui-service-ums
在各个服务中创建启动配置文件
3、openFegin快速使用
定义pom依赖
<!--服务调用--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
服务提供者
使用正常controller
@RestController @RequestMapping("ums/growthchangehistory") public class HelloController { @GetMapping("/hello") public R hello() { MemberEntity memberEntity = new MemberEntity(); memberEntity.setNickname("tony"); memberEntity.setJob("工程师"); return R.ok().put("item",memberEntity); } }
服务消费者
@FeignClient(name = "baiyuanhui-service-ums") // 远程服务名 @RequestMapping("/ums/growthchangehistory") // 公共请求地址 public interface UmsFeign { @GetMapping("/hello") public R hello() ; }
在消费者启动类上开启远程调用服务
@EnableFeignClients // 开启远程服务调用 public class PmsApplication { public static void main(String[] args) { SpringApplication.run(PmsApplication.class); } }
4、配置中心
配置中心仍然使用nacos
配置中心添加命名空间
每一个服务都有自己命名空间,通过分组区分开发、测试、生产环境
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eeDopLwQ-1607187334410)(image/image-20200710144913283.png)]
修改baiyuanhui-service工程pom
添加配置中心依赖
<!--配置中心--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
修改服务模块中的bootstrap.properties
将对应的配置文件
# nacos服务 spring.cloud.nacos.server-addr=127.0.0.1:8848 # 服务名 spring.application.name=baiyuanhui-service-oms # 命名空间 spring.cloud.nacos.config.namespace=4eb8aa51-3cdf-49d7-9a60-7d20a68af1ee # 配置文件Id spring.cloud.nacos.config.extension-configs[0].data-id=datacourse.yml # 分组 spring.cloud.nacos.config.extension-configs[0].group=dev # 是否动态刷新 spring.cloud.nacos.config.extension-configs[0].refresh=true
PS 注意
动态刷新表示可以每次获取配置数据都从远程获取,当远程nacos修改了配置文件,那么应用每当读取配置文件都会从nacos中进行获取
5、Gateway网关
5.1 简单使用
使用gateway作为网关进行路由的转发、鉴权操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Thds1dCq-1607187334413)(image/image-20200710210315043.png)]
创建工程baiyuanhui-gateway
定义pom依赖
gateway网关不能引入start-web服务
<!-- gateway网关场景启动器 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
创建application.yml
可以拥有多种匹配规则
server: port: 22100 spring: application: name: baiyuanhui-gateway cloud: nacos: server-addr: 127.0.0.1:8848 gateway: routes: - id: baiud # 路由Id uri: https://www.baidu.com # 路由地址 predicates: - Path=/baidu # 匹配规则
5.2 匹配规则
gateway可以拥有多种匹配规则
官方文档 https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.3.RELEASE/reference/html/#the-method-route-predicate-factory
- Route: 路由匹配
- Predicate: 断言匹配,使用java的方式进行断言匹配
- Filter: 过滤器,可以在请求的时候进行对请求进行过滤器,可以在请求中增加请求参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c3iFhNLM-1607187334414)(image/image-20200710211323860.png)]
5.3 路由重写
通过官方文档,跨域使用filter进行路由的重定向
server: port: 22100 spring: application: name: baiyuanhui-gateway # 服务名 cloud: nacos: server-addr: 127.0.0.1:8848 # nacos地址 gateway: routes: - id: renren-fast uri: lb://renren-fast predicates: - Path=/api/** # 匹配规则 filters: # 过滤器 - RewritePath=/api(?<segment>/?.*), /renren-fast/$\{segment} # 路由重定向,前面为匹配,后面是需要替换的值
5.4 CORS跨域
在网关中配置了跨域,那么在后面的服务模块中将不需要在配置跨域
有两种配置方式,一种通过配置文件的方式
定义application.yml
server: port: 22100 spring: application: name: baiyuanhui-gateway # 服务名 cloud: nacos: server-addr: 127.0.0.1:8848 # nacos地址 gateway: globalcors: cors-configurations: # cros跨域配置 '[/**]': allowedOrigins: "*" # 允许所有请求来源 allowedMethods: "*" # 允许所有请求方法 allowedHeaders: "*" # 允许所有请求头 allowCredentials: true # 允许携带cookie
代码实现配置
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsWebFilter; import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; @Configuration public class GatewayCorsConfig { /** * 跨域配置,代码方式 * @return */ @Bean public CorsWebFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration configuration = new CorsConfiguration(); configuration.addAllowedHeader("*"); // 允许头进行跨域 configuration.addAllowedMethod("*"); // 允许那些请求方式可进行跨域 configuration.addAllowedOrigin("*") ; // 那些请求来源可以进行跨域 configuration.setAllowCredentials(true); // 允许携带cookie进行跨域 source.registerCorsConfiguration("/**",configuration); return new CorsWebFilter(source); } }
6、feign之间传递流对象
feign服务之间的调用,传参默认的格式为:ContentType=application/x-www-form-urlencoded
以表单的形式传参的,而文件流的传参,需要form-data的ContentType,否则会报错的一下是解决fegin调用的文件流程传递
原作者地址:https://blog.csdn.net/u014534643/article/details/82495648
1.添加依赖
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.8.0</version>
</dependency>
注意spring boot版本是2.x以上的,上面两个依赖的版本不低于3.5.0,否则还是无效的
2.新建feign的配置
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @description : 解决feign传递流数据的异常
* @createTime :2020/6/14
*/
@Configuration
public class FeignSupportConfig {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
}
3. 配置feign接口
@Component
@FeignClient(value = "baiyuanhui-service-third-party",configuration = {FeignSupportConfig.class})
public interface ThirdPartyFeign {
/**
* 保存到阿里云端
* @param file 上传的文件
* @return
*/
@PostMapping(value = "third-party/oss/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R ossUpload2(@RequestPart("file") MultipartFile file);
}
这里参数参数不可以使用RequestParam,必须使用RequestPart
服务端保持不变
/**
* 保存到阿里云端
* @param file 上传的文件
* @return
*/
@RequestMapping(value = "/upload")
public R ossUpload2(@RequestParam("file") MultipartFile file){
String path = this.ossService.uploadFile(file);
return R.ok().put("data",path);
}