4.分布式系统
1.三个组件
springcloud提供的三个组件
- 注册中心:Eureka--》已经停止维护了
- 配置中心:SpringCloudConfig
- 网关:Zuul
对于本项目使用的是springcloud Alibaba,使用简单而且学习曲线低
Nacos:注册中心和配置中心
Sentinel:服务容错(限流,熔断,降级)
Seata(原Fescar):分布式解决方案
以下式springcloud本项目中使用的组件:
Ribbon:负载均衡
Feign:调用远程服务,声明式http客户端
GateWay:API网关
Sleuth:调用链监控
2.版本依赖关系
查询得知版本后在common模块里添加如下版本依赖控制
<dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.6.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
3.Nacos注册中心
下载nacos服务中心server--我下的是1.3.1
这个需要把环境变量设置的名字改成javaHome--不想改环境变量可以这么操作--》问题解决
因为每个服务都需要注册中心,所以放在common里
<!-- nacos--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
在用到nacos的模块配置文件配置nacos的地址和这个服务的名字
spring: datasource: username: root password: root url: jdbc:mysql://192.168.116.128:3306/gulimall_sms driver-class-name: com.mysql.jdbc.Driver #配置nacos cloud: nacos: discovery: server-addr: 127.0.0.1:8848 application: name: gulimall-coupon # MapperScan # sql映射文件位置 mybatis-plus: mapper-locations: classpath:/mapper/**/*.xml global-config: db-config: id-type: auto server: port: 7000
在主程序上开启服务的注册发现的客户端注解
在运行之前得先把nacos服务器启动
启动项目后访问8848端口查看服务
账号密码都是nacos
在服务管理的服务列表就能发现我们的服务了
接下来把所有的模块都注册进服务中心
4.Feign远程调用--我们最开始创建项目的时候已经引入依赖了
来尝试使用feign写一个远程服务,让会员member去调用一下优惠券coupon的内容
需要实现的效果,请求http://localhost:8000/member/member/coupons后携带出会员的信息和优惠券的信息
1.先在coupon里编写一个函数,让这个函数成为我们即将远程调用的函数,让这个优惠券携带一个满100减10的信息
/** * * @return 返回ok状态并且携带参数 */ @RequestMapping("member/list") public R memberCouponEntity(){ CouponEntity entity = new CouponEntity(); entity.setCouponName("满100减10"); return R.ok().put("coupons",Arrays.asList(entity)); }
2.在member模块的主函数里启用远程调用功能并且指定扫描的包在哪
3.创建一个feign包这个包里放置所有远程调用的接口
接口
/** * @author wuyimin * @create 2021-08-03 18:30 * @description 调用远程服务的接口 */ @FeignClient("gulimall-coupon")//告诉springcloud这里需要调用远程服务,这里是注册中心给的模块的名字 public interface CouponFeignService { //远程接口,如果以后这个方法被调用,那么就会去调用coupon里的对应方法,这里的方法信息必须和coupon里的一致 @RequestMapping("coupon/coupon/member/list")//这里要写全路径 public R memberCouponEntity(); }
4.在controller中调用刚刚的接口
这里先创建了一个会员对象设置名字后,我们调用接口,它的return值里携带了coupon的信息,把他们一起存到R(其实就是一个map)中然后return回去
@Autowired private CouponFeignService couponFeignService; @RequestMapping("/coupons") public R test(){ MemberEntity memberEntity=new MemberEntity(); memberEntity.setNickname("zhangsan"); R r = couponFeignService.memberCouponEntity(); return R.ok().put("member",memberEntity).put("coupons",r.get("coupons")); }
PS:如果此时coupon服务下线了,就会直接出现超时异常
5.使用nacos的配置中心功能
在common中需要引入一个依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
更改配置从前的做法
1.模拟配置文件
#不加coupon前缀的话取出的是系统的环境变量
coupon.user.name=zhangsan
coupon.user.age=18
2.在具体controller里面使用@Value注解取出配置的值
public class CouponController { @Value("${coupon.user.name}") private String name; @Value("${coupon.user.age}") private String age; @RequestMapping("/test") public R test(){ return R.ok().put("name",name).put("age",age); } }
弊病:当前应用正在上线中,改了应用配置之后需要重新打包再上线,而且配置文件需要在多台电脑上反复修改
有了配置中心以后
3.添加bootStrap配置文件
#此文件会优先于application.properties来加载 #配置中心的信息 spring.application.name=gulimall-coupon spring.cloud.nacos.config.server-addr=127.0.0.1:8848
4.在controller上增加配置中心刷新的注解
@RestController @RequestMapping("coupon/coupon") @RefreshScope//用于刷新的时候动态更改配置中心发布的内容 public class CouponController { @Value("${coupon.user.name}") private String name; @Value("${coupon.user.age}") private String age; @RequestMapping("/test") public R test(){ return R.ok().put("name",name).put("age",age); } }
5.进入配置中心后点击配置列表后点击右边的+增加配置
项目运行的时候,输出信息栏会有一个配置的名字,默认是应用名.properties
把原来的配置搬家到配置中心后点击发布
发布新建配置后后需要重启一下coupon服务
6.可以看到现在的配置列表里已经多了一个配置
修改一下配置,发现已经可以实时更新了
如果配置中心和当前应用都配置了相同的内容,那么以配置中心为准(毕竟bootstrap先运行)
6.nacos作为配置中心的更多细节
1.命名空间(默认是public)
1.命名空间基于环境进行隔离
在配置列表里所有新建的配置都属于默认的public空间里。
我们可以添加多个命名空间来达到隔离的效果,每个命名空间的变量是不互通的
通过在配置文件里切换命名空间来更换环境,这里需要使用命名空间的uuid
此时返回的已经变成prop配置中心的xiaoliu了
2.每一个微服务之间互相隔离,每一个微服务都创建自己的命名空间
2.配置集:所有配置的集合
3.配置集ID:类似文件名就是Data ID
4.配置分组
默认所有的配置集都属于DEFAULT_GROUP;
比如双十一的时候用哪一组配置,六一八的时候用哪一组配置
通过配置文件中的spring.cloud.nacos.config.group=DEFAULT_GROUP来控制使用的是哪个组
5.在此项目中配置中心如何工作
每个微服务创建自己的命名空间,使用配置分组区分环境,dev,test,prod
6.加载多配置集
在其中用数组spring.cloud.nacos.config.extension-configs[]
写明每个配置集
spring.application.name=gulimall-coupon spring.cloud.nacos.config.server-addr=127.0.0.1:8848 # 可以选择对应的命名空间 # 写上对应环境的命名空间ID spring.cloud.nacos.config.namespace=b176a68a-6800-4648-833b-be10be8bab00 # 更改配置分组 spring.cloud.nacos.config.group=dev spring.cloud.nacos.config.extension-configs[0].data-id=datasource.yml spring.cloud.nacos.config.extension-configs[0].group=dev spring.cloud.nacos.config.extension-configs[0].refresh=true spring.cloud.nacos.config.extension-configs[1].data-id=mybatis.yml spring.cloud.nacos.config.extension-configs[1].group=dev spring.cloud.nacos.config.extension-configs[1].refresh=true spring.cloud.nacos.config.extension-configs[2].data-id=other.yml spring.cloud.nacos.config.extension-configs[2].group=dev spring.cloud.nacos.config.extension-configs[2].refresh=true
7.GateWay网关-》路由,过滤,限流,监控
1.创建网关模块
2.网关也需要注册到注册中心,所以要依赖common模块,注意这里依赖完common模块以后也导入了输入源之类的包,如果运行网关模块会报错,所以要排除掉与数据源相关的配置
//开启服务的注册发现(配置注册中心地址) @EnableDiscoveryClient @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) public class GulimallGatewayApplication { public static void main(String[] args) { SpringApplication.run(GulimallGatewayApplication.class, args); } }
3.来测试一下网关的路由功能
网关的配置信息
这里表示的是如果url带了baidu就转发到www.baidu.com
url是uri的子集,
uri:地球/中国/湖南大学/研一/wuyimin
url:wuyimin
结果:
这个其实访问的是qq/hello,因为没有hello请求所以出现这个页面