在SpringCloud架构体系中,微服务间的通信是基于Feign调用。而在实际使用Feign的过程中我们大概率会面临下面几个问题:Feign客户端放在消费端还是独立一个api层?Feign调用的接口如何要不要进行包装?Feign如何抓取业务生产端的业务异常?这篇文章我们就来一起探讨一下这几个问题,希望看完能对你有所帮助。首先我们先看看Feign的调用方式如何抉择?Feign的调用方式如何选择?总体来说,Feign的调用方式分为两大类:在生产端API中声明Feign客户端如上,消费端服务直接依赖生产端提供的API包,然后通过@Autowired注解注入,就可以直接调用生产者提供的接口。这样做的
前几天有一个看我SpringCloudalibaba系列文章的粉丝私下问我:如何处理jwt失效的问题?修改密码或退出登录后需要将之前的jwttoken失效掉,不允许使用旧token登录系统。我说:很简单呀,咱们直接无为而治,用户退出或修改密码的时候前端直接删除这个token不就完了吗?后端啥都不用管,啥也不用做。他说:别闹,你的每篇文章我都给你一键三连。我当时就被感动了,既然是这样的好读者,我果断答应专门给他写篇文章来分享一下我这个不太成熟的做法,改造一下这个SpringCloudalibaba项目。在正式开始之前,我们先来回顾一下oauth2中token的相关知识。知识回顾众所周知,在OAu
在SpringCloud实战系列文章中曾经介绍过在SpringCloud体系下如何防止前端请求绕过网关直接到达后端微服务,今天我们要反其道而行之,介绍在SpringCloud体系中如何防止内部隐私接口被网关调用。看到这里可能有的同学会有点晕,怎么还有这种业务场景呢,别急,咱们先回顾一下我们的业务场景。“友情提示,这是系列文章,欢迎持续关注!”业务场景客户端通过网关调用OrderService服务获取数据,OrderService通过Feign调用AccountService服务,而当AccountService提供对应的Feign接口后,客户端是可以通过网关直接调用AccountService
前言这篇文章来源于粉丝提出的一个问题:如何解决多环境统一注册中心服务实例乱窜?怎么理解呢?假设现在开发环境的AccountService已经在Nacos中注册了,现在小张需要对它进行修改升级,本地启动AccountService后也注册到了Nacos,但是在调试的时候请求通过网关经常直接跳转到开发环境,这样的话小张就没办法安心debug了。其实这个问题归根结底是如何基于SpringCloudGateway实现灰度发布,通过指定的规则让请求流量到达特定的实例。在SpringCloud2020版本中官方推荐使用SpringCloudLoadBalancer来替换原Ribbon的负载均衡器。所以本篇
前言分布式事务是在微服务开发中经常会遇到的一个问题,之前的文章中我们已经实现了利用Seata来实现强一致性事务,其实还有一种广为人知的方案就是利用消息队列来实现分布式事务,保证数据的最终一致性,也就是我们常说的柔性事务。消息队列实现分布式事务原理首先让我们来看一下基于消息队列实现分布式事务的原理方案。发送消息的服务有个OUTBOX数据表,在进行INSERT、UPDATE、DELETE业务操作时也会给OUTBOX数据表INSERT一条消息记录,这样可以保证原子性,因为这是基于本地的ACID事务。OUTBOX表充当临时消息队列,然后我们在引入一个消息中继(MessageRelay)的服务,由他从O
概述在单体项目中如果我们需要记录操作日志一般会通过如下手段实现:建立一个自定义注解,标注业务操作类型通过AOP组装日志实体,完成日志的收集工作具体实现可以参考如下的文章链接:http://javadaily.cn/articles/2020/05/13/1589330750429.html但是在微服务架构中我们不可能每个服务都写一个自定义注解,再写一个AOP,这很明显违反了Don’trepeatyourself精神。所以这时候我们一般都会建立一个公共的组件,在公共组件中完成日志的收集,后端服务只需要引入这个公共的组件即可。这就是今天文章的内容,独立的业务日志收集组件。SpringBootSta
前面文章咱们对比过网关授权与微服务授权的区别,文章也提到了,如果要实现微服务授权,一般会构建一个独立的资源服务器配置模块,否则每个后端业务都需要进行资源服务器的配置,那本节内容我们就来完成此功能。由于间隔时间较久,建议先阅读下面两篇相关文章回顾一下。SpringCloudAlibaba微服务实战十九-集成RBAC授权SpringCloudAlibaba微服务实战二十八-网关授权VS微服务授权话不多说,我们直接开始代码改造。认证服务器改造首先我们需要改造认证服务器,需要认证服务器在构建用户权限的时候使用的是权限标识字段。对于代码而言只需要UserDetailServiceImpl#loadUse
请求响应日志是日常开发调试定位问题的重要手段,在微服务中引入SpringCloudGateway后我们希望在网关层统一进行日志的收集。本节内容将实现以下两个功能:获取请求的输入输出参数,封装成自定义日志将日志发送到MongoDB进行存储获取输入输出参数首先我们先定义一个日志体@Datapublic class GatewayLog { /**访问实例*/ private String targetServer; /**请求路径*/ private String requestPath; /**请求方法*/ private String requestMeth
在SpringCloud架构中,实现授权功能有两种实现方式:在网关层进行授权由后端微服务自己授权两种方式在此系列文章中都有实现方案,那么问题来了:哪种才是最优方案,哪种方案更合理呢?很抱歉,看完这篇文章你也不一定能得到你想要的答案,因为结论是并没有最优方案,两种方案各有千秋,只有根据自身业务选择对应的方案。本文我们将两种方案做一个简单对比,以便大伙在做方案决策有个选择参考。解决方案对比首先我们看看两种方案实现的原理:如果对具体实现方式有疑问的同学可以参考这篇文章:SpringCloudAlibaba微服务实战十九-集成RBAC授权网关授权基于网关授权我们又叫基于路径匹配器授权,请求在经过网关的
前言使用SpringCloud架构后我们希望所有的请求都需要经过网关才能访问,在不作任何处理的情况下我们是可以绕过网关直接访问后端服务的。如下,我们绕过网关直接访问后端服务也是可以获取到数据的。那我们今天的议题就是如何防止请求绕过网关直接访问后端服务?解决方案我觉得防止绕过网关直接请求后端服务的解决方案主要有三种:使用Kubernetes部署在使用Kubernetes部署SpringCloud架构时我们给网关的Service配置NodePort,其他后端服务的Service使用ClusterIp,这样在集群外就只能访问到网关了。网络隔离后端普通服务都部署在内网,通过防火墙策略限制只允许网关应用
前言今天内容主要是解决一位粉丝提的问题:在使用SpringSecurityOAuth2时如何自定义认证服务器返回异常。那么首先我们先以Password模式为例看看在认证时会出现哪些异常情况。授权模式错误这里我们故意将授权模式password修改成password1,认证服务器返回如下所示的异常{ "error": "unsupported_grant_type", "error_description": "Unsupported grant type: password1"}密码错误在认证时故意输错usern
前言之前在集成RBAC授权的文章中提到了SpringCloud可以「基于路径匹配器授权」在网关层进行用户权限校验,这种方式的实现原理是SpringcloudGateway接受到请求后根据ReactiveAuthorizationManager#check(Mono<Authentication>authenticationMono,AuthorizationContextauthorizationContext)方法基于AntPathMatcher校验当前访问的URL是否在用户拥有的权限URL中,如果能匹配上则说明拥有访问权限并放行到后端服务,否则提示用户无访问权限。具体实现方式在
前言在单体SpringBoot项目中我们需要捕获全局异常只需要在项目中配置@RestControllerAdvice和@ExceptionHandler就可以针对不同类型异常进行统一处理,统一包装后返回给前端调用方。@Slf4j@RestControllerAdvicepublic class RestExceptionHandler { /** * 默认全局异常处理。 * @return ResultData */ @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERN
概述在正常情况下Feign有三种客户端实现:Client.Default类:默认的feign.Client客户端实现类,内部使用HttpURLConnnection完成HTTPURL请求处理;ApacheHttpClient类:内部使用Apachehttpclient开源组件完成HTTPURL请求处理的feign.Client客户端实现类;OkHttpClient类:内部使用OkHttp3开源组件完成HTTPURL请求处理的feign.Client客户端实现类。@ConditionalOnClass({ ILoadBalancer.class, Feign.class })@Condition
概述在SpringCloud构建的微服务系统中,大多数的开发者使用都是官方提供的Feign组件来进行内部服务通信,这种声明式的HTTP客户端使用起来非常的简洁、方便、优雅,但是有一点,在使用Feign消费服务的时候,相比较Dubbo这种RPC框架而言,性能较差。虽说在微服务架构中,会讲按照业务划分的微服务独立部署,并且运行在各自的进程中。微服务之间的通信更加倾向于使用HTTP这种简答的通信机制,大多数情况都会使用RESTAPI。这种通信方式非常的简洁高效,并且和开发平台、语言无关,但是通常情况下,HTTP并不会开启KeepAlive功能,即当前连接为短连接,短连接的缺点是每次请求都需要建立TC
今天内容主要是解决一位粉丝提的问题:如何在jwt中添加用户的额外信息并在资源服务器中获取这些数据。涉及的知识点有以下三个:如何在返回的jwt中添加自定义数据如何在jwt中添加用户的额外数据,比如用户id、手机号码如何在资源服务器中取出这些自定义数据下面我们分别来看如何实现。如何在返回的jwt中添加自定义数据这个问题比较简单,只要按照如下两步即可:编写自定义token增强器package com.javadaily.auth.security;import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;im
在之前的项目中我们已经实现了使用Feign调用远程接口,本章内容主要是借助sentinel实现Feign接口熔断器功能。概述首先我们看看不使用熔断器的情况下调用一个没有启动的服务会出现什么效果,然后再来看看使用sentinel熔断器后的效果。如上,我们使用order-service中FeignController调用account-service中的接口,在没启用熔断器的情况下,接口会抛出500异常。实现使用sentinel实现熔断器很简单,简单几步即可。定义fallback类,当熔断时返回默认数据package com.javadaily.feign.fallback;@Slf4jpubli
概述前面几篇文章我们一直是在实现SpringCloud体系中的认证功能模块,验证当前登录用户的身份;本篇文章我们来讲SpringCloud体系中的授权功能,验证你是否能访问某些功能。认证授权很多同学分不清认证和授权,把他们当同一个概念来看待。其实他们是两个完全不同的概念,举个容易理解的例子:你是张三,某知名论坛的版主。在你登录论坛的时候输入账号密码登录成功,这就证明了你是张三,这个过程叫做认证(authentication)。登录后系统判断你是版主,你可以给别人发表的帖子加亮、置顶,这个校验过程就是授权(authorization)。简而言之,认证过程是告诉你你是谁,而授权过程是告诉你你能做什
概述大家都知道在oauth2认证体系中有四种授权模式:授权码模式(authorizationcode)简化模式(implicit)客户端模式(clientcredentials)密码模式(password)那么如何新增一个自定义的授权模式,比如像下面这样根据手机号和短信验证码进行登录呢?要自定义授权模式我们得先了解下oauth2.0的整体认证过程,认证入口在org.springframework.security.oauth2.provider.endpoint.TokenEndpoint#postAccessToken方法中@RequestMapping( value = {&
概述在OAuth2体系中认证通过后返回的令牌信息分为两大类:不透明令牌(opaquetokens)和透明令牌(notopaquetokens)。不透明令牌就是一种无可读性的令牌,一般来说就是一段普通的UUID字符串。使用不透明令牌会降低系统性能和可用性,并且增加延迟,因为资源服务不知道这个令牌是什么,代表谁,需要调用认证服务器获取用户信息接口才知道这个令牌是谁。如下就是我们在资源服务器中的配置,需要指明认证服务器的接口地址。security: oauth2: resource: user-info-uri: http://localhost:5000/user/current
概述好久没有更新SpringCloudAlibaba系列的文章了,今天我们来将版本升级到最新的毕业版本。并且将原来容器化部署的组件seata、nacos、sentinel拉出来单独部署,为我们后面k8s部署作准备。官方推荐版本如下:这篇文章主要是讲升级过程中遇到的一些问题并讲述解决的过程与方法,如果要了解详细用法还请翻看之前的文章。主版本升级<properties>... <spring-boot.version>2.2.5.RELEASE</spring-boot.version> <alibaba-cloud.version>2.2.1.RE
SpringCloudAlibaba系列文章已经写了15篇了,基本框架大体完成,业务相关的逻辑还需要根据项目本身的业务进行梳理改造。今天将是本系列的最后一篇-SpringCloud容器化部署(理论上最后一篇,不排除后面会对相关组件进行升级)看在写了这么多的份上是不是应该点个在看呢?开启Docker远程访问由于我是在windows上进行开发没有安装docker,所以需要找一台安装好docker的服务器并开启远程访问。使用mac的同学请忽略。打开docker配置文件vi/lib/systemd/system/docker.service开放2376端口找到ExecStart=/usr/bin/do
导读:上篇文章我们已经抽取出了单独的认证服务,本章主要内容是让SpringCloudGateway集成Oauth2。概念部分image.png在网关集成Oauth2.0后,我们的流程架构如上。主要逻辑如下:1、客户端应用通过api网关请求认证服务器获取access_tokenhttp://localhost:8090/auth-service/oauth/token2、认证服务器返回access_token{"access_token":"f938d0c1-9633-460d-acdd-f0693a6b5f4c","token_type&quo
导读:为了保证我们微服务的安全性,本章主要内容是使用Oauth2.0给我们微服务加上安全校验。概念为了保证服务的安全性,往往都会在接口调用时做权限校验。在分布式架构中我们会把复杂的业务拆成多个微服务,这样不得不在所有服务中都实现这样的权限校验逻辑,这样就会有很多代码和功能冗余。所以在微服务架构中一般会独立出一个单独的认证授权服务,供其他所有服务调用。在SpringCloud体系中,我们只对网关层开放外网访问权限,其他后端微服务做网络隔离,所有外部请求必须要通过网关才能访问到后端服务。在网关层对请求进行转发时先校验用户权限,判断用户是否有权限访问。我们一般使用Oauth2.0来实现对所有后端服务
导读:通过前面的章节我们在微服务层做了限流,并且集成了SpringCloudGateway,本章主要内容是将限流功能从微服务迁移到网关层。SpringCloudGateway原生限流SpringcloudGateway原生限流主要基于过滤器实现,我们可以直接使用内置的过滤器RequestRateLimiterGatewayFilterFactory,目前RequestRateLimiterGatewayFilterFactory的实现依赖于Redis,所以我们还要引入spring-boot-starter-data-redis-reactive。POM依赖<dependency>&
导读:在SpringCloud体系架构中,我们需要的每个服务都需要对外输出接口文档,本篇内容主要是给我们的微服务配上Swagger的接口文档,并在网关层完成接口聚合。Swagger2简介在当下很多项目都会采用前后端分离的模式,前端和后端的工作由不同的开发人员完成。在这种开发模式下,我们需要维护一份及时更新且完整的RestAPI接口文档。传统意义上的文档都是后端人员在开发相关接口后手动更新到接口文档上,但是这种方式很难保证文档的及时性,而且由于一些原因后端开发人员可能会忘记更新,这样就会导致随着开发的进行接口文档会失去他本身的参考意义,反而会增加沟通成本。而Swagger给我们提供了一个全新的维
在SpringCloud体系架构中,我们需要部署一个单独的网关服务对外提供访问入口,然后网关服务根据配置好的规则将请求转发至具体的后端服务,本章内容主要是给我们的微服务加上网关SpringCloudGateway。前言背景我们有了三个服务account-service,product-service,order-service。现在有客户端WEB应用或APP应用需要访问后端服务获取数据那么就需要在客户端维护好三个服务的访问路径。这样的架构会有如下几个典型的问题:每个微服务都需要配置单独的访问域名,开通外网访问权限,每新增一个服务都需要先让运维人员配置好域名映射客户端需要维护所有微服务的访问地址
前言通过前两篇文章我们使用了Seata作为分布式事务组件,并使用Nacos作为Seata的注册配置中心,本篇文章我们将Seata部署在容器Docker上。当然了如果大家对Docker不是很熟悉的话或者仅对Docker感兴趣可以翻看我之前为大家准备的两篇文章。Docker基础与实战,看这一篇就够了Docker-Compose基础与实战,看这一篇就够了Seata容器化在使用Docker部署服务的时候我们应该将配置文件外部化,这样方便后续修改,在修改完成后通过-v指令将文件挂载进容器。接下来我们一步一步来实现容器化过程。启动一个Seata的临时容器。dockerrun--rm--nameseata-
本篇作为SpringCloudAlibaba微服务实战系列的第八篇,主要内容是让Seata使用Nacos作为注册配置中心。系列文章,欢迎持续关注。上篇文章中我们使用的是Seata的file配置实现分布式事务,既然本系列文章用的是Springcloudalibaba全家桶而Seata又恰好支持Naocs,那么我们肯定也将选择Nacos作为Seata的注册配置中心。本篇文章我们将一步一步把Seata整合上Nacos,大家伙跟我一起动手试试吧~本篇文章依赖于上篇文章SpringCloudAlibaba微服务实战七-分布式事务配置调整服务端配置修改服务端主要是修改\seata\conf\registr
导读:本篇作为SpringCloudAlibaba微服务实战系列的第七篇,主要内容是使用Seata解决分布式事务问题。系列文章,欢迎持续关注。场景说明订单服务order-service需要对外提供创建订单的接口,创建订单的业务逻辑如下:先调用本地的orderService保存订单操作,然后通过feign调用远程的accout-service进行账户余额扣减,最后再通过feign调用远程的product-service进行库存扣减操作。关键的逻辑代码如下:OrderController对外提供创建订单的接口@PostMapping("/order/create")public