技术选择
注册中心: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
版本选择
组件版本关系
毕业版本依赖关系(推荐)
下载Nacos
下载地址 由上面版本选择可知:这里应该使用 Nacos 的版本为1.2.1
我使用的docker拉取镜像
docker pull nacos/nacos-server:1.2.1
docker启动nacos容器
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中引入版本依赖
根据上面版本选择可知:
SpringCloud 版本: Hoxton.SR3
SpringCloud alibaba 版本: 2.2.1.RELEASE
SpringBoot 版本: 2.2.5.RELEASE
<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作为注册中心
nacos官方文档 以优惠模块为例,只需要4个步骤
- 改pom
- 写yml
- 主启动
- 业务类
在common模块引入nacos作为注册中心的依赖
<!-- nacos作为服务注册中心
这里千万别写成了nacos-config,这是nacos作为配置中心的依赖
-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
修改yml
spring:
cloud:
nacos:
# 别写成config了
discovery:
server-addr: 127.0.0.1:8848
application:
# name必须要有,作为在注册中心注册的模块名称
name: gulimall-coupon
在主启动类添加注解
添加注解@EnableDiscoveryClient
@SpringBootApplication
@MapperScan("com.pumpkin.gulimall.coupon.dao")
@EnableDiscoveryClient
public class GulimallCouponApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallCouponApplication.class, args);
}
}
完成上面的所有操作后,启动Nacos,运行主启动类启动服务后,在浏览器打开配置文件中的地址:127.0.0.1:8848/nacos (默认账号/密码:nacos/nacos)中就可以看到当前服务已经注册到 Nacos 服务列表中。
踩坑
引入了nacos作为配置中心的依赖,而没有在yml配置文件中配置其对应的信息,启动服务会报错
com.alibaba.nacos.api.exception.NacosException: java.lang.reflect.InvocationTargetException
引入OpenFeign远程调用服务
以会员模块,优惠券模块为例。
引入OpenFeign依赖(改pom)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
引入openfeign不需要修改yml文件
主启动
在主启动类上添加注解@EnableFeignClients(basePackages = "feign接口所在包目录")
@SpringBootApplication
@MapperScan("com.pumpkin.gulimall.member.dao")
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.pumpkin.gulimall.member.feign")
public class GulimallMemberApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallMemberApplication.class, args);
}
}
业务类
以会员模块调用优惠模块为例
优惠模块中等待被调用的接口
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
@GetMapping("/member/getCoupon")
public R getAllCoupon(){
CouponEntity entity = new CouponEntity();
entity.setCouponName("满100减10");
return R.ok().put("coupon" , entity) ;
}
}
在会员模块新建com.pumpkin.gulimall.member.feign
包用来存放所有feign接口
/**
* @author pumpkin
* @date 2022/1/24 0024 下午 17:46
*/
@FeignClient("gulimall-coupon") //要调用的服务在注册中心的名称
@Component
public interface CoupoinFeignService {
@GetMapping("/coupon/coupon/member/getCoupon")
public R getAllCoupon() ;
}
在会员模块的controller层调用
@RestController
@RequestMapping("member/member")
@RefreshScope //动态刷新
public class MemberController {
@Autowired
private CoupoinFeignService coupoinFeignService ;
@GetMapping("/getCoupon")
public R getCoupon(){
MemberEntity entity = new MemberEntity();
entity.setNickname("张三");
R coupon = coupoinFeignService.getAllCoupon();
return coupon.put("member" ,entity) ;
}
}
启动会员模块,优惠模块微服务,在地址栏输入localhost:8000/member/member/getCoupon
完成调用
解析:
- 当前请求member服务的
/member/member/getCoupon
请求; - 会调用
coupoinFeignService.getAllCoupon()
; - 此时会到服务注册中心找到
gulimall-coupon
服务; - 调用该服务的
/coupon/coupon/member/getCoupon
请求对应的方法。
引入Nacos作为配置中心
引入依赖(改pom)
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
写yml
创建bootstrap.yml
配置文件,该配置文件优先于application.yml
具体操作看官方文档
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
namespace: 这里写命名空间的uuid
group: 这里写分组名称
application:
name: gulimall-member
添加@RefreshScope
动态刷新
在controller上添加@RefreshScope
动态刷新注解,修改配置中心配置不需要重新启动项目
@RestController
@RequestMapping("member/member")
@RefreshScope //动态刷新
public class MemberController {
//调用配置中心的配置
@Value("${config.name}")
private String name ;
@Value("${config.girlfriend}")
private String girlfriend ;
@GetMapping("/getConfig")
public R getConfig(){
return R.ok().put("name" , name).put("girlfriend" , girlfriend) ;
}
}
引入geteway作为网关服务
具体操作看gateway官网 创建网关子模块
pom文件,在pom中引入common模块的依赖
改pom
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.pumpkin.gulimall</groupId>
<artifactId>gulimall-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gulimall-gateway</name>
<description>网关</description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>com.pumpkin.gulimall</groupId>
<artifactId>gulimall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<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>
</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>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
写yml
application.yml
server:
port: 88
spring:
application:
name: gulimall-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
# 网关路由
gateway:
routes:
- id: baidu_route
uri: https://www.yuque.com/pumpkin-ypb0o
//断言,如果请求带有参数qq,并且qq=zf,则路由到上面的uri
predicates:
- Query=qq,zf
bootstrap.yml
读取配置中心配置信息
spring:
application:
name: gulimall-gateway
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
namespace: c1cc4167-23ec-4184-be61-965d42ed69a3
group: dev