组件应用
一、服务注册中心Nacos
1. 前提
由于每个微服务项目都需要在服务中心中注册,随后进行统一的管理,所以直接把Nacos引入到所有微服务的共用模块common模块中去
2. 配置
-
修改common中的pom.xml文件,引入Nacos Discovery Stater
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
-
在需要使用的微服务中的application.yml中配置Nacos Server地址和服务名称
spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848 application: name: gulimall-xxx
-
在需要注册到注册中的微服务的主类上标注注解@EnableDiscoveryClient
-
访问http://127.0.0.1:8848/nacos/ 账号密码都为nacos
二、配置中心Nacos
1. 前提
由于每个微服务项目的配置文件都需要由配置中心进行统一管理,在配置中心中进行创建、修改、发布,所以直接把Nacos引入到所有微服务的共用模块common模块中去
2. 配置
2.1 基本配置
- 引入配置中心依赖,放在common中
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
- 在需要配置管理的微服务的类路径下创建
bootstrap.properties
配置文件,这个文件是在SpringBoot
规定的,优先级高于application.yml
- 在
bootstrap.properties
中定义本微服务的名字并将本服务注册到配置中心中(注意,此时本来在application.yml
文件中的配置,可以转移到配置中心中进行配置了)spring.application.name=gulimall-xxx spring.cloud.nacos.config.server-addr=192.168.11.1:8848
- 在配置中心中创建一个
data ID
与本服务名同名的properties
或yml
文件,通过修改该配置文件即可管理本微服务的配置 - 此时如果对配置中心中的配置文件修改,还需要重启nacos,在相应的Controller中加上@RefreshScope注解,即可不重启服务就能进行修改
2.2 配置中心进阶
**前提:**由于不仅不同的微服务都有自己的配置文件,甚至同一个的微服务在不同的生产环境下也会有不同的配置要求,所以,如果把所有的配置文件都放在一起,那管理起来是十分混乱的,因此,我们不光需要用配置中心来管理配置文件,更要把不同的微服务的配置文件、同一个微服务不同生产环境下的配置文件分别进行管理。
2.2.1 命名空间
-
用于配置隔离
-
默认新增的配置文件都在public空间下,
-
我们可以自定义命名空间,并在自定义的命名空间下创建配置文件
-
可以在
bootstrap.properties
文件中按照如下方式指定命名空间spring.cloud.nacos.config.namespace=命名空间的id
-
我们可以基于环境进行隔离,也可以基于微服务进行隔离,本项目中我们要求每个微服务一个命名空间即基于微服务进行隔离
2.2.2 配置集
- 所有配置的集合,简单来说,就是每个配置文件中我们都要写很多的配置,一个配置文件中的所有配置加起来就叫一个配置集
2.2.3 配置集ID
- 类似配置文件名,就是上面所说的
data ID
2.2.4 配置分组
- 默认所有的配置集都属于
DEFAULT_GROUP
分组 - 我们可以在创建配置文件时人为的的选择配置分组(此时就自动的创建了一个我们选择的分组)
- 可以在
bootstrap.properties
文件中按照如下方式指定使用该命名空间下的哪个分组spring.cloud.nacos.config.group=分组名
- 本项目中我们要求微服务的每个生产环境都有一个分组
总结:namespace > group > 配置集(配置文件)
2.3 再次进阶:同时加载多个配置集(配置文件)
- 我们在配置中心中进行配置时,通常将不同的配置单独写在一个配置文件中,比如MyBatis的放在一个
mybatis.yml
中,Datasource的放在一个datasource.yml
中,所以这也就自然需要我们在一个微服务的一个环境下同时加载多个配置文件 - 方式:在指定了命名空间之后,定义一个数组,数组中的一个元素指明要加载配置文件、配置文件所处的环境、是否支持动态刷新
spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml spring.cloud.nacos.config.ext-config[0].group=dev spring.cloud.nacos.config.ext-config[0].refresh=true
三、网关gateway
1. 前提
本项目中,前端发送给所有微服务的请求都有统一的规范,比如本项目中都需要以http:localhost:88/api/
开头,如果不经过处理,这些请求无法被映射到指定的Controller的方法中,这就需要我们通过网关拦截所有请求,并进行动态的路由,将指定的请求路由到其相对应的微服务中,网关模块也是整个项目中的一个微服务。
2. 基础知识
2.1 基本概念
- 客户端发请求给服务端,请求会到达网关,网关先利用断言判定请求是否符合路由规则,如果符合,则会交给过滤器进行处理,处理后的请求就会被后端微服务匹配和处理,微服务处理后的响应又会经过网关再次进行处理,处理之后将响应返回到前端进行展示。
2.2 作用
- 路由:当客户端向服务端发送请求时,首先会发送到网关,网关将请求路由到指定的服务。路由模块中由路由的id、目的地的的uri(可加上负载均衡lb)、断言的集合、过滤器的集合组成。当匹配了断言集合,在经过过滤器集合的处理,请求就会被路由到其应该到达的位置。
- Predicate断言:Java8中所提供的一个断言函数,可以匹配请求里的任何的信息,比如请求路径,请求头,甚至发送请求的时间。
- Filter过滤:过滤器可以处理要请求到服务器的请求和要相应到客户端的响应。
3. 配置
-
由于网关也是一个微服务,所以依然需要定义好服务名称、端口号,并注册到nacos中进行统一的管理和配置,同时在主类标注注解
@EnableDiscoveryClient
spring.application.name=gulimall-gateway spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 server.port=88
-
在
application.yml
中配置路由规则spring: cloud: gateway: routes: - id: product_route uri: lb://gulimall-product predicates: - Path=/api/product/** filters: - RewritePath=/api/(?<segment>.*),/$\{segment}
四、远程调用OpenFeign
1. 前提
不同的微服务模块之间往往需要相互调用,比如当工作人员在前端增加商品的时候,会同时增加一些优惠信息,比如买三免一等等。这些需要优惠模块处理的信息发送给了商品模块,这就需要我们在商品模块中远程调用优惠模块进行处理
2. 配置
前提要求:调用和被调用的模块都要注册到nacos注册中心中,并在各自主类上标注@EnableDiscoveryClient
开启服务发现和注册功能
-
在调用和被调用模块中引入openFeign的启动器
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
-
主动调用的服务的主类上标注
@EnableFeignClients(basePackages = "主动调用服务的接口所在包")
(如果feign包在主类所在包下可以不用标注此注解就可以实现自动扫描,否则,必须要显式的声明) -
在主动调用的服务中创建接口(一般放在feign包下,好区分),在接口上用注解@FeignClient(“被调用的服务名”)声明被调用的服务
-
在接口中的方法中,用@RequestMapping(“被调用的服务的方法的url路径”)声明被调用的具体路径,接口中的方法不需要和被调用服务的url路径指向的方法名称一致,只要返回值一致,请求路径对应,且传输对象可以符合要求就可以(有时为了方便,我们直接把被调用服务的方法复制黏贴过来)
3. 细节解析(product模块调用coupon模块)
3.1 只要json数据模型是兼容的,双方服务无需使用同一个对象
- 当我们在product的feign的接口中的定义了
R saveSpuBounds(@RequestBody SpuBoundsTo spuBoundsTo);
方法 - SpringCloud利用@RequestBody注解将这个对象转为json
- 在注册中心中找到远程服务gulimall-coupon,给服务的/coupon/spubounds/save发送请求,将上一步转换出来的json放在请求体位置,发送请求
- 被调用的远程服务收到请求并接收到了请求体里的json数据,
public R save(@RequestBody SpuBoundsEntity spuBounds)
将请求体的json转为SpuBoundsEntity - 表明:只要SpuBoundsTo和SpuBoundsEntity里面的属性名存在一部分一一对应就可以进行以上的转换
3.2 可以有两种方式进行远程调用
- 通过网关进行远程调用
-
@FeignClient("gulimall-gateway"):给gulimall-gateway所在机器发请求
-
/api/product/skuinfo/info/{skuId}
-
- 后端服务之间远程调用
-
FeignClient("gulimall-coupon"):直接让后台指定服务处理/给gulimall-product所在机器发请求
-
/product/skuinfo/info/{skuId}
-