在阅读这篇文章前,推荐一篇“好”文章:MediaCrawler 提取评论生词云:小红书实例-麦琳评论区
对于从事自媒体的同学来说是一个非常不错的工具,也非常详细的说明了生成词云的过程。
微服务大家都不陌生,无论是概念还是技术,在前几年都是非常火热的一个话题。之前写过一个《什么样的项目适合微服务架构?》,感兴趣的可以看一下,这里就不赘述。
对于构建微服务的技术栈来讲,Spring Cloud Netflix 和 Spring Cloud Alibaba 我在实际项目中都用过。以我的感受来讲,Alibaba 这一套对开发者来讲更友好,这里不展开。
本文基于 Spring Cloud Alibaba 设计一个基本的微服务架构并实现,如果有不到位的地方也请各位大佬多多指点。
以典型的购物商场为例,如果项目以微服务形式开发,大概会有用户、商品、库存、订单、支付等多个服务。
各个服务之间必然会存在一些交集,比如一个交易会涉及到订单、商品、库存等多个服务,这时候就需要通过互相调用获得对方的能力。
微服务之间的调用,其实就是网络通信,当然,我们不会自己实现调用过程。有很多现成的RPC框架,直接拿来用就好,本文选择 Dubbo 框架用于各服务之间的调用。
微服务架构的项目,不论是出于高可用还是高并发的考虑,各个服务一般都是以集群的形式存在,例如用户服务可能会部署 N 个实例。
这个时候就有一个问题:调用方应该调用哪个实例?
这个时候就需要有一个概念:服务注册与发现。
简单来说,服务的提供者将自己上报给一个平台,调用方通过这个平台就知道有几个实例并选择调用。用专业术语来讲,这里“平台”被称为“注册中心”。对于注册中心,本文选择 Nacos。
而作为RPC调用框架的 Dubbo 来讲,具体调用哪个实例就是它的工作,这里称之为”负载均衡策略“。
就如上所说,一次交易需要多个服务的协同才能完成,这也是分布式的特性。这个过程中必然会存在分布式事务问题,为了更快速、方便的解决这一问题,本文选择现成的分布式事务解决框架 Seata。
对于微服务架构的项目来讲,最终会对外暴露很多请求地址。但是,我们不可能对外提供多个地址,一定是需要一个统一的访问入口,这里称之为“网关”。 因为和业务关联,所以这里的网关又称之为“业务网关”或““微服务网关”。当然,现在也有流量、业务网关为一体的云原生网关,例如Higress,这里不展开说明。对于微服务网关,本文选择 Gateway 。
以上的几个微服务组件基本上可以搭建一个简单的微服务项目。但通常微服务架构的项目不会这么简单,否则也没必要选择微服务架构。
就如上面所说,微服务项目中会有很多的服务,在发布部署时再一个个手动打包部署就不太现实。如何让微服务快速构建、发布甚至是自动扩缩容,这里称之为DevOps。
以及各服务在运行过程中避免不了一些问题的发生,例如服务下游的因请求响应过慢、超时导致请求阻塞,从而引起服务雪崩,并且如何在错综复杂的调用链路中快速定位排查哪个环节出现了问题。如何避免这些问题或者更好的解决这些问题让服务更稳定地运行,我们称之为“服务治理”。
对于“服务雪崩”问题,可以通过限流、熔断降级有效的避免,本文选择 Sentinel 。对于“调用链路”问题,可以通过“全链路追踪”提高定位排查效率,本文选择 Zipkin。
加上系统中离不开的数据库、文件存储、缓存、以及消息队列等组件,通常一个微服务架构是这样的。
接下来,就基于上述涉及到的微服务组件搭建一个微服务项目。
首先需要将上述涉及到的 Nacos、Sentinel、Seata、Zipkin 组件先行部署起来。本文就基于 Docker 部署,部署过程这里不赘述,有需要可以前往官网了解。
还是以购物商场为例,我这里创建了网关、订单、库存、用户这几个服务。
该示例会实现服务的注册、发现和调用以及分布式事务的验证,限流、熔断降级等功能。
首先看服务注册、发现。将这几个服务注册到 Nacos 只需要3个步骤:
@EnableDiscoveryClient
注解 <dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos
项目启动成功后,Nacos管理页面就可以看到注册成功的服务。
简单来说,就是spring-cloud-starter-alibaba-nacos-discovery
作为nacos的客户端和nacos进行通信,达到注册和发现的效果。
各服务成功注册后,就可以借助RPC框架互相调用。如上所说,本文选择的是Dubbo完成调用。
将这几个服务完成Dubbo的调用需要3个步骤:
@EnableDubbo
注解 <dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
</dependency>
dubbo.registry.address=nacos://127.0.0.1:8848
dubbo.registry.register-mode=instance
dubbo.protocol.port=20882
dubbo.application.name=order
dubbo.application.logger=slf4j
为了让各项目之间可以更方便的调用,我将每个工程分为 api 和 service 。
各api工程声明了该服务暴露的接口能力,然后在service中进行实现,如果需要被其他服务调用,service中的实现需要添加@DubboService
注解。
这样的话,当某个服务需要其他服务的能力时直接依赖api工程。以 order
工程为例,后续会调用user
和stock
的服务,所以order-service
中直接添加user-api
和stock-api
的依赖。
然后在编码时通过@DubboReference
引入就可以完成服务之间的调用。
当以上的工作完成后,会发现在nacos中接口能力也已经成功注册(如下图),这样其他的服务也能通过nacos发现,从而完成调用。
当然,也可以通过网关进行统一调用,只需要在gateway项目中配置路由即可转发至指定的服务,例如:
spring.cloud.gateway.routes[0].id=order
spring.cloud.gateway.routes[0].uri=lb://order
spring.cloud.gateway.routes[0].predicates[0]=Path=/order/**
lb://order
的配置就说明了:可以负载调用order
服务的多个实例。
如果要保证order
服务中的add
接口的事务一致性,就可以通过Seata来处理。
因为本文选择的Dubbo进行服务调用,所以需要使用Seata让将dubbo支持分布式事务。需要以下几个步骤即可实现:
@GlobalTransactional
注解。 <dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-seata-spring-boot-starter</artifactId>
</dependency>
以上操作完后对Seata进行验证,如下图,在stock
服务中模拟库存不足,Seata 帮我们进行了回滚。
seata 原理可移步至官网,这里就不赘述了。
虽说服务限流、熔断降级实现细节较复杂,但使用 Sentinel 之后完全可以通过UI界面进行限流、降级的配置。
同样,因为本文选择的Dubbo进行服务调用,所以 Sentinel 支持 dubbo 防护能力需要以下几个步骤即可实现:
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-sentinel-spring-boot-starter</artifactId>
</dependency>
引入这个依赖后,Dubbo 的服务接口和方法就会成为 Sentinel 中的资源,在配置了规则后就可以自动享受到 Sentinel 的防护能力。
建议大家自行部署体验。
微服务技术发展至今技术已经非常成熟,我们可以选择现有的框架快速搭建一套微服务项目。当然,项目中的技术越多,系统的复杂度也随之增加。
整篇文章看下来不难发现,微服务中的服务调用是最基本且最重要的,种种技术栈都围绕着RPC。无论注册中心、分布式事务以及服务治理等。所以在微服务架构中选择一个RPC框架是至关重要的。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。