微服务常用的组件有哪些
现在有越来越多的应用都在采用微服务架构,我曾经工作过的两家公司的项目就都是使用的微服务架构,今天我们就来带大家搭建一个最小化的微服务应用,这样大家会对微服务中各个组件的作用和联系有更加深刻的认识。
下图体现了微服务项目中各个组件之间的关系:
说下微服务的几大必不可少的组件,它们分别是:
- 注册中心:所有微服务的ip地址都会注册在上面,它就类似于咱们手机中的通讯录,我们可以根据这个通讯录查到提供某个服务的所有服务器的ip地址,这样就能调用具体某个服务器上的接口。目前开发中最常用的注册中心是nacos,我们今天要搭建的微服务也是使用它作为注册中心。总而言之,当听到注册中心这四个字,我们脑海中的第一反应就是它是一个通讯录,里面存的都是各个微服务的联系方式。
- 配置中心:在过去的单体项目中,每个服务的配置都是写在各自的配置文件中,微服务与此不同,因为微服务中的每个服务可能会部署到多台服务器上,如果还是按照之前的做法,那么每个提供相同服务的项目用的都是完全相同的配置文件,将来某个微服务的哪个配置需要改变,就需要我们找到提供这个服务的所有节点,然后一个个修改配置文件,这样很明显是不利于维护的,所以我们就需要将所有服务的配置文件统一放到某个地方,这样我们只需要去这一个地方修改配置文件即可,而不是去所有服务节点去一个个修改配置文件。这其实有点像我们开发中的将重复代码抽取成一个工具类在各个地方调用一样,都是将重复的配置或者代码抽取出来集中管理,这样更好维护。总结一句话就是,配置中心是所有微服务的配置文件。前来说,最常用的配置中心是nacos,对,你没看错,又是nacos,nacos是阿里巴巴开源的一个组件,可以同时充当注册中心和配置中心。
- 服务调用工具:由于整个项目拆分成了一个个微服务,而有时候处理某个任务可能需要同时用到多个服务的功能,比如:用户在淘宝下单后,可能就需要在订单服务中调用库存服务的接口,这时候就需要各个服务之间能够相互调用,其实就是调用接口,我们使用postman调用单体服务的接口类似,可以实现网络接口调用的工具有很多,最常用的有springMVC内置的RestTemplate,但是我们在服务调用时不会直接用它,而是使用基于它封装过的openFeign。因为后者会从注册中心中拿到服务器的地址,然后通过负载均衡策略选择其中某个节点进行调用,这要比我们直接使用restTemplate方便的多。如果我们将注册中心当做是通讯录,那么openFeign就相当于是拨号的手机。
- 网关:网关是所有服务的入口,相当于你家的大门,客户端的每个请求不会直接到达各个微服务,而是会先到达网关,然后通过网关将请求转发给对应的微服务,微服务将结果返回给网关,然后网关再将结果返回给客户端。目前最常用的网关是gateway,我们这次也将使用它作为网关。
上面四个就是微服务中必不可少的组件,少一个都不行。当然微服务的组件肯定不止这些,比如和熔断限流有关的组件,和微服务链路追踪有关的组件,后两者虽然重要,但并不是必须的。由于我们这里只是想搭建一个最小化的微服务应用,所以这里只会用到上面四个必不可少的组件,我这里的微服务组件选型是:gateway + openFeign + nacos。
我们可以通过下图中的请求调用链路来理解这四个组件在微服务中的角色和作用
简单解释一下这张图:
- 客户端的请求首先达到网关
- 网关从注册中心获取到服务C的ip列表,然后从中选择一个节点进行调用
- 服务C又通过注册中心拿到服务B的节点列表,然后通过负载均衡策略调用选择服务B的某个节点,拿到B返回的结果
- 服务C将最终的结果返回给网关
- 网关将服务C返回的结果返回给客户端
搭建注册中心
启动nacos服务端
我们需要去nacos的官网下载nacos,然后通过startup.cmd -m standalone
指令启动nacos注册中心的服务端。
接下来我们就可以通过http://localhost:8848/nacos
进入到nacos注册中心的页面,这个页面主要是为了方便我们查看注册中心中的信息,跟我们查看redis数据的客户端工具差不多。
进入后我们可以在服务列表看到所有注册的服务
当然大家刚进去时,这里肯定是空的,需要各个微服务将自己的信息注册到nacos后才能在这里看到数据。
创建项目
微服务也是一个Maven的多模块工程,我们在父模块中主要是为了管理依赖的版本,同时我们还会创建一个公共模块,用来存放项目中的实体类和通用的工具类和所有微服务都需要引入的依赖。
下面是我的父模块的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.lizemin</groupId>
<artifactId>TaoBao-micro-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>micro-service</name>
<description>micro-service</description>
<modules>
<module>common</module>
<module>order</module>
<module>stock</module>
<module>transport</module>
<module>product</module>
<module>tabao-gateway</module>
<module>api-client</module>
</modules>
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud-dependencies.version>2021.0.5</spring-cloud-dependencies.version>
<spring-cloud-alibaba-dependencies.version>2021.0.5.0</spring-cloud-alibaba-dependencies.version>
<spring-boot-dependencies.version>2.6.13</spring-boot-dependencies.version>
<common.version>0.0.1-SNAPSHOT</common.version>
</properties>
<dependencyManagement>
<dependencies>
<!--管理所有spring cloud组件的版本-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--管理所有spring cloud alibaba组件的版本-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--管理所有微服务springboot的版本-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
需要注意的是:我们在使用spring cloud和springboot以及spring cloud alibaba时,一定要考虑它们之间的版本兼容性。各个版本的兼容关系可以参考这里。
下面是common模块的pom.xml
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lizemin</groupId>
<artifactId>TaoBao-micro-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>common</artifactId>
<packaging>jar</packaging>
<name>common</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.35</version>
</dependency>
<!--nacos注册中心客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.lizemin</groupId>
<artifactId>api-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--nacos配置中心客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
</project>
上面我引入了所有微服务都需要的nacos注册中心客户端和nacos配置中心的客户端,同时我还引入了hutool的工具类
然后我们只需要在各个微服务的application.yaml中添加如下配置即可:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # 这里是配置中心的地址
搭建网关
网关我们使用的是gateway,需要引入相应的依赖:
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lizemin</groupId>
<artifactId>TaoBao-micro-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>tabao-gateway</artifactId>
<packaging>jar</packaging>
<name>tabao-gateway</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--引入gateway的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.lizemin</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-web</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
上面我们引入了gateway的依赖,以及公共模块的依赖。然后我们需要给网关配置路由,也就是转发规则。当我们访问某个路径时,网关根据什么规则来决定将这个请求转发给哪个微服务。
下面是我的网关的配置文件
server:
port: 8888
spring:
application:
name: GATEWAY-SERVICE
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
routes:
# 订单服务
- id: order_route
uri: lb://ORDER-SERVICE
predicates:
- Path=/order/**
filters:
- StripPrefix=1 # 去掉路径前缀中的第一个部分
# 商品服务
- id: product_route
uri: lb://PRODUCT-SERVICE
predicates:
- Path=/product/**
filters:
- StripPrefix=1 # 去掉路径前缀中的第一个部分
# 库存服务
- id: stock_route
uri: lb://STOCK-SERVICE
predicates:
- Path=/stock/**
filters:
- StripPrefix=1 # 去掉路径前缀中的第一个部分
# 运输服务
- id: transport_route
uri: lb://TRANSPORT-SERVICE
predicates:
- Path=/transport/**
filters:
- StripPrefix=1 # 去掉路径前缀中的第一个部分
搭建各个服务
前面说过微服务项目就是一个模块工程,我这里模拟了电商微服务的项目,分别搭建了订单微服务,商品微服务,库存微服务,物流微服务
这几个模块跟我们平时的springboot应用没啥区别,这里限于篇幅就省略了。
使用openFeign远程调用
这里我为了方便各个微服务间使用openFeign调用,专门建了一个api-client的模块。
使用open需要引入如下依赖:
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lizemin</groupId>
<artifactId>TaoBao-micro-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>api-client</artifactId>
<packaging>jar</packaging>
<name>api-client</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--引入服务调用的工具:openFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--新版的openFeign需要引入负载均衡器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
另外,我们在使用openFeign时,需要开启feign的调用,具体方式是在主启动类上添加@EnableFeignClients
注解即可
然后我们就可以使用openFeign调用其他微服务的接口了,如下图所示:
这里我在订单服务中通过openFeign调用了库存微服务的接口。
将配置迁移到nacos配置中心
前面我们都是将配置放在application.yml中,接下来我们需要将配置迁移到nacos配置中心。前面我们已经在common模块中引入了nacos配置中心的客户端依赖,接下来我们直接将各个微服务的配置迁移到nacos,如下图所示:
首先我们需要新建一个配置
然后我们在各个微服务中配置nacos注册中心即可:
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 # nacos配置中心的地址
group: ORDER_GROUP # 这里需要和nacos上的group保持一致
shared-configs: # 公共配置
- data-id: COMMON-dev.yaml
group: DEFAULT_GROUP
refresh: true # 配置是否支持热更新
# 默认使用public命名空间
config:
import:
- nacos:ORDER-SERVICE-dev.yaml?refreshEnabled=true
- nacos:COMMON-dev.yaml?group=DEFAULT_GROUP&refreshEnabled=true
这样我们就搭建好了整个项目,接下来我们通过网关查看订单,结果如下:
可以看到网关成功返回了结果
通过日志,我们可以看到请求也确实到了商品微服务。
文章中完整的示例代码地址
最后的总结
在这篇文章中我们给大家介绍了微服务中几个关键组件,以及它们的作用和在项目中的角色,并且带大家从头到尾搭建了整个微服务,希望对大家有用。
觉得有收获的朋友可以点个赞,您的鼓励就是我最大的动力!