微服务-注册中心、配置中心、网关
组件选择
参考:官方
注册中心: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 Server
下载地址:Github Release 由上面版本选择可知:当前对应 Nacos 版本为1.2.1
下载对应系统的tar包(Linux)或者zip包(Windows),解压后运行bin目录下的可执行文件即可运行Nacos
引入Nacos作为注册中心
1. pom文件引入依赖
common模块 ```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">
<artifactId>mall</artifactId><groupId>groupId</groupId><version>1.0-SNAPSHOT</version>
4.0.0 mall-common 每一个微服务公共的依赖,bean,工具类等 <!-- 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>javax.validation</groupId><artifactId>validation-api</artifactId><version>2.0.1.Final</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.32</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test</artifactId><version>2.1.8.RELEASE</version><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.8.0-M1</version><scope>test</scope></dependency><!-- 配置中心来做配置管理--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency></dependencies><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>
- coupon模块```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>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.ht.mall</groupId><artifactId>gulimall-coupon</artifactId><version>0.0.1-SNAPSHOT</version><name>mall-coupon</name><description>商城-优惠卷服务</description><properties><java.version>1.8</java.version><spring-cloud.version>Greenwich.SR3</spring-cloud.version></properties><dependencies><dependency><groupId>groupId</groupId><artifactId>mall-common</artifactId><version>1.0-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></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.8.0-M1</version><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>
2. yaml文件增加配置
在 coupon 中的application.yml 配置文件中配置 Nacos Server 地址和微服务名称
spring:application:name: mall-coupondatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.1.103:3306/mall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: rootcloud:nacos:discovery:server-addr: localhost:8848mybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: autoserver:port: 7000
3. 主启动类增加注解
使用 @EnableDiscoveryClient 注解开启服务注册与发现功能
@MapperScan("com.ht.mall.product.dao")@SpringBootApplication@EnableDiscoveryClientpublic class MallCouponApplication {public static void main(String[] args) {SpringApplication.run(MallCouponApplication.class, args);}}
此时,启动Nacos,运行主启动类启动服务后,在浏览器打开配置文件中的地址:localhost:8848/nacos (账号密码:nacos/nacos)中就可以看到当前服务已经注册到 Nacos 服务列表中
引入Feign远程服务调用
测试member和coupon的远程调用
想要获取当前会员领取到的所有优惠券。先去注册中心找优惠券服务, 注册中心调一台优惠券服务器给会员,会员服务器发送请求给这台优 惠券服务器,然后对方响应。
Feign与注册中心
spring cloud feign
声明式远程调用
feign是一个声明式的HTTP客户端,他的目的就是让远程调用更加简单。
给远程服务发的是HTTP请求。
会员服务想要远程调用优惠券服务,只需要给会员服务里引入openfeign依赖,他就有了远程调用其他服务的能力。
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
在coupon中修改如下的内容
@RequestMapping("coupon/coupon")public class CouponController {@Autowiredprivate CouponService couponService;@RequestMapping("/member/list")public R membercoupons(){ //全系统的所有返回都返回R// 应该去数据库查用户对于的优惠券,但这个我们简化了,不去数据库查了,构造了一个优惠券给他返回CouponEntity couponEntity = new CouponEntity();couponEntity.setCouponName("满100减10");//优惠券的名字return R.ok().put("coupons",Arrays.asList(couponEntity));}
这样我们准备好了优惠券的调用内容 在member的配置类上加注解@EnableFeignClients(basePackages=”com.ht.mall.member.feign”), 告诉spring这里面是一个远程调用客户端,member要调用的接口
@SpringBootApplication@EnableDiscoveryClient@EnableFeignClients(basePackages="com.ht.mall.member.feign")public class MallMemberApplication {public static void main(String[] args) {SpringApplication.run(MallMemberApplication .class, args);}}
调用刚才写的优惠券的功能
复制函数部分,在member的com.ht.mall.member.feign包下新建接口:
/*** 告诉spring cloud这个接口是一个远程客户端*/@FeignClient("mall-coupon")public interface CouponFeignService {/*** 调用coupon服务,再去调用coupon服务/coupon/coupon/member/list对应的方法* @return 得到一个R对象*/@RequestMapping("/coupon/coupon/member/list")public R memberCoupons();}
然后我们在member的控制层写一个测试请求
@RestController@RequestMapping("member/member")public class MemberController {@Autowiredprivate MemberService memberService;@AutowiredCouponFeignService 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
{"msg":"success","code":0,"coupons":[{"id":null,"couponType":null,"couponImg":null,"couponName":"满100减10","num":null,"amount":null,"perLimit":null,"minPoint":null,"startTime":null,"endTime":null,"useType":null,"note":null,"publishCount":null,"useCount":null,"receiveCount":null,"enableStartTime":null,"enableEndTime":null,"code":null,"memberLevel":null,"publish":null}],"member":{"id":null,"levelId":null,"username":null,"password":null,"nickname":"张三","mobile":null,"email":null,"header":null,"gender":null,"birth":null,"city":null,"job":null,"sign":null,"sourceType":null,"integration":null,"growth":null,"status":null,"createTime":null}}
引入Nacos作为配置中心
参考:官方介绍
1. common模块引入nacos-config依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency>
2. 配置 Nacos Config 元数据
在服务模块新建bootstrap.properties
此处以coupon服务为例:
spring.application.name=mall-couponspring.cloud.nacos.config.server-addr=localhost:8848
3. 测试读取配置中心配置
给配置中心新增一个配置
读取配置
application.properties
coupon.user.name=zhangsan2coupon.user.age=20
CouponController.java
@RefreseScope:动态刷新,修改配置中心配置不需要重新启动项目
@RefreshScope@RestController@RequestMapping("coupon/coupon")public class CouponController {@Autowiredprivate 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);}}
请求 /coupon/coupon/test 可以看到配置中心的数据,修改配置中心的配置,刷新可自动更新,nacos的配置内容优先于项目本地的配置内容。
4. Nacos 命名空间
为了对不同服务之间进行配置隔离,这里为每个微服务创建自己的命名空间。
后端代码中在 bootstrap.properties 配置属于自己服务的命名空间
spring.application.name=mall-couponspring.cloud.nacos.config.server-addr=localhost:8848spring.cloud.nacos.config.namespace=eed1d158-6019-487f-b38a-cf79430eba44
5. 加载多配置集
- 配置集:一组相关或不相关配置项的集合。
- 配置集ID:类似于配置文件名,即Data ID
- 配置分组:默认所有的配置集都属于DEFAULT_GROUP。自己可以创建分组,比如双十一,618,双十二
spring.cloud.nacos.config.group=DEFAULT_GROUP # 更改配置分组
最终方案:每个微服务创建自己的命名空间,然后使用配置分组区分环境(dev/test/prod)
把原来application.yml里的内容都分文件抽离出去,在nacos里创建好后,指定coupons要导入的配置即可。
datasource.yml
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.1.103:3306/mall_sms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: root
mybatis.yml
mybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: auto
other.yml ```yaml spring: application: name: mall-coupon cloud: nacos:
discovery:server-addr: localhost:8848
server: port: 7000
注释application.yml的内容<br />修改coupon里的bootstrap.properties```yaml# 改名字,对应nacos里的配置文件名spring.application.name=mall-couponspring.cloud.nacos.config.server-addr=localhost:8848# 可以选择对应的命名空间 ,即写上对应环境的命名空间IDspring.cloud.nacos.config.namespace=eed1d158-6019-487f-b38a-cf79430eba44# 配置文件所在的组spring.cloud.nacos.config.group=dev# 加载多配置集spring.cloud.nacos.config.ext-config[0].data-id=datasource.ymlspring.cloud.nacos.config.ext-config[0].group=devspring.cloud.nacos.config.ext-config[0].refresh=truespring.cloud.nacos.config.ext-config[1].data-id=mybatis.ymlspring.cloud.nacos.config.ext-config[1].group=devspring.cloud.nacos.config.ext-config[1].refresh=truespring.cloud.nacos.config.ext-config[2].data-id=other.ymlspring.cloud.nacos.config.ext-config[2].group=devspring.cloud.nacos.config.ext-config[2].refresh=true
引入Gateway作为API网关
参考:官网
创建网关子模块mall-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>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.ht.mall</groupId><artifactId>mall-gateway</artifactId><version>0.0.1-SNAPSHOT</version><name>mall-gateway</name><description>API网关</description><properties><java.version>1.8</java.version><spring-cloud.version>Greenwich.SR3</spring-cloud.version></properties><dependencies><dependency><groupId>groupId</groupId><artifactId>mall-common</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><version>2.1.0.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
主启动类
@EnableDiscoveryClient@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})public class MallGatewayApplication {public static void main(String[] args) {SpringApplication.run(MallGatewayApplication.class, args);}}
配置nacos注册中心地址applicaion.properties
spring.application.name=mall-gatewayspring.cloud.nacos.discovery.server-addr=localhost:8848server.port=88
bootstrap.properties 填写配置中心地址
spring.application.name=mall-gatewayspring.cloud.nacos.config.server-addr=localhost:8848spring.cloud.nacos.config.namespace=cfc9231c-e4d3-4f2e-ad7a-c12faffbf7dc
在gateway命名空间里创建文件mall-gateway.yml
spring:application:name: mall-gateway
在项目里创建application.yml
spring:cloud: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_routeuri: http://www.baidu.compredicates:- Query=url,baidu- id: test_routeuri: http://www.qq.compredicates:- Query=url,qq
测试:
启动项目分别请求:
localhost:88?url=baidu
localhost:88?url=qq
会分别跳转到百度和github 表示成功。
