gulimall-分布式组件
一、分布式SpringCloud环境
组件选择
注册中心:SpringCloud Alibaba Nacos
配置中心:SpringCloud Alibaba Nacos
负载均衡:SpringCloud Ribbon
声明式HTTP客户端:SpringCloud Feign ——调用远程服务
负载均衡:SpringCloud Ribbon —— feign中已经整合,无需显示引用
服务容错:SpringCloud Alibaba Sentinel ——限流、降级、熔断
API网关:SpringCloud Gateway ——webflux 编程模式
调用链路监控:SpringCloud Sleuth
分布式事务:SpringCloud Alibaba Seata ——原Fescar
版本说明
推荐版本
二、1. nacos用作服务注册中心
2.1 下载 Nacos Server
2.2 Linux安装 Nacos Server
1.下载对应系统的tar包(Linux)或者zip包(Windows),解压后运行bin目录下的可执行文件即可运行Nacos
2.sudo docker pull nacos/nacos-server:1.2.1
3.docker 启动Nacos
sudo docker run --name nacos -d -p 8848:8848 --privileged=true --restart=always -e JVM_XMS=512m -e JVM_XMX=2048m -e MODE=standalone -e PREFER_HOST_MODE=hostname -v /home/nacos/logs:/home/nacos/logs nacos/nacos-server:1.2.1
三、父pom新增依赖
如已有下面依赖请注释,使用一下依赖
<properties>
<spring.boot.version>2.2.5.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR3</spring.cloud.version>
<cloud.alibaba.version>2.2.1.RELEASE</cloud.alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
四、使用nacos作为注册中心
4.1 common模块引入nacos-discovery依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
4.2 配置
在随便一个服务加上 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring:
datasource:
username: root
password: root
url: jdbc:mysql://192.168.33.10:3306/gulimall_pms?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
application:
name: gulimall-product
cloud:
nacos:
discovery:
server-addr: 192.168.33.10:8848
# MapperScan
# sql映射文件位置
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
server:
port: 10000
4.3 在主启动类上使用 @EnableDiscoveryClient 注解开启服务注册与发现功能在这里插入代码片
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallCouponApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallCouponApplication.class, args);
}
}
4.4 进入nacos
此时,启动Nacos,运行主启动类启动服务后,在浏览器打开配置文件中的地址:127.0.0.1:8848/nacos (账号密码:nacos/nacos)中就可以看到当前服务已经注册到 Nacos 服务列表中
其他服务以同样方式配置即可
五、使用Feign远程调用服务
5.1 common引入Feign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
5.2 主启动类开启远程调用功能
@EnableFeignClients(basePackages = "com.jyyy.gulimall.member.feign")
@EnableDiscoveryClient
@SpringBootApplication
public class MallMemberApplication {
public static void main(String[] args) {
SpringApplication.run(MallMemberApplication.class, args);
}
}
5.3 远程调用过程测试
member调用coupon
coupon模块接口定义
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
@RequestMapping("/member/list")
public R membercoupons() {
CouponEntity couponEntity = new CouponEntity();
couponEntity.setCouponName("满100减10");
return R.ok().put("coupons", Arrays.asList(couponEntity));
}
}
member定义远程调用接口
1. 首先在接口上加上@FeignClient注解声明要调用哪个服务
2. 定义接口方法,并声明要调用服务接口的地址 @RequestMapping("/coupon/coupon/member/list")
当前接口方法的的含义:当前服务调用该方法,会到服务注册中心找到 mall-coupon 服务,去调用该服务的/coupon/coupon/member/list 请求对应的方法。
在member的com.jyy.gulimall.member.feign包下新建类
@FeignClient("gulimall-coupon")
public interface CouponFeignService {
@RequestMapping("/coupon/coupon/member/list")
R memberCoupons();
}
在member的控制层写一个测试请求
@RestController
@RequestMapping("member/member")
public class MemberController {
@Autowired
private MemberService memberService;
@Autowired
CouponFeignService couponFeignService;
@RequestMapping("/coupons")
public R test(){
MemberEntity memberEntity = new MemberEntity();
memberEntity.setNickname("会员昵称张三");
//假设张三去数据库查了后返回了张三的优惠券信息
R membercoupons = couponFeignService.memberCoupons();
//打印会员和优惠券信息
return R.ok().put("member",memberEntity).put("coupons",membercoupons.get("coupons"));
}
启动服务,测试
测试:http://localhost:8000/member/member/coupons
解析
1. 当前请求member服务的 /member/member/coupons 请求;
2. 会调用couponFeignService.memberCoupons();
3. 此时会到服务注册中心找到 mall-coupon 服务;
4. 调用该服务的/coupon/coupon/member/list 请求对应的方法。
六、使用Nacos作为配置中心
配置中心的意思是不在application.properties等文件中配置了,而是放到nacos配置中心公用,这样无需每台机器都改
官方教程
6.1 common模块引入nacos-config依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
6.2 在服务模块新建bootstrap.yaml配置 Nacos Config 元数据
还是原来我们使用配置的方式,只不过优先级变了,所以匹配到了nacos的配置
在coupons项目中创建/src/main/resources/bootstrap.properties ,这个文件是springboot里规定的,他优先级别application.properties高
spring:
application:
name: gulimall-coupon
cloud:
nacos:
config:
server-addr: 192.168.33.10:8848
file-extension: yaml
6.3 测试读取配置中心配置
给配置中心新增一个配置
新建接口读取配置
CouponController.java
@RefreshScope // 动态刷新,修改配置中心配置不需要重新启动项目
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
@Autowired
private CouponService couponService;
@Value("${coupon.user.name}")
private String name;
@Value("${coupon.user.age}")
private Integer age;
@RequestMapping("/test")
public R test() {
return R.ok().put("name", name).put("age", age);
}
}
输入网址测试
http://localhost:7000/coupon/coupon/test
6.4 Nacos 命名空间
为了对不同服务之间进行配置隔离,这里为每个微服务创建自己的命名空间
后端代码中在bootstrap.yaml 配置属于自己服务的命名空间
spring:
application:
name: gulimall-coupon
cloud:
nacos:
config:
server-addr: 192.168.33.10:8848
file-extension: yaml
namespace: 49fe9f91-89d4-411b-a123-5ce6576a518d
每个微服务创建自己的命名空间,然后使用配置分组区分环境(dev/test/prod)
七、使用Gateway作为API网关
7.1 网关的作用
一、动态上下线:发送请求需要知道商品服务的地址,如果商品服务器有123服务器,1号掉线后,还得改,所以需要网关动态地管理,他能从注册中心中实时地感知某个服务上线还是下线。【先通过网关,网关路由到服务提供者】
二、拦截:请求也要加上询问权限,看用户有没有权限访问这个请求,也需要网关。
三、网关是请求流量的入口,常用功能包括路由转发,权限校验,限流控制等。springcloud gateway取代了zuul网关。
7.2 三大核心概念
三大核心概念:
Route:发一个请求给网关,网关要将请求路由到指定的服务。路由有id,目的地uri,断言的集合,匹配了断言就能到达指定位置,
Predicate断言:就是java里的断言函数,匹配请求里的任何信息,包括请求头等。根据请求头路由哪个服务
Filter:过滤器请求和响应都可以被修改。
客户端发请求给服务端。中间有网关。先交给映射器,如果能处理就交给handler处理,然后交给一系列filer,然后给指定的服务,再返回回来给客户端。
7.3 创建网关子模块gulimall-gateway
创建
创建微服务,使用initilizer,Group:com.jyyy.gulimall,Artifact: gulimall-gateway,package:com.jyyy.gulimall.gateway。 搜索gateway选中。
gateway下的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jyyy.gulimall</groupId>
<artifactId>gulimall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>gulimall-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gulimall-gateway</name>
<description>API网关</description>
<dependencies>
<dependency>
<groupId>com.jyyy.gulimall</groupId>
<artifactId>gulimall-common</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
gateway主启动类
// 不需要数据库连接,排除掉
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableDiscoveryClient
public class GulimallGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallGatewayApplication.class, args);
}
}
配置gateway的nacos
spring:
application:
name: gulimall-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.33.10:8848
server:
port: 88
配置gateway配置中心
创建一个独立的命名空间
bootstrap.yaml
spring:
application:
name: gulimall-gateway
cloud:
nacos:
config:
server-addr: 192.168.33.10:8848
file-extension: yaml
namespace: 4d367997-3020-4a31-a03d-635df6c5b4cb
7.4 测试
配置gateway路由规则
spring:
application:
name: gulimall-gateway
cloud:
nacos:
config:
server-addr: 192.168.33.10:8848
file-extension: yaml
namespace: 4d367997-3020-4a31-a03d-635df6c5b4cb
gateway:
routes:
#Query A 参数有A就行,Query B,C 参数B的值为C即可
#实现针对于“http://localhost:88/hello?url=baidu”,转发到“https://www.baidu.com/hello”,
#针对于“http://localhost:88/hello?url=qq”的请求,转发到“https://www.qq.com/hello”
- id: baidu_route
uri: https://www.baidu.com
predicates:
- Query=url,baidu
- id: github_route
uri: https://www.github.com
predicates:
- Query=url,github
启动项目,分别请求baidu,github
http://localhost:88/s?wd=Ep%E6%B5%81%E8%8B%8F&url=baidu
https://github.com/zsy0216?url=github