03-微服务搭建
1、搭建分布式基本环境
分布式组件 | 功能 |
SpringCloud Alibaba - Nacos | 注册中心(服务发现/注册)、配置中心(动态配置管理) |
SpringCloud Alibaba - Sentinel | 服务容错(限流、降级、熔断) |
SpringCloud Alibaba - Seata | 原 Fescar,即分布式事务解决方案 |
SpringCloud - Ribbon | 负载均衡 |
SpringCloud - Feign | 声明式 HTTP 客户端(调用远程服务) |
SpringCloud - Sleuth | 调用链监控 |
SpringCloud - Gateway | API 网关(webflux 编程模式) |
引入微服务依赖
在 common 模块中引入 springcloud-alibaba 版本依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Nacos 注册中心
① 首先,修改common模块的 pom.xml 文件,引入 Nacos Discovery Starter。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
② 下载启动 nacos:Releases · alibaba/nacos · GitHub,双击 nacos\bin\startup.cmd
③ 每个微服务应用的 /src/main/resources/application.properties 配置文件中配置 Nacos Server 地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
④ 每个服务的启动类上添加 @EnableDiscoveryClient 注解开启服务注册与发现功能
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
@RestController
class EchoController {
@GetMapping(value = "/echo/{string}")
public String echo(@PathVariable String string) {
return string;
}
}
}
⑤ 配置每个服务名称
spring.application.name=gulimall-coupon
⑥ 启动服务,在 nacos 中查看是否注册成功
OpenFeign 远程调用
① 每个服务引入 openfeign 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
② 声明远程调用服务接口:在 member 服务中定义此接口(member 服务调用 coupon 服务),将所有的远程调用接口都放在 feign 包里面。
@FeignClient("gulimail-coupon")
public interface CouponFeignService {
@RequestMapping("coupon/coupon/member/list")
public R memberCoupons();
}
③ 调用方服务(member)开启远程调用注解:@EnableFeignClients
@EnableFeignClients(basePackages = "com.atguigu.gulimail.member.feign")
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallMemberApplication {
public static void main(String[] args) {
SpringApplication.run(GulimailMemberApplication.class, args);
}
}
④ member 服务远程调用 coupon 服务
@Autowired
CouponFeignService couponFeignService;
@RequestMapping("/coupons")
public R test() {
// 定义一个会员
MemberEntity memberEntity = new MemberEntity();
memberEntity.setNickname("龙傲天");
// 远程调用copuon服务获取此会员的优惠卷
R memberCoupons = couponFeignService.memberCoupons();
return R.ok().put("member", memberEntity).put("coupons", memberCoupons.get("coupons"));
}
⑤ coupon 服务获取优惠卷列表
/*
* 返回当前会员的所有优惠卷
* */
@RequestMapping("/member/list")
public R memeberCoupons() {
CouponEntity couponEntity = new CouponEntity();
couponEntity.setCouponName("满100减50...");
return R.ok().put("coupons", Arrays.asList(couponEntity));
}
⑥ 访问接口 http://localhost:8000/member/member/coupons 测试远程调用
注意:可以访问成功的前提是,服务提前注册到了nacos中
Nacos 配置中心
原始读取配置方式
如下是没有使用Nacos作为配置中心之前,读取配置文件的方式:
① 第一步:在配置文件中定义变量信息
coupon.user.name=AotianLong
coupon.user.age=18
② 第二步:将配置文件中的配置读取到类的变量中
@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);
}
引入配置中心
需求:原始读取配置方式,程序打包部署后不能动态更改信息,此时就需要引入配置中心了
① 在common模块引入 nacos 配置依赖和bootstrap依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.1.2</version>
</dependency>
② 在每个服务应用中创建 /src/main/resources/bootstrap.properties 配置文件
# 微服务名称
spring.application.name=gulimall-coupon
# 配置中心 Nacos 地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
③ 在nacos控制台创建项目的配置如文件,编写配置信息:如,gulimall-coupon.properties
④ 在需要读取配置中心数据的类上添加@RefreshScope
注解,在变量上添加 @Value
注解
// 动态刷新
@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);
}
}
注意:如果配置中心 和 微服务项目里面的配置文件同时存在相同的配置信息,那么会优先读取配置中心中的信息。
配置中心概念
① 命名空间:
利用命名空间做环境隔离(默认空间是 public):开发、测试、生产。
在bootstrap.properties配置文件中指定命名空间。
spring.cloud.nacos.config.namespace=e0ed0744-32c5-4f41-8ace-09b1391fc4a1
基于微服务进行隔离:给每个服务创建自己的命名空间,服务在启动的时候只需要加载自己命名空间下的配置文件。
② 配置集:所有配置的集合;配置集ID:Data ID 类似文件名
③ 配置分组:默认所有的配置集都属于 DEFAULT_GROUP,可以配置配置分组
# 在bootstrap.properties 配置文件中指定配置分组。
spring.cloud.nacos.config.group=dev
每个微服务创建自己的命名空间,使用配置分组区分环境(开发、测试、生产…)
拆分配置
需求:同时加载多个配置集,不同组件的配置不会写在同一个配置文件中如:数据源、框架、微服务
① 配置文件按功能拆分:如spring拆分成一个,mybatis拆分成一个、其他配置再拆分成一个
② 在bootstrap.properties 配置文件中加载配置信息
spring.cloud.nacos.config.namespace=42917e19-6cbd-4478-89a1-3e36d5d16df5
spring.cloud.nacos.config.group=dev
spring.cloud.nacos.config.ext-config[0].data-id=datasource.yaml
spring.cloud.nacos.config.ext-config[0].group=dev
spring.cloud.nacos.config.ext-config[0].refresh=true
spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yaml
spring.cloud.nacos.config.ext-config[1].group=dev
spring.cloud.nacos.config.ext-config[1].refresh=true
spring.cloud.nacos.config.ext-config[2].data-id=others.yaml
spring.cloud.nacos.config.ext-config[2].group=dev
spring.cloud.nacos.config.ext-config[2].refresh=true
Gateway 网关
网关作为流量的入口,常用功能包括路由转发、权限校验、限流控制等。
网关提供 API 全托管服务,丰富的 API 管理功能,辅助企业管理大规模的 API,以降低管理成本和安全风险,包括协议适配、协议转发、安全策略、防刷、流量、监控日志等功能。
核心概念 | 解释 |
路由 | 路由是网关最基础的部分,路由信息有一个 ID、一个目的 URL、一组断言和一组 Filter 组成。如果断言路由为真,则说明请求的 URL 和配置匹配 |
断言 | Java8 中的断言函数。Spring Cloud Gateway 中的断言函数输入类型是 Spring5.0 框架中的 ServerWebExchange。Spring Cloud Gateway 中的断言函数允许开发者去定义匹配来自于 http request 中的任何信息,比如请求头和参数等。 |
过滤器 | 一个标准的 Spring webFilter。Spring cloud gateway 中的 filter 分为两种类型的Filter,分别是 Gateway Filter 和 Global Filter。过滤器 Filter 将会对请求和响应进行修改处理。 |
① 创建 gateway 服务,引入gulimail-common依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.atguigu.gulimall</groupId>
<artifactId>gulimall-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gulimall-gateway</name>
<description>网关服务</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway-mvc</artifactId>
</dependency>
<!-- 引入common依赖(注册中心、配置中心)-->
<dependency>
<groupId>com.atguigu.gulimall</groupId>
<artifactId>gulimall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
② 开启服务注册发现:@EnableDiscoveryClient
,并排除数据源的配置
@EnableDiscoveryClient
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class GulimallGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallGatewayApplication.class, args);
}
}
③ 配置 Nacos 服务地址、服务名和端口:application.properties
spring.application.name=gulimall-gateway
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
server.port=88
④ 配置Naocs配置中心地址、并指定命名空间:bootstrap.properties
spring.cloud.nacos.config.namespace=84f86833-fca4-4ee9-9ffd-fbb65ccaebfb
⑤ 测试网关服务:在application.yaml 文件中编写路由规则后启动服务
spring:
cloud:
gateway:
routes:
- id: qq_route
uri: https://www.qq.com
predicates:
- Query=url,qq