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网关-》路由,过滤,限流,监控

API 网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 API 网关这一层。也就是说,
API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 API 网关来做,这样既提高业务灵活性又不缺安全性,典型的架构图如图所示:

 官网传送门

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请求所以出现这个页面

 

 

 

 

 

 

 

 

 

posted @ 2021-08-03 15:12  一拳超人的逆袭  阅读(57)  评论(0编辑  收藏  举报