【谷粒商城】(二)SpringCloudAlibaba分布式组件
微服务 分布式组件
注册中心
:每一个微服务上线都应该注册到注册中心。这样做的好处在于方便微服务之间的相互调用,比如订单服务想要调用商品服务,就可以通过注册中心查看有哪几台主机的商品服务进行了注册,然后进行挑选。
配置中心
:比如商品服务在10台机器上,一旦修改配置则需要每个进行修改十分麻烦,这时候可以通过配置中心对微服务进行集中配置。
网关
:为请求达到注册、配置中心做一些预先工作。
1 Nacos注册中心
- 导入nacos依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos.discovery</artifactId> </dependency>
关于springcloud、springboot、springcloudalibaba的版本选择建议直接开局alibaba java initializr,否则很容易半夜砸电脑(
我是将
2.2.2.RELEASE
版本的springcloudalibaba写到了common中,将2.3.7.RELEASE
版本的spring-boot和Hoxton.SR9
版本的spring-cloud写入到每个微服务中的pom文件了。详情如下:
member 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> <groupId>com.hikaru.grainmall</groupId> <artifactId>grainmall-member</artifactId> <version>0.0.1-SNAPSHOT</version> <name>grainmall-member</name> <description>谷粒商城-会员服务</description> <parent> <groupId>com.hikaru.grainmall</groupId> <artifactId>grainmall</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.3.7.RELEASE</spring-boot.version> <spring-cloud.version>Hoxton.SR9</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>com.hikaru.grainmall</groupId> <artifactId>grainmall-common</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <dependencyManagement> <dependencies> <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>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.7.RELEASE</version> <configuration> <mainClass>com.hikaru.grainmall.member.GrainmallMemberApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
common 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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>grainmall</artifactId> <groupId>com.hikaru.grainmall</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>grainmall-common</artifactId> <description>每一个微服务公共的依赖,bean,工具类等</description> <properties> <spring-cloud-alibaba.version>2.2.2.RELEASE</spring-cloud-alibaba.version> </properties> <dependencies> <!-- mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.8</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.12</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <!-- 导入mysql驱动 --> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.17</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <!-- 服务注册/发现--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- 配置中心来做配置管理--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> </project>
-
启动nacos后在微服务应用的/src/main/resource/application.properties配置文件中配置NacosServer地址。
启动nacos要以单机模式启动:
startup.cmd -m standalone
application.yml
spring: datasource: username: root password: root url: jdbc:mysql://192.168.60.3:3306/grainmall_ums driver-class-name: com.mysql.cj.jdbc.Driver cloud: nacos: discovery: server-addr: 127.0.0.1:8848 application: name: grainmall-member mybatis-plus: mapper-locations: classpath:/mapper/**/*.xml global-config: db-config: id-type: auto -
使用@EnableDiscoveryClient注解开启服务注册与发现功能
@EnableDiscoveryClient @SpringBootApplication public class GrainmallCouponApplication { public static void main(String[] args) { SpringApplication.run(GrainmallCouponApplication.class, args); } }
然后就可以在nacos的控制台看到注册了的服务了:
2 Nacos配置中心
使用场景
:当项目上线后需要更改配置时,每次修改代码再重新运行显然是不现实的(哪怕是热部署),可以通过配置中心针对每一个微服务组件发布配置来实现热修复。
-
导入依赖 spring-cloud-starter-alibaba-nacos-config
<!-- 配置中心来做配置管理--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> 我这里是将依赖引入了common组件的pom.xml,然后使用的dependencyManagement进行的版本管理
-
创建
bootstrap.properties
设置配置中心的配置# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html # Nacos认证信息 spring.application.name=graninmall-coupon spring.cloud.nacos.config.username=nacos spring.cloud.nacos.config.password=nacos spring.cloud.nacos.config.contextPath=/nacos # 设置配置中心服务端地址 spring.cloud.nacos.config.server-addr=127.0.0.1:8848 # Nacos 配置中心的namespace。需要注意,如果使用 public 的 namcespace ,请不要填写这个值,直接留空即可 spring.cloud.nacos.config.namespace= ① 配置中心的配置必须使用bootstrap.properties,这个文件会比其他配置文件的优先级高
② 最新版本的Navos只需配置服务端地址spring.cloud.nacos.config就能实现对配置和注册中心的配置
-
测试实例,使用@Value注解获取配置的值
@RefreshScope @RestController @RequestMapping("coupon/coupon") public class CouponController { @Autowired private CouponService couponService; @Value("${member.username}") private String username; @Value("${member.password}") private String password; @RequestMapping("/test") public R test() { return R.ok().put("username", this.username).put("password", this.password); } -
在Nacos控制台发布配置
Data id为配置的服务组件名+properties
3 Nacos命名空间及配置分组
命名空间
:用于做微服务组件配置隔离的。默认是public(保留空间)。可以增加如开发、测试、生产的命名空间,用于隔离不同场景的配置。但是一般情况下为每一个微服务创建一个命名空间,使用分组区别开发生成等环境。
分组
:默认为DEFAULT_GROUP默认分组,作用是在同一个微服务命名空间下的多种配置情况,每个配置的Data Id相同但是分组不同,可以在指定命名空间的同时指定分组,一般用于区别开发生成等环境。
spring.cloud.nacos.config.namespace=ca192043-c316-4bed-b44c-6436867be25e spring.cloud.nacos.config.group=test
新版的命名空间也可以直接写应用名了
5 配置中心同时加载多个配置集
微服务的任何配置信息都可以放在配置文件中,只需要在bootstrap.properties中说明加载配置中心的那些配置文件即可。
首先将datasource.yml、mybatis.yml、other.yml发布到配置中心,然后在bootstrap.properties
文件中配置:
# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html # Nacos认证信息 spring.application.name=grainmall-coupon spring.cloud.nacos.config.username=nacos spring.cloud.nacos.config.password=nacos spring.cloud.nacos.config.contextPath=/nacos # 设置配置中心服务端地址 spring.cloud.nacos.config.server-addr=127.0.0.1:8848 # Nacos 配置中心的namespace。需要注意,如果使用 public 的 namcespace ,请不要填写这个值,直接留空即可 spring.cloud.nacos.config.namespace=ca192043-c316-4bed-b44c-6436867be25e 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
这样会默认读取 应用名.properties(应用名一定不要写错。。)
扩展读取 datasource.yml、mybatis.yml、other.yml
如果配置中心有配置则优先使用配置中心的,没有则使用本地配置
4 OpenFeign远程调用
Feign声明式远程调用:feign是一个声明式的http客户端,它的目的是让远程调用更加简单。Feign提供了Http请求的模板,通过编写简单的接口和插入注解,就可以定义好Http请求的参数、格式、地址等信息。
Feign整合了负载均衡(Ribbon)
和服务熔断(Hystrix)
,可以让我们不再需要显式地使用这两个组件。
SpringCLoudFeign在NetfixFeign的基础上扩展了对SpringMVC注解的支持,在其实现下,我们只需要创建一个接口并用注解的方式实现它,既可以完成对服务提供方的接口绑定。简化了SpringcloudRibbon自行封装服务调用客户端的开发量。
比如上面的会员服务想要调用优惠券服务,只需要在会员微服务组件中引入OpenFeign依赖。
-
导入Feign依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> -
使用@EnableFeignClients注解启用远程服务调用
@EnableFeignClients @EnableDiscoveryClient @SpringBootApplication public class GrainmallMemberApplication { public static void main(String[] args) { SpringApplication.run(GrainmallMemberApplication.class, args); } } -
编写远程服务调用接口,并使用@FeignClient("grainmall-coupon")注解表明调用的远程服务
@FeignClient("grainmall-coupon") public interface CouponFeignService { @RequestMapping("/coupon/coupon/member/list") public R memberCoupons(); } 接口函数即为被远程调用的函数:
@RequestMapping("/member/list") public R memberCoupons() { CouponEntity couponEntity = new CouponEntity(); couponEntity.setCouponName("满100减10"); return R.ok().put("coupons", Arrays.asList(couponEntity)); } -
测试远程调用
@Autowired private CouponFeignService couponFeignService; @RequestMapping("/coupons") public R coupons() { MemberEntity memberEntity = new MemberEntity(); memberEntity.setNickname("张三"); R memberCoupons = couponFeignService.memberCoupons(); return R.ok().put("member", memberEntity).put("coupon", memberCoupons.get("coupons")); }
5 SpringCloud Gateway 网关设置
使用场景
:当我们前端访问微服务的一个主机宕机了,需要改成另一台该微服务的主机,每次手动更改是不现实的,这个时候就可以借助网关,网关可以从配置、注册中心感知微服务。
先由客户端去请求网关,然后网关代转给其它服务,在网关层将这些请求做统一的处理。网关就作为了流量的入口,常用功能包括路由转发、权限校验、限流控制等。而SpringCloud Gateway作为第二代网关框架,取代了Zuul网关。(SpringCloud GateWay每秒处理请求能够达到三万)
网关的组成
:
-
路由(Route)
:请求发送到网关,然后根据路由发送至指定位置。首先包括一个标示性的id
区分不同路由,然后包含一个uri
表明路由的地址,一个断言的集合
,和一个过滤器的集合
。 -
断言(Predicate)
:只有集合中的断言全部为真,路由才能将请求发送到指定uri。 -
过滤器(Filter)
:过滤请求,在请求发出后和响应结束前都可以对请求、响应进行修改。
整体来说,就是请求达到网关后会先进行路由断言判断,集合中的断言全部为真则再经过一层层过滤器后抵达路由uri。
SpringCloud GateWay创建网关
① 导入依赖(或者直接aliInitialze,推荐)
<?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> <groupId>com.hikaru</groupId> <artifactId>grainmall-gateway</artifactId> <version>0.0.1-SNAPSHOT</version> <name>grainmall-gateway</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.3.7.RELEASE</spring-boot.version> <spring-cloud.version>Hoxton.SR9</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.hikaru.grainmall</groupId> <artifactId>grainmall-common</artifactId> <version>0.0.1-SNAPSHOT</version> <exclusions> <exclusion> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <dependencyManagement> <dependencies> <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>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.7.RELEASE</version> <configuration> <mainClass>com.hikaru.gateway.GrainmallGatewayApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
注意不要导入common的mybatis-plus依赖,这里我在xml文件进行的修改,也可以在springboot启动器@SpringBootApplication中设置不注册mybatis-plus的AutoConfig
② 配置bootstrap.properties配置nacos配置中心
spring.application.name=grainmall-gateway spring.cloud.nacos.config.server-addr=127.0.0.1:8848 spring.cloud.nacos.config.namespace=2a289849-d4a4-45cf-83f1-a9fb4ede9b6b spring.cloud.nacos.config.extension-configs[0].data-id=grainmall-gateway.yml spring.cloud.nacos.config.extension-configs[0].refresh=true
这里是先连接的配置中心,所以需要设置:
1 应用名:用于读取默认的 应用名 + properties 配置
2 nacos配置中心的地址
3 命名空间的uuid
4 额外的配置文件:grainmall-gateway.yml
③ 在配置中心中配置grainmall-gateway.yml
spring: cloud: nacos: discovery: namespace: 2a289849-d4a4-45cf-83f1-a9fb4ede9b6b application: name: grainmall-gateway server: port: 88
然后配置文件设置的是注册中心的配置,包括
1 注册带哪个配置中心
2 注册的应用名
3 访问该服务的端口号
③ 配置网关
spring: cloud: gateway: routes: - id: qq uri: https://www.qq.com predicates: - Query= uri, qq - id: baidu uri: https://www.baidu.com predicates: - Query= uri, baidu
- Query= url, qq表示参数的断言,即参数为url的时候触发该路由
且第二个值可以写成正则表达式
③ 启动网关和nacos,访问 \http://localhost:88/hello?uri=qq
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步