API网关
Spring Cloud Gateway、Soul、Kong、APISIX和Zuul
weixin_42073629
这个作者很懒,什么都没留下…
展开
-
Spring Cloud Zuul的饥饿加载(eager-load)使用
上一篇我们介绍了如何使用Ribbon的earger-load配置加速Spring Cloud中对服务接口的第一次调用。可是这样只是解决了内部服务间的调用,另外一个问题依然经常困扰我们,那就是网关到内部服务的访问。由于Spring Cloud Zuul的路由转发也是通过Ribbon实现负载均衡的,所以它也会存在第一次调时比较慢的情况。那么这个时候我们要如何设置呢?Zuul中的Eager Load配置在Spring Cloud Zuul中也提供了一个配置参数来实现earger-load,具体如下:.原创 2020-07-19 16:58:16 · 373 阅读 · 0 评论 -
Spring Cloud Zuul的路径匹配
路径匹配不论是使用传统路由的配置方式还是服务路由的配置方式,我们都需要为每个路由规则定义匹配表达式,也就是上面所说的path参数。在Zuul中,路由匹配的路径表达式采用了Ant风格定义。Ant风格的路径表达式使用起来非常简单,它一共有下面这三种通配符:通配符 说明 ? 匹配任意的单个字符 * 匹配任意数量的字符 ** 匹配任意数量的字符,支持多级目录 我们可以通过下表的示例来进一步理解这三个通配符的含义并参考着来使用:URL路径 说明 /us原创 2020-07-18 19:20:46 · 893 阅读 · 0 评论 -
Spring Cloud Zuul的fallback优化
如何在Zuul中使用fallback功能我们在项目中使用Spring cloud zuul的时候,有一种这样的需求,就是当我们的zuul进行路由分发时,如果后端服务没有启动,或者调用超时,这时候我们希望Zuul提供一种降级功能,而不是将异常暴露出来。在Dalston版本中,Spring cloud zuul提供这种降级功能,操作步骤如下:在主函数上添加@EnbaleZuulProxy注解。 实现ZuulFallbackProvider接口。对应ZuulFallbackProvider源码如下原创 2020-07-18 17:54:36 · 272 阅读 · 0 评论 -
Spring Cloud Zuul统一异常处理(三)
在最新的Dalston版本中,Spring Cloud Zuul做了一些优化,所以我们不再需要做这些扩展就已经能够正确的处理异常信息了。那么,在Dalston版中,Spring Cloud Zuul中做了怎么样的修改以达到之前我们自己扩展的效果呢?过滤器类型的变更读者是否还记得我们之前分析了Spring Cloud Zuul自带的核心过滤器有哪些呢?我们先根据下图回忆一下:这次主要将SendErrorFilter过滤器的类型从POST改为了ERROR,所以核心过滤器变成了如下图的结构:原创 2020-07-18 17:40:56 · 317 阅读 · 0 评论 -
Spring Cloud Zuul统一异常处理(二)
在前几天发布的《Zuul统一异常处理(一)》一文中,我们详细说明了当Zuul的过滤器中抛出异常时会发生客户端没有返回任何内容的问题以及针对这个问题的两种解决方案:一种是通过在各个阶段的过滤器中增加try-catch块,实现过滤器内部的异常处理;另一种是利用error类型过滤器的生命周期特性,集中地处理pre、route、post阶段抛出的异常信息。通常情况下,我们可以将这两种手段同时使用,其中第一种是对开发人员的基本要求;而第二种是对第一种处理方式的补充,以防止一些意外情况的发生。这样的异常处理机制看似已经原创 2020-07-18 17:38:07 · 229 阅读 · 0 评论 -
Spring Cloud Zuul统一异常处理(一)
在上一篇《Spring Cloud微服务架构:服务网关(过滤器)》一文中,我们详细介绍了Spring Cloud Zuul中自己实现的一些核心过滤器,以及这些过滤器在请求生命周期中的不同作用。我们会发现在这些核心过滤器中并没有实现error阶段的过滤器。那么这些过滤器可以用来做什么呢?接下来,本文将介绍如何利用error过滤器来实现统一的异常处理。过滤器中抛出异常的问题首先,我们可以来看看默认情况下,过滤器中抛出异常Spring Cloud Zuul会发生什么现象。我们创建一个pre类型的过滤器,并原创 2020-07-18 17:33:51 · 427 阅读 · 0 评论 -
Spring Cloud Zuul重试机制探秘
简介本文章对应spring cloud的版本为(Dalston.SR4),具体内容如下:开启Zuul功能 通过源码了解Zuul的一次转发 怎么开启zuul的重试机制 Edgware.RC1版本的优化开启Zuul的功能首先如何使用spring cloud zuul完成路由转发的功能,这个问题很简单,只需要进行如下准备工作即可:注册中心(Eureka Server) zuul(同时也是Eureka Client) 应用服务(同时也是Eureka Client)我们希望zuul和后端原创 2020-07-15 00:24:12 · 236 阅读 · 0 评论 -
Spring Cloud Zuul处理Cookie和重定向
由于我们在之前所有的入门教程中,对于HTTP请求都采用了简单的接口实现。而实际使用过程中,我们的HTTP请求要复杂的多,比如当我们将Spring Cloud Zuul作为API网关接入网站类应用时,往往都会碰到下面这两个非常常见的问题:会话无法保持 重定向后的HOST错误本文将帮助大家分析问题原因并给出解决这两个常见问题的方法。会话保持问题通过跟踪一个HTTP请求经过Zuul到具体服务,再到返回结果的全过程。我们很容易就能发现,在传递的过程中,HTTP请求头信息中的Cookie和Author原创 2020-07-15 00:04:44 · 586 阅读 · 0 评论 -
Spring Cloud Zuul中使用Swagger汇总API接口文档
有很多读者问过这样的一个问题:虽然使用Swagger可以为Spring MVC编写的接口生成了API文档,但是在微服务化之后,这些API文档都离散在各个微服务中,是否有办法将这些接口都整合到一个文档中?之前给大家的回复都只是简单的说了个思路,昨天正好又有人问起,索性就举个例子写成博文供大家参考吧。如果您还不了解Spring Cloud Zuul和Swagger,建议优先阅读下面两篇,有一个初步的了解:Spring Cloud构建微服务架构:服务网关(基础) Spring Boot中使用Swag.原创 2020-07-14 23:30:00 · 154 阅读 · 0 评论 -
Spring Cloud微服务架构:服务网关(过滤器)
过滤器的作用通过上面所述的两篇我们,我们已经能够实现请求的路由功能,所以我们的微服务应用提供的接口就可以通过统一的API网关入口被客户端访问到了。但是,每个客户端用户请求微服务应用提供的接口时,它们的访问权限往往都需要有一定的限制,系统并不会将所有的微服务接口都对它们开放。然而,目前的服务路由并没有限制权限这样的功能,所有请求都会被毫无保留地转发到具体的应用并返回结果,为了实现对客户端请求的安全校验和权限控制,最简单和粗暴的方法就是为每个微服务应用都实现一套用于校验签名和鉴别权限的过滤器或拦截器。不过,原创 2020-07-14 23:23:03 · 416 阅读 · 0 评论 -
Spring Cloud微服务架构:服务网关(路由配置)
上一节,我们通过使用Spring Cloud Zuul构建了一个基础的API网关服务,同时也演示了Spring Cloud Zuul基于服务的自动路由功能。在本文中,我们将进一步详细地介绍关于Spring Cloud Zuul的路由功能,以帮助读者可以更好的理解和使用它,以完成更复杂的路由配置。传统路由配置所谓的传统路由配置方式就是在不依赖于服务发现机制的情况下,通过在配置文件中具体指定每个路由表达式与服务实例的映射关系来实现API网关对外部请求的路由。没有Eureka和Consul的服务治理框原创 2020-07-14 23:20:29 · 494 阅读 · 0 评论 -
Spring Cloud微服务架构:服务网关(基础)
通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了。比如下图所示:我们使用Spring Cloud Netflix中的Eureka实现了服务注册中心以及服务注册与发现;而服务间通过Ribbon或Feign实现服务的消费以及均衡负载;通过Spring Cloud Config实现了应用多环境的外部化配置以及版本管理。为了使得服务集群更为健壮,使用Hystrix的融断机制来避免在微服务架构中个别服务出现异常时引起的故障蔓延。在该架构中,我们的原创 2020-07-14 23:15:56 · 200 阅读 · 0 评论 -
Spring Cloud Netflix 网关 Zuul 入门
1. 概述Zuul是由 Netflix 开源的微服务网关,提供都动态路由、监控、熔断、安全等等功能。Zuul is a gateway service that provides dynamic routing, monitoring, resiliency, security, and more.Spring Cloud Netflix Zuul将 Zuul 融入 Spring Cloud 生态体系,作为 Spring Cloud 微服务架构中的 API 网关。如下图所示:拓..原创 2020-07-13 01:14:45 · 610 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 网关管理 HTTP API
1. 概述本文主要分享网关管理 HTTP API。org.springframework.cloud.gateway.actuate.GatewayWebfluxEndpoint,提供管理网关的 HTTP API 。构造方法,代码如下:@RestController@RequestMapping("${management.context-path:/application}/gateway")public class GatewayWebfluxEndpoint implements .原创 2020-06-24 00:18:59 · 255 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.10) 之 RequestRateLimiterGatewayFilterFactory 请求限流
1. 概述本文主要分享RequestRateLimiterGatewayFilterFactory 的代码实现。在《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.2) 之 GatewayFilterFactory 过滤器工厂》一文中,我们看到 Spring Cloud Gateway 提供了多种 GatewayFilterFactory 的实现,而 RequestRateLimiterGatewayFilterFactory 也是其中的一种。通过 RequestR...原创 2020-06-24 00:15:10 · 3785 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.9) 之 HystrixGatewayFilterFactory 熔断
1. 概述本文主要分享HystrixGatewayFilterFactory 的代码实现。在《Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.2) 之 GatewayFilterFactory 过滤器工厂》一文中,我们看到 Spring Cloud Gateway 提供了多种 GatewayFilterFactory 的实现,而 HystrixGatewayFilterFactory 也是其中的一种。通过 HystrixGatewayFilterFactory ,可...原创 2020-06-24 00:03:15 · 2403 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.8) 之 WebClientHttpRoutingFilter
1. 概述本文主要分享WebClientHttpRoutingFilter 的代码实现。WebClientHttpRoutingFilter ,Http路由网关过滤器。其根据http://或https://前缀( Scheme )过滤处理,使用基于org.springframework.cloud.gateway.filter.WebClient实现的 HttpClient 请求后端 Http 服务。WebClientWriteResponseFilter ,与 WebClien...原创 2020-06-23 23:59:18 · 1831 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.7) 之 NettyRoutingFilter
1. 概述本文主要分享NettyRoutingFilter 的代码实现。NettyRoutingFilter ,Netty路由网关过滤器。其根据http://或https://前缀( Scheme )过滤处理,使用基于 Netty 实现的 HttpClient 请求后端 Http 服务。NettyWriteResponseFilter ,与 NettyRoutingFilter成对使用的网关过滤器。其将 NettyRoutingFilter 请求后端 Http 服务的响应写回客户端...原创 2020-06-23 23:55:26 · 3774 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.6) 之 WebSocketRoutingFilter
1. 概述本文主要分享WebsocketRoutingFilter 的代码实现。WebsocketRoutingFilter ,Websocket路由网关过滤器。其根据ws:///wss://前缀( Scheme )过滤处理,代理后端 Websocket 服务,提供给客户端连接。如下图 :目前一个RouteDefinition 只能指定一个后端 WebSocket 服务。官方正在计划在 LoadBalancerClientFilter 上实现 Websocket 的负载均衡功能...原创 2020-06-23 23:50:52 · 3119 阅读 · 2 评论 -
Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.5) 之 ForwardRoutingFilter
1. 概述本文主要分享ForwardRoutingFilter 的代码实现。RouteToRequestUrlFilter ,转发路由网关过滤器。其根据forward://前缀( Scheme )过滤处理,将请求转发到当前网关实例本地接口。举个例子,配置 RouteDefinition 路由定义如下 :spring: application: name: juejin-gateway cloud: gateway: routes: ...原创 2020-06-23 23:45:22 · 1884 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.4) 之 LoadBalancerClientFilter 负载均衡
1. 概述本文主要分享LoadBalancerClientFilter 的代码实现。LoadBalancerClientFilter 根据lb://前缀过滤处理,使用serviceId选择一个服务实例,从而实现负载均衡。2. 环境搭建在《Spring-Cloud-Gateway 源码解析 —— 路由(1.4)之 DiscoveryClientRouteDefinitionLocator 注册中心》「2. 环境搭建」有详细教程。3. LoadBalancerClientFil...原创 2020-06-23 23:42:40 · 2106 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.3) 之 RouteToRequestUrlFilter
1. 概述本文主要分享RouteToRequestUrlFilter 的代码实现。RouteToRequestUrlFilter 根据匹配的 Route ,计算请求的地址。注意,这里的地址指的是 URL ,而不是 URI。???? RouteToRequestUrlFilter 的代码十分少,所以这会是一篇简单的文章。2. RouteToRequestUrlFilterorg.springframework.cloud.gateway.filter.RouteToRequestUrlFi原创 2020-06-23 23:40:35 · 2023 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.2) 之 GatewayFilterFactory 过滤器工厂
1. 概述本文主要分享GatewayFilterFactory 的实现类。GatewayFilterFactory 实现类较多,根据用途整理如下脑图 :下面我们开始逐块解析源码实现。2. Header本小节分享 Header 相关的 GatewayFilterFactory 实现类。2.1 AddRequestHeaderGatewayFilterFactory用途 :添加指定请求 Header 为指定值。 配置 : spring: cloud: g.原创 2020-06-23 23:38:50 · 747 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.1) 之 GatewayFilter 一览
1. 概述本文主要对过滤器 GatewayFilter 做整体的认识。过滤器整体类图如下 :是不是有点疑惑 GlobalFilter 与 GatewayFilter 的关系 ?且见本文分晓。2. GatewyFilterorg.springframework.cloud.gateway.filter.GatewayFilter,网关过滤器接口,代码如下 :public interface GatewayFilter { /** * Process the Web r..原创 2020-06-23 23:33:30 · 922 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 处理器 (3.3) 之 FilteringWebHandler 创建过滤器链
1. 概述本文主要分享FilteringWebHandler。在《Spring-Cloud-Gateway 源码解析 —— 处理器 (3.2) 之 RoutePredicateHandlerMapping 路由匹配 》「2.1 SimpleHandlerAdapter」里,我们看到SimpleHandlerAdapter#handle(ServerWebExchange, Object)调用FilteringWebHandler#handle(ServerWebExchange)方法,...原创 2020-06-23 23:29:33 · 1100 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 处理器 (3.2) 之 RoutePredicateHandlerMapping 路由匹配
1. 概述本文主要分享RoutePredicateHandlerMapping 路由匹配。我们先一起来看看,一个请求是怎么被 Spring Cloud Gateway 处理的,如下图 :org.springframework.web.reactive.DispatcherHandler:接收到请求,匹配 HandlerMapping ,此处会匹配到 RoutePredicateHandlerMapping 。 org.springframework.cloud.gateway.hand..原创 2020-06-23 23:27:48 · 1980 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 处理器 (3.1) 之 RoutePredicateFactory 路由谓语工厂
1. 概述本文主要分享RoutePredicateFactory 路由谓语工厂。RoutePredicateFactory 涉及到的类在org.springframework.cloud.gateway.handler.predicate包下,如下图 :Spring Cloud Gateway 创建 Route 对象时,使用 RoutePredicateFactory 创建 Predicate 对象。Predicate 对象可以赋值给Route.predicate属性,用于匹配请求...原创 2020-06-22 23:58:38 · 803 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 路由(2.4)之 Kotlin 自定义 RouteLocator
1. 概述本文主要分享如何使用 Kotlin 实现自定义 RouteLocator。???? 由于笔者暂时不了解 Kotlin ,也比较懒,暂时不准备了解 Kotlin ,所以本文很大可能性是"一本正经的胡说八道"。2. RouteLocatorDslorg.springframework.cloud.gateway.route.RouteLocatorDsl,使用 Kotlin 实现自定义 RouteLocator 。我们先打开GatewayDsl.kt,大体浏览一下。下面我们来看..原创 2020-06-22 23:56:19 · 355 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 路由(2.3)之 Java 自定义 RouteLocator
1. 概述本文主要分享如何使用 Java 实现自定义 RouteLocator。ps :为什么这里强调 Java 呢?可以使用 Kotlin 实现自定义 RouteLocator ,在下一篇文章我们会详细分享。首先我们来看一段示例程序,代码如下 :import static org.springframework.cloud.gateway.filter.factory.GatewayFilters.addResponseHeader;import static org.springfr原创 2020-06-22 23:54:51 · 1227 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 路由(2.2)之 RouteDefinitionRouteLocator 路由配置
1. 概述本文主要分享RouteDefinitionRouteLocator 的源码实现。蓝色部分 :RouteDefinitionRouteLocator 。2. RouteDefinitionRouteLocatororg.springframework.cloud.gateway.route.RouteDefinitionRouteLocator,基于RouteDefinitionLocator的 RouteLocator实现类。RouteDefinitionRoute...原创 2020-06-22 23:53:02 · 3192 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 路由(2.1)之 RouteLocator 一览
1. 概述本文主要对路由定位器 RouteLocator 做整体的认识。在《Spring-Cloud-Gateway 源码解析 —— 路由(1.1)之 RouteDefinitionLocator 一览》中,我们对 RouteLocator 对了简单的介绍 : RouteLocator 可以直接自定义路由(org.springframework.cloud.gateway.route.Route) ,也可以通过 RouteDefinitionRouteLocator 获取 Route...原创 2020-06-22 23:50:40 · 955 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 路由(1.4)之 DiscoveryClientRouteDefinitionLocator 注册中心
1. 概述本文主要对DiscoveryClientRouteDefinitionLocator 的源码实现。DiscoveryClientRouteDefinitionLocator 通过调用org.springframework.cloud.client.discovery.DiscoveryClient获取注册在注册中心的服务列表,生成对应的 RouteDefinition 数组。2. 环境搭建在解析源码之前,我们先以 Eureka 为注册中心,讲解下如何配置 DiscoveryC...原创 2020-06-22 23:47:09 · 1419 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 路由(1.3)之 RouteDefinitionRepository 存储器
1. 概述本文主要对RouteDefinitionRepository 的源码实现。蓝色部分 :RouteDefinitionRepository 。本文涉及到的类图如下 :下面我们来逐个类进行解析。2. RouteDefinitionWriterorg.springframework.cloud.gateway.route.RouteDefinitionWriter,路由配置写入接口。该接口定义了保存与删除两个方法,代码如下 :public interface ...原创 2020-06-22 23:44:23 · 6272 阅读 · 3 评论 -
Spring Cloud Netflix 网关 Zuul 入门
1. 概述Zuul是由 Netflix 开源的微服务网关,提供都动态路由、监控、熔断、安全等等功能。Zuul is a gateway service that provides dynamic routing, monitoring, resiliency, security, and more.Spring Cloud Netflix Zuul将 Zuul 融入 Spring Cloud 生态体系,作为 Spring Cloud 微服务架构中的 API 网关。如下图所示:拓..原创 2020-06-22 07:09:34 · 573 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 路由(1.2)之 PropertiesRouteDefinitionLocator 配置文件
1. 概述本文主要对PropertiesRouteDefinitionLocator 的源码实现。蓝色部分 :PropertiesRouteDefinitionLocator 。2. PropertiesRouteDefinitionLocatororg.springframework.cloud.gateway.config.PropertiesRouteDefinitionLocator,从配置文件( 例如,YML / Properties 等 ) 读取路由配置。代码如下 :..原创 2020-06-21 20:52:34 · 1583 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 路由(1.1)之 RouteDefinitionLocator 一览
1. 概述本文主要对路由定义定位器 RouteDefinitionLocator 做整体的认识。在《Spring-Cloud-Gateway 源码解析 —— 网关初始化》中,我们看到路由相关的组件 RouteDefinitionLocator / RouteLocator 的初始化。涉及到的类比较多,我们用下图重新梳理下 :RouteDefinitionLocator负责读取路由配置(org.springframework.cloud.gateway.route.RouteDefi...原创 2020-06-21 20:49:08 · 970 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 网关初始化
1. 概述本文主要分享Spring Cloud Gateway 启动初始化的过程。在初始化的过程中,涉及到的组件会较多,本文不会细说,留到后面每篇文章针对每个组件详细述说。那么这有什么意义呢?先对 Spring Cloud Gateway 内部的组件有整体的印象。在官方提供的实例项目spring-cloud-gateway-sample,我们看到 GatewaySampleApplication 上有@EnableAutoConfiguration注解。因为该项目导入了sprin...原创 2020-06-21 20:30:36 · 938 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 调试环境搭建
1. 依赖工具Maven (>= 3.3.3) JDK IntelliJ IDEA2. 源码拉取从官方仓库https://github.com/spring-cloud/spring-cloud-gateway.gitFork出属于自己的仓库。为什么要Fork?既然开始阅读、调试源码,我们可能会写一些注释,有了自己的仓库,可以进行自由的提交。????使用IntelliJ IDEA从Fork出来的仓库拉取代码。如果master分支处于1.x版本,请使用In...原创 2020-06-21 20:24:50 · 879 阅读 · 0 评论 -
Spring-Cloud-Gateway 源码解析 —— 核心组件构建原理
引言在当下学习和使用 spring cloud 技术栈的热潮中,网关已经成了不可或缺的内容。开发者在选择用来解决特定领域内问题的框架时,多了解几款相关同类产品可加大选择余地。除了 Netflix 的 zuul 之外,spring cloud gateway 可作为开发者的另一个选择。Zuul 分 1.x 和 2.x 版本。Zuul 2.x 版本和 spring cloud gateway 都使用 Non-Blocking I/O 模型。本文主要从源码上介绍 spring cloud gate原创 2020-06-21 20:43:12 · 716 阅读 · 0 评论 -
Spring Cloud 网关 Spring Cloud Gateway 入门
1. 概述Spring Cloud Gateway是由WebFlux+Netty+Reactor实现的响应式的 API 网关。Spring Cloud Gateway 旨在为微服务架构提供一种简单且有效的 API 路由的管理方式,并基于 Filter 的方式提供网关的基本功能,例如说安全认证、监控、限流等等。Spring Cloud Gateway 定位于取代 NetflixZuul,成为 Spring Cloud 生态系统的新一代网关。目前看下来非常成功,老的项目的网关逐步从 ...原创 2020-06-21 19:41:49 · 2120 阅读 · 0 评论