TIPS
本文基于Spring Cloud Greenwich SR2,理论兼容Spring Cloud所有版本。
加依赖:
1 | <dependency> |
注意, logstash-logback-encoder
的版本务必和Logback兼容,否则会导致应用启动不起来,而且不会打印任何日志!可前往 https://github.com/logstash/logstash-logback-encoder
查看和Logback的兼容性。
在 resources
目录下创建配置文件:logback-spring.xml
,内容如下:
1 | <?xml version="1.0" encoding="UTF-8"?> |
新建 bootstrap.yml
,并将application.yml
中的以下属性移到bootstrap.yml
中。
1 | spring: |
由于上面的 logback-spring.xml
含有变量(例如 springAppName
),故而 spring.application.name
属性必须设置在 bootstrap.yml
文件中,否则,logback-spring.xml
将无法正确读取属性。
启动应用
日志会打印到 /Users/reno/Desktop/未命名文件夹/elk/logs/目录中
,并且文件名称为 user-center.json
,内容类似如下:
1 | {"@timestamp":"2019-08-29T02:38:42.468Z","severity":"DEBUG","service":"microservice-provider-user","trace":"5cf9479e966fb5ec","span":"5cf9479e966fb5ec","parent":"","exportable":"false","pid":"13144","thread":"http-nio-8000-exec-1","class":"o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor","rest":"Using 'application/json;q=0.8', given [text/html, application/xhtml+xml, image/webp, image/apng, application/signed-exchange;v=b3, application/xml;q=0.9, */*;q=0.8] and supported [application/json, application/*+json, application/json, application/*+json]"} |
下面,只需要让Logstash收集到这个JSON文件,就可以在Kibana上检索日志啦!
简单起见,本文使用Docker搭建ELK;其他搭建方式,请看官自行百度,比较简单,但很耗时。
创建 docker-compose.yml
文件,内容如下:
1 | version: '3' |
需要注意,上面的 /Users/reno/Desktop/未命名文件夹/elk/logs/
需要改成你应用的打印路径。
在docker-compose.yml文件所在目录创建 config/logstash.conf
,内容如下:
1 | input { |
启动ELK
1 | docker-compose up |
访问你微服务的API,让它生成一些日志(如果产生日志比较少,可将 org.springframework
包的日志级别设为 debug
)
访问 http://localhost:5601
(Kibana地址),可看到类似如下的界面,按照如图配置Kibana。
输入条件,即可分析日志:
原理比较简单:
TIPS
本文基于SonarQube 7.9.1,理论支持6.0及更高版本。
SonarQube是一个开源的代码质量管理系统,可用来快速定位代码中的Bug、漏洞以及不优雅的代码。它支持几乎所有的常见编程语言,例如Java、JavaScript、TypeScript、Kotlin、Ruby、Go, Scala等。并且还有插件机制,利用插件,可以让SonarQube更加强大,例如可以整合Findbugs、PMD、Checkstyle等。可以说,SonarQube是一款提升项目代码质量必备的根据。
本文手把手搭建、使用SonarQube。
前往 https://www.sonarqube.org/downloads/
,按照如图说明下载即可。建议下载 LTS
版本,以便获得长期的维护与支持。
其他需求详见:https://docs.sonarqube.org/7.9/requirements/requirements/
TIPS
- 《其他需求》建议大家参照一下,里面探讨如何修改Linux文件描述符限制等说明;
- 上面贴的是是7.9版的链接,如果你使用的是其他版本,只需将版本名称改掉即可,例如改为7.8即可查看7.8.x的需求。
解压压缩包
将目录切换到SonarQube的 /bin
目录,可看到类似如下的目录结构:
1 | ├── bin |
根据你的操作系统,切换到响应目录。例如,您的机器是macOS
,则可切换到 macosx-universal-64
目录。
执行如下命令即可启动SonarQube。
1 | ./sonar.sh start |
当然,该shell还有其他命令,可输入 ./sonar.sh --help
或者 ./sonar.sh
查阅。
稍等片刻,访问 http://localhost:9000/
即可看到类似如下的界面,说明安装成功。
./sonar.sh stop
即可。./sonar.sh restart
即可。访问:http://localhost:9000
账号:admin
密码:admin
默认情况下,SonarQube使用的是H2数据库,这是一款非常流行的嵌入式数据库。但生产环境中,SonarQube并不建议使用H2。SonarQube支持多种数据库,例如Qracle、PostgreSQL、SQL Server等。下面,我们以PostgreSQL为例,让SonarQube使用PostgreSQL存储数据。
TIPS
支持的数据库及数据库版本请前往这篇文档查看,避免SonarQube不支持你的数据库版本以及注意点。
https://docs.sonarqube.org/7.9/requirements/requirements/
举个例子:SonarQube 7.9要求使用PostgreSQL 9.3-9.6或者PostgreSQL 10,并且必须配置使用UTF-8
简单起见,我用Docker搭建PostgreSQL。
1 | version: '3.1' |
修改配置文件:$SONARQUBE_HOME/conf/sonar.properties
。
找到类似如下的内容:
1 | #----- PostgreSQL 9.3 or greater |
在这行下面,添加如下内容:
1 | sonar.jdbc.url=jdbc:postgresql://localhost/sonar?currentSchema=public |
这里,数据库地址、账号、密码根据你的需求修改。
执行 ./sonar.sh restart
,重启SonarQube。观察PostgreSQL,可以发现,此时SonarQube会自动在PostgreSQL数据库中建表并插入初始化数据。
类似的方式,你也可以为你的SonarQube配置其他数据库。
在Maven的全局配置文件: $MAVEN_PATH/conf/settings.xml
(也可能是.m2/settings.xml
看你是怎么配置Maven的)中添加如下内容:
1 | <profile> |
到Maven项目的根目录执行如下命令,即可使用SonarQube分析项目:
1 | mvn sonar:sonar -Dsonar.java.binaries=target/sonar |
等待片刻后,项目构建成功:
1 | [INFO] Spring Cloud YES ................................... SUCCESS [ 12.431 s] |
此时,再次访问 http://localhost:9000
,即可看到类似如下的界面:
如右上角所示,此时可以看到SonarQube已经为我们分析了一个项目,该项目有1个Bug、2个脆弱点、31个代码味道问题。点击项目名称(图中的 Spring Cloud YES
)即可看到详情,可以根据SonarQube给我们的提示进行修正、重构。
右上角头像 - My Account - Security页中,在 Generate New Token
中填入你的Token名称,并点击Generate
按钮。
点击按钮后,将会看到生成的Token,例如 62b615f477557f98bc60b396c2b4ca2793afbdea
使用如下命令,即可使用Sonar分析项目。
1 | mvn sonar:sonar \ |
SonarQube有一个强大的插件机制。以安装汉化插件为例——
按照图示进行操作:
点击 Install
按钮后,将会弹出重启SonarQube的提示,点击即可重启。重启后,可看到类似如下的界面
类似的方式,也可为SonarQube安装其他插件。
TIPS
https://t.itmuch.com/doc.html 是个人在慕课网视频《 面向未来微服务:Spring Cloud Alibaba从入门到进阶 》的实战项目配套文档。
/v2/api-docs
swagger2markup-maven-plugin
,将 /v2/api-docs
生成ASCIIDOC文件;asciidoctor-maven-plugin
,将ASCIIDOC文件转换成HTML;TIPS
Swagger的使用非常简单,本文不展开探讨了,各位看官自行百度一下用法吧。
常用注解:
- @Api
- @ApiOperation
- @ApiModel
- @ApiModelProperty
加依赖
1 | <!-- swagger --> |
配置Swagger(按照自己的需要配置,下面的配置代码仅供参考)
1 | /** |
为接口Swagger注解
1 |
|
/v2/api-docs
端点,描述了你的API的信息。在pom.xml中添加如下内容:
1 | <build> |
swagger2markup-maven-plugin
插件的作用是读取 http://localhost:8080/v2/api-docs
的信息,生成ASCIIDOC文档。当然你也可以生成其他格式,比如Markdown等等。
这款插件还有很多使用姿势,详见 https://github.com/Swagger2Markup/swagger2markup-maven-plugin
下面,只需要将ASCIIDOC转换成html就OK了,在pom.xml中添加如下内容:
1 | <build> |
asciidoctor-maven-plugin
插件同样也有很多姿势,详见:https://github.com/asciidoctor/asciidoctor-maven-plugin
生成的文件在 src/docs/asciidoc/html
(看你插件上面的配置哈),然后你就可以弄个NGINX部署了。
mvn swagger2markup:convertSwagger2markup
生成ASCIIDOCmvn asciidoctor:process-asciidoc
生成htmlTIPS
Spring Cloud Greenwich SR1
1 | <dependency> |
1 | spring: |
只要你的API被调用,应用就会疯狂报类似如下的异常。
1 | 2019-08-24 23:10:25.330 ERROR [user-center,,,] 48628 --- [.naming.updater] com.alibaba.nacos.client.naming : [NA] failed to update serviceName: DEFAULT_GROUP@@localhost |
原因:
Spring Cloud把 http://localhost:9411/
当作了服务发现组件里面的服务名称;于是,Nacos Client尝试从Nacos Server寻找一个名为 localhost:9411
的服务…这个服务根本不存在啊,于是就疯狂报异常(因为Nacos Client本地定时任务,刷新本地服务发现缓存)
知道原因之后,要想解决很简单:
http://localhost:9411/
,当成一个URL,而不要当做服务名。Zipkin Server
官方并不支持注册到服务发现组件!!!!在 https://github.com/openzipkin/zipkin/issues/2540
里面,官方人员解答得很清楚了:
@nkorange thank you for reaching out. We have had several users ask about service discovery with Zipkin Server over the years (see #1870) and less ask about dynamic/external configuration. We don’t currently support any service discovery as a first-class feature. There is a workaround to use Eureka mentioned in #1870. So unless a user is using that, or is building a custom Zipkin Server (which we don’t officially support), there should be no service discovery.
If you want to come chat with us on Gitter (https://gitter.im/openzipkin/zipkin) about next steps, please do.
详见 We don't currently support any service discovery as a first-class feature.
如果你想要注册到服务发现组件,那么可以参考 https://github.com/openzipkin/zipkin/issues/1870
说明自己改造Zipkin Server让其注册到服务发现组件,但这样做不会得到任何官方的技术支持!!
所以,将Zipkin Server注册到Nacos或者其他服务发现组件,不是最优解。我们的解决方案就演变成了:让Spring Cloud 正确识别
http://localhost:9411/
,当成一个URL,而不要当做服务名。这一种解决方案。
1 | spring: |
从这个配置的注释( 代码见 org.springframework.cloud.sleuth.zipkin2.ZipkinProperties#discoveryClientEnabled
)来看,只要设置成false,那么就会把 http://localhost:9411/
当成一个URL,而不是服务名称了。
你以为已经牛逼了,然而当你去测试的时候,发现 然并卵
,一点效果都没有。
问题代码在这里:org.springframework.cloud.sleuth.zipkin2.sender.ZipkinRestTemplateSenderConfiguration.DiscoveryClientZipkinUrlExtractorConfiguration.ZipkinClientNoOpConfiguration
,里面是这么玩的:
1 |
|
当你看到这个代码的时候,就应该知道解决方案啦!那就是你得把配置修改为:
1 | spring: |
就可以了!
这其实是Spring Cloud Sleuth子项目 spring-cloud-sleuth-zipkin
的一个Bug!
https://github.com/spring-cloud/spring-cloud-sleuth/issues/1376
https://github.com/spring-cloud/spring-cloud-sleuth/pull/1379
,代码已经合并了,在 Spring Cloud Greenwich SR3
版本中会修正!简单总结一下:
spring.zipkin.discoveryClientEnabled = false
,否则配置不生效!!discovery-client-enabled
或者 discoveryClientEnabled
。我暂时没有找到Spring Cloud这样做的意图。我的猜想:是因为早期Spring Cloud是使用自己编写代码实现Zipkin Server的(从Finchley开始,改成了直接用Zipkin官方现成的jar包启动),这种方式可以注册到你想要的服务发现组件上(因为本质上,Zipkin Server就是个基于Spring Boot的应用嘛)。
个人觉得Spring Cloud这部分的设计不太优雅,如果让我来设计的话,我应该会这么设计:
URL模式:
1 | spring: |
服务名称的模式:
1 | spring: |
这样带来的好处:
http://
、 lb://
)就可以区分出是具体URL还是微服务名称了,无需配置 discoveryClientEnabled
lb://
协议和Spring Cloud Gateway形成了呼应,学习成本也比较低,使用体验更加一致不过工作比较忙,只有创意,暂时没有时间提交PR…哈哈,所以…吐槽完还是得继续忍着啊…
]]>TIPS
TIPS
如下命令可下载最新版本。
1 | curl -sSL https://zipkin.io/quickstart.sh | bash -s |
下载下来的文件名为 zipin.jar
TIPS
如下地址可下载最新版本。
访问如下地址即可:
1 | https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec |
下载下来的文件名为 zipkin-server-2.12.9-exec.jar
提供2.12.9版本。
1 | 链接:https://pan.baidu.com/s/1HXjzNDpzin6fXGrZPyQeWQ 密码:aon2 |
使用如下命令,即可启动Zipkin Server
1 | java -jar 你的jar包 |
访问http://localhost:9411
即可看到Zipkin Server的首页。
JWT
的工具类。基于 jjwt
库,这是一个Java圈子最流行的 JWT
操作库。
TIPS
jjwt
GitHub:https://github.com/jwtk/jjwt- 本工具类来自个人开源的认证、授权框架 Light Security
加依赖
1 | <dependency> |
工具类:
1 | 4j |
写配置
1 | jwt: |
使用:
1 |
|
RequestRateLimiterGatewayFilterFactory
提供限流的能力,基于令牌桶算法实现。目前,它内置的 RedisRateLimiter
,依赖Redis存储限流配置,以及统计数据。当然你也可以实现自己的RateLimiter,只需实现 org.springframework.cloud.gateway.filter.ratelimit.RateLimiter
接口,或者继承 org.springframework.cloud.gateway.filter.ratelimit.AbstractRateLimiter
。
漏桶算法:
想象有一个水桶,水桶以一定的速度出水(以一定速率消费请求),当水流速度过大水会溢出(访问速率超过响应速率,就直接拒绝)。
漏桶算法的两个变量:
- 水桶漏洞的大小:rate
- 最多可以存多少的水:burst
令牌桶算法:
系统按照恒定间隔向水桶里加入令牌(Token),如果桶满了的话,就不加了。每个请求来的时候,会拿走1个令牌,如果没有令牌可拿,那么就拒绝服务。
TIPS
- Redis Rate Limiter的实现基于这篇文章: Stripe
- Spring官方引用的令牌桶算法文章: Token Bucket Algorithm ,有兴趣可以看看。
加依赖:
1 | <dependency> |
写配置:
1 | spring: |
写代码:按照X限流,就写一个针对X的KeyResolver。
1 |
|
这样,限流规则即可作用在路径上。
1 | 例如: |
持续高速访问某个路径,速度过快时,返回 HTTP ERROR 429
。
你也可以实现针对用户的限流:
1 |
|
针对来源IP的限流:
1 |
|
借助Actuator的监控端点,可分析全局过滤器、过滤器工厂、路由详情。详见:Spring Cloud Gateway监控
加日志,按需将如下包的日志级别设置成 debug
或 trace
,总有一款对你有用。
org.springframework.cloud.gateway
org.springframework.http.server.reactive
org.springframework.web.reactive
org.springframework.boot.autoconfigure.web
reactor.netty
redisratelimiter
配置示例:
1 | logging: |
Reactor Netty HttpClient
以及 HttpServer
可启用 Wiretap
。将reactor.netty
包设置成 debug
或 trace
,然后设置如下属性:
spring.cloud.gateway.httpserver.wiretap=true
spring.cloud.gateway.httpclient.wiretap=true
分别开启HttpServer及HttpClient的Wiretap。
然后,就可以分析日志啦。
]]>TIPS
- 相关Issue: https://github.com/spring-cloud/spring-cloud-gateway/issues/1194
- wiretap其实是Reactor Netty的概念,作用是,打印对端之间的流量详情,相关文档:
只要为Spring Cloud Gateway添加Spring Boot Actuator( spring-boot-starter-actuator
)的依赖,并将 gateway
端点暴露,即可获得若干监控端点,监控 & 操作Spring Cloud Gateway的方方面面。
1 | management: |
监控端点一览表:
TIPS
以下所有端点都挂在/actuator/gateway/
下面。
例如:routes
的全路径是/actuator/gateway/routes
,以此类推。
ID | HTTP Method | Description |
---|---|---|
globalfilters |
GET | 展示所有的全局过滤器 |
routefilters |
GET | 展示所有的过滤器工厂(GatewayFilter factories) |
refresh |
POST【无消息体】 | 清空路由缓存 |
routes |
GET | 展示路由列表 |
routes/{id} |
GET | 展示指定id的路由的信息 |
routes/{id} |
POST【消息体如下】 | 新增一个路由 |
routes/{id} |
DELETE【无消息体】 | 删除一个路由 |
其中,要想动态添加路由配置,只需发送POST请求,消息体如下:
1 | { |
TIPS
技巧:消息体其实是有规律的,你可以先在配置文件中配置一个路由规则,然后访问
${GATEWAY_URL}/actuator/gateway/routes
端点,每个路由id的对应段落,就是你的消息体啦。
如使用 POSTMAN
测试,可配置如下:
操作完成后,可再次访问 ${GATEWAY_URL}/actuator/gateway/routes
端点,可以看到,新的路由已被动态添加了。
]]>TIPS
如果没有实时生效,使用refresh端点刷新一下路由信息即可。
TIPS
本文基于Spring Cloud Gateway SR2,理论适配Spring Cloud Gateway SR1以及更高版本。
本文详细探讨Spring Cloud Gateway内置的全局过滤器。包括:
1 Combined Global Filter and GatewayFilter Ordering
2 Forward Routing Filter
3 LoadBalancerClient Filter
4 Netty Routing Filter
5 Netty Write Response Filter
6 RouteToRequestUrl Filter
7 Websocket Routing Filter
8 Gateway Metrics Filter
9 Marking An Exchange As Routed
GlobalFilter
接口和 GatewayFilter
有一样的接口定义,只不过, GlobalFilter
会作用于所有路由。
TIPS
官方声明:GlobalFilter的接口定义以及用法在未来的版本可能会发生变化。
个人判断:GlobalFilter可用于生产;如果有自定义GlobalFilter的需求,理论上也可放心使用——未来即使接口定义以及使用方式发生变化,应该也是平滑过渡的(比如Zuul的Fallback,原先叫ZuulFallbackProvider,后来改叫FallbackProvider,中间就有段时间新旧使用方式都支持,后面才逐步废弃老的使用方式)。
当请求到来时,Filtering Web Handler
处理器会添加所有 GlobalFilter
实例和匹配的 GatewayFilter
实例到过滤器链中。
过滤器链会使用 org.springframework.core.Ordered
注解所指定的顺序,进行排序。Spring Cloud Gateway区分了过滤器逻辑执行的”pre”和”post”阶段,所以优先级高的过滤器将会在pre阶段最先执行,优先级最低的过滤器则在post阶段最后执行。
TIPS
数值越小越靠前执行,记得这一点就OK了。
示例代码:
1 |
|
执行结果:
1 | first pre filter |
ForwardRoutingFilter
会查看exchange的属性 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
的值(一个URI),如果该值l的scheme是 forward
,比如:forward://localendpoint
,则它会使用Spirng的DispatcherHandler
处理该请求。请求URL的路径部分,会被forward URL中的路径覆盖。未修改的原始URL,会被追加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
属性中。
TIPS
这段文档太学术了,讲解了
LoadBalancerClientFilter
的实现原理,对使用者来说,意义不大;对使用者来说,只要知道这个Filter是用来做本地forward就OK了。建议:如对原理感兴趣的,建议直接研究源码,源码比官方文档好理解。
LoadBalancerClientFilter
会查看exchange的属性 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
的值(一个URI),如果该值的scheme是 lb
,比如:lb://myservice
,它将会使用Spring Cloud的LoadBalancerClient
来将 myservice
解析成实际的host和port,并替换掉 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
的内容。原始地址会追加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
中。该过滤器还会查看 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
属性,如果发现该属性的值是 lb
,也会执行相同逻辑。
示例:
1 | spring: |
默认情况下,如果无法在
LoadBalancer
找到指定服务的实例,那么会返回503(对应如上的例子,找不到service实例,就返回503);可使用spring.cloud.gateway.loadbalancer.use404=true
让其返回404。
LoadBalancer
返回的ServiceInstance
的isSecure
的值,会覆盖请求的scheme。举个例子,如果请求打到Gateway上使用的是HTTPS
,但ServiceInstance
的isSecure
是false,那么下游收到的则是HTTP请求,反之亦然。然而,如果该路由指定了GATEWAY_SCHEME_PREFIX_ATTR
属性,那么前缀将会被剥离,并且路由URL中的scheme会覆盖ServiceInstance
的配置
TIPS
这段文档太学术了,讲解了
LoadBalancerClientFilter
的实现原理,对使用者来说,意义不大;对使用者来说,其实只要知道这个Filter是用来整合Ribbon的就OK了。建议:如对原理感兴趣的,建议直接研究源码,源码比官方文档好理解。
如果 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
的值的scheme是 http
或 https
,则运行Netty Routing Filter 。它使用Netty HttpClient
向下游发送代理请求。获得的响应将放在exchange的 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR
属性中,以便在后面的filter中使用。(有一个实验性的过滤器: WebClientHttpRoutingFilter
可实现相同功能,但无需Netty)
如果exchange中的 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR
属性中有 HttpClientResponse
,则运行 NettyWriteResponseFilter
。该过滤器在所有其他过滤器执行完成后执行,并将代理响应协会网关的客户端侧。(有一个实验性的过滤器: WebClientWriteResponseFilter
可实现相同功能,但无需Netty)
如果exchange中的 ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR
属性中有一个 Route
对象,则运行 RouteToRequestUrlFilter
。它根据请求URI创建一个新URI,但会使用该 Route
对象的URI属性进行更新。新URI放到exchange的 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
属性中。
如果URI具有scheme前缀,例如 lb:ws://serviceid
,该 lb
scheme将从URI中剥离,并放到 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
中,方便后面的过滤器使用。
如果exchange中的 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
属性的值的scheme是 ws
或者 wss
,则运行Websocket Routing Filter。它底层使用Spring Web Socket将Websocket请求转发到下游。
可为URI添加 lb
前缀实现负载均衡,例如 lb:ws://serviceid
。
如果你使用 SockJS 所谓普通http的后备,则应配置正常的HTTP路由以及Websocket路由。
1 | spring: |
要启用Gateway Metrics,需添加 spring-boot-starter-actuator
依赖。然后,只要spring.cloud.gateway.metrics.enabled
的值不是false,就会运行Gateway Metrics Filter。此过滤器添加名为 gateway.requests
的时序度量(timer metric),其中包含以下标记:
routeId
:路由IDrouteUri
:API将路由到的URIoutcome
:由 HttpStatus.Series 分类status
:返回给客户端的Http StatushttpStatusCode
:返回给客户端的请求的Http StatushttpMethod
:请求所使用的Http方法这些指标暴露在 /actuator/metrics/gateway.requests
端点中,并且可以轻松与Prometheus整合,从而创建一个 Grafana dashboard 。
TIPS
Prometheus是一款监控工具,Grafana是一款监控可视化工具;Spring Boot Actuator可与这两款工具进行整合。关于整合,笔者写过手把手的博客,有兴趣可以看一下:
在网关路由 ServerWebExchange
后,它将通过在exchange添加一个 gatewayAlreadyRouted
属性,从而将exchange标记为 routed
。一旦请求被标记为 routed
,其他路由过滤器将不会再次路由请求,而是直接跳过。您可以使用便捷方法将exchange标记为 routed
,或检查exchange是否是 routed
。
ServerWebExchangeUtils.isAlreadyRouted
检查是否已被路由ServerWebExchangeUtils.setAlreadyRouted
设置routed状态TIPS
简单来说,就是网关通过
gatewayAlreadyRouted
属性表示这个请求已经转发过了,而无需其他过滤器重复路由。从而防止重复的路由操作。
TIPS
本文基于 Spring Cloud Greenwich SR2
,理论支持 Spring Cloud Greenwich SR1
,其中的新特性标注出来了。
这一节来探讨Spring Cloud Gateway内置的Filter工厂。包括:
1 AddRequestHeader GatewayFilter Factory
2 AddRequestParameter GatewayFilter Factory
3 AddResponseHeader GatewayFilter Factory
4 DedupeResponseHeader GatewayFilter Factory
5 Hystrix GatewayFilter Factory
6 FallbackHeaders GatewayFilter Factory
7 PrefixPath GatewayFilter Factory
8 PreserveHostHeader GatewayFilter Factory
9 RequestRateLimiter GatewayFilter Factory
10 RedirectTo GatewayFilter Factory
11 RemoveHopByHopHeadersFilter GatewayFilter Factory
12 RemoveRequestHeader GatewayFilter Factory
13 RemoveResponseHeader GatewayFilter Factory
14 RewritePath GatewayFilter Factory
15 RewriteResponseHeader GatewayFilter Factory
16 SaveSession GatewayFilter Factory
17 SecureHeaders GatewayFilter Factory
18 SetPath GatewayFilter Factory
19 SetResponseHeader GatewayFilter Factory
20 SetStatus GatewayFilter Factory
21 StripPrefix GatewayFilter Factory
22 Retry GatewayFilter Factory
23 RequestSize GatewayFilter Factory
24 Modify Request Body GatewayFilter Factory
25 Modify Response Body GatewayFilter Factory
26 Default Filters
断点打在 org.springframework.cloud.gateway.filter.NettyRoutingFilter#filter
,就可以调试Gateway转发的具体细节了。
添加如下配置,可观察到一些请求细节:
1 | logging: |
1 | spring: |
为原始请求添加名为 X-Request-Foo
,值为 Bar
的请求头。
1 | spring: |
为原始请求添加请求参数 foo=bar
1 | spring: |
添加名为 X-Request-Foo
,值为 Bar
的响应头。
TIPS
Spring Cloud Greenwich SR2提供的新特性,低于这个版本无法使用。
强烈建议阅读一下类org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory上的注释,比官方文档写得还好。
1 | spring: |
剔除重复的响应头。
举个例子:
我们在Gateway以及微服务上都设置了CORS(解决跨域)header,如果不做任何配置,请求 -> 网关 -> 微服务,获得的响应就是这样的:
1 | Access-Control-Allow-Credentials: true, true |
也就是Header重复了。要想把这两个Header去重,只需设置成如下即可。
1 | filters: |
也就是说,想要去重的Header如果有多个,用空格分隔即可;
去重策略:
1 | RETAIN_FIRST: 默认值,保留第一个值 |
TIPS
Hystrix是Spring Cloud第一代中的容错组件,不过已经进入维护模式(相关文章:Spring Cloud Netflix项目进入维护模式之我见 ),未来,Hystrix会被Spring Cloud移除掉,取而代之的是Alibaba Sentinel/Resilience4J。
所以本文不做详细探讨了,但Gateway整合Hystrix其实包含了很多姿势。请感兴趣的同学自行前往官方文档了解详情:
https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#hystrix
。
1 | spring: |
TIPS
也是对Hystrix的支持,不做详细探讨了,请感兴趣的同学自行前往官方文档了解详情:
https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#fallback-headers
1 | spring: |
1 | spring: |
为匹配的路由添加前缀。例如:访问${GATEWAY_URL}/hello
会转发到https://example.org/mypath/hello
。
1 | spring: |
如果不设置,那么名为 Host
的Header由Http Client控制;如果设置了,那么会设置一个请求属性(preserveHostHeader=true),路由过滤器会检查从而去判断是否要发送原始的、名为Host的Header。
TIPS
在视频Spring Cloud Gateway一章,限流一节会详细讲解。也可阅读官方文档
https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#_requestratelimiter_gatewayfilter_factory
1 | spring: |
1 | spring: |
Location
的Header。上面配置表达的意思是: ${GATEWAY_URL}/hello
会重定向到 https://ecme.org/hello
,并且携带一个 Location:http://www.itmuch.com
的Header。
1 | spring.cloud.gateway.filter.remove-hop-by-hop.headers: Connection,Keep-Alive |
移除转发请求的Header,多个用 ,
分隔。默认情况下,移除如下Header。这些Header是由 IETF 组织规定的。
1 | spring: |
为原始请求删除名为 X-Request-Foo
的请求头。
1 | spring: |
删除名为 X-Request-Foo
的响应头。
1 | spring: |
重写请求路径。如上配置,访问 /foo/bar
会将路径改为/bar
再转发,也就是会转发到 https://example.org/bar
。需要注意的是,由于YAML语法,需用$\
替换 $
。
1 | spring: |
如果名为 X-Response-Foo
的响应头的内容是/42?user=ford&password=omg!what&flag=true
,则会被修改为/42?user=ford&password=***&flag=true
。
1 | spring: |
在转发到后端微服务请求之前,强制执行 WebSession::save
操作。用在那种像 Spring Session
延迟数据存储(笔者注:数据不是立刻持久化)的,并希望在请求转发前确保session状态保存情况。
如果你将Spring Secutiry
于Spring Session
集成使用,并想确保安全信息都传到下游机器,你就需要配置这个filter。
添加一系列起安全作用的响应头。Spring Cloud Gateway参考了这篇博客的建议:https://blog.appcanary.com/2017/http-security-headers.html
默认会添加如下Header(包括值):
X-Xss-Protection:1; mode=block
Strict-Transport-Security:max-age=631138519
X-Frame-Options:DENY
X-Content-Type-Options:nosniff
Referrer-Policy:no-referrer
Content-Security-Policy:default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'
X-Download-Options:noopen
X-Permitted-Cross-Domain-Policies:none
如果你想修改这些Header的值,可使用如下配置:
前缀:spring.cloud.gateway.filter.secure-headers
上面的header对应的后缀:
xss-protection-header
strict-transport-security
frame-options
content-type-options
referrer-policy
content-security-policy
download-options
permitted-cross-domain-policies
例如:spring.cloud.gateway.filter.secure-headers.xss-protection-header: 你想要的值
如果想禁用某些Header,可使用如下配置:spring.cloud.gateway.filter.secure-headers.disable
,多个用 ,
分隔。例如:spring.cloud.gateway.filter.secure-headers.disable=frame-options,download-options
。
1 | spring: |
采用路径template
参数,通过请求路径的片段的模板化,来达到操作修改路径的母的,运行多个路径片段模板化。
如上配置,访问${GATEWAY_PATH}/foo/bar
,则对于后端微服务的路径会修改为 /bar
。
1 | spring: |
如果后端服务响应带有名为 X-Response-Foo
的响应头,则将值改为替换成 Bar
。
1 | spring: |
修改响应的状态码,值可以是数字,也可以是字符串。但一定要是Spring HttpStatus
枚举类中的值。如上配置,两种方式都可以返回HTTP状态码401。
1 | spring: |
数字表示要截断的路径的数量。如上配置,如果请求的路径为 /name/bar/foo
,则路径会修改为/foo
,也就是会截断2个路径。
1 | spring: |
针对不同的响应做重试,可配置如下参数:
retries
: 重试次数statuses
: 需要重试的状态码,取值在 org.springframework.http.HttpStatus
中methods
: 需要重试的请求方法,取值在 org.springframework.http.HttpMethod
中series
: HTTP状态码系列,取值在 org.springframework.http.HttpStatus.Series
中1 | spring: |
为后端服务设置收到的最大请求包大小。如果请求大小超过设置的值,则返回 413 Payload Too Large
。默认值是5M
TIPS
该过滤器处于
BETA
状态,未来API可能会变化,生产环境请慎用。
可用于在Gateway将请求发送给后端微服务之前,修改请求体内容。该过滤器只能通过代码配置,不支持在配置文件设置。示例:
1 |
|
TIPS
该过滤器处于
BETA
状态,未来API可能会变化,生产环境请慎用。
可用于修改响应体内容。该过滤器只能通过代码配置,不支持在配置文件设置。示例:
1 |
|
1 | spring: |
如果你想为所有路由添加过滤器,可使用该属性。
]]>TIPS
本文基于Spring Cloud Greenwich SR2编写,兼容Spring Cloud Finchley及更高版本。
这一节来详细探讨Spring Cloud Gateway的路由谓词工厂
(Route Predicate Factories),路由谓词工厂的作用是:符合Predicate的条件,就使用该路由的配置,否则就不管。 只要掌握这一句,掌握路由谓词工厂就比较轻松了。
TIPS
Predicate是Java 8提供的一个函数式编程接口。
本文探讨了Spring Cloud Gateway中内置的谓词工厂,包括:
谓词工厂 |
---|
After |
Before |
Between |
Cookie |
Header |
Host |
Method |
Path |
Query |
RemoteAddr |
先来探讨Spring Cloud Gateway路由配置的两种姿势:
1 | spring: |
表示访问 GATEWAY_URL/**
会转发到 http://www.itmuch.com/**
TIPS
这段配置不能直接使用,需要和下面的Predicate配合使用才行。
1 | spring: |
表示访问 GATEWAY_URL/spring-cloud/spring-cloud-stream-pan-ta/
会转发到 http://www.itmuch.com/spring-cloud/spring-cloud-stream-pan-ta/
TIPS
这段配置不能直接使用,需要和下面的Predicate配合使用才行。
1 | spring: |
表示访问 GATEWAY_URL/**
会转发到 user-center
微服务的 /**
TIPS
这段配置不能直接使用,需要和下面的Predicate配合使用才行。
1 | spring: |
表示访问 GATEWAY_URL/shares/1
会转发到 user-center
微服务的 /shares/1
TIPS
这段配置不能直接使用,需要和下面的Predicate配合使用才行。
下面正式探讨路由谓词工厂。Spring Cloud Gateway提供了十来种路由谓词工厂。为网关实现灵活的转发提供了基石。
示例:
1 | spring: |
TIPS
- 技巧:时间可使用
System.out.println(ZonedDateTime.now());
打印,然后即可看到时区。例如:2019-08-10T16:50:42.579+08:00[Asia/Shanghai]
- 时间格式的相关逻辑:
- 默认时间格式:org.springframework.format.support.DefaultFormattingConversionService#addDefaultFormatters
- 时间格式注册:org.springframework.format.datetime.standard.DateTimeFormatterRegistrar#registerFormatters
示例:
1 | spring: |
示例:
1 | spring: |
示例:
1 | spring: |
1 | spring: |
1 | spring: |
1 | spring: |
1 | spring: |
TIPS
建议大家看下这一部分的官方文档,里面有个segment编程技巧。比较简单,留个印象。
https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#_path_route_predicate_factory
示例1:
1 | spring: |
示例2:
1 | spring: |
示例:
1 | spring: |
TIPS
建议大家看下这一部分的官方文档,有个小编程技巧。比较简单,留个印象。
https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#_remoteaddr_route_predicate_factory
本文来对Spring Cloud Stream,做一个知识点盘点和总结,包括:
组内只有1个实例消费。如果不设置group,则stream会自动为每个实例创建匿名且独立的group——于是每个实例都会消费。
组内单次只有1个实例消费,并且会轮询负载均衡。通常,在将应用程序绑定到给定目标时,最好始终指定consumer group。
与外部消息系统通信的组件,为构造 Binding
提供了 2 个方法,分别是 bindConsumer
和 bindProducer
,它们分别用于构造生产者和消费者。Binder使Spring Cloud Stream应用程序可以灵活地连接到中间件,目前spring为kafka、rabbitmq提供binder。
Binding
是连接应用程序跟消息中间件的桥梁,用于消息的消费和生产,由binder创建。
TIPS
严格来说这个不是概念,而是一种Stream提高伸缩性、吞吐量的一种方式。不过不想另起标题了,写在这里吧。
一个或多个生产者将数据发送到多个消费者,并确保有共同特征标识的数据由同一个消费者处理。默认是对消息进行hashCode,然后根据分区个数取余,所以对于相同的消息,总会落到同一个消费者上。
示例:
1 | public interface Barista { |
作用:
示例:
1 | public interface Source { |
作用:
类似Input,只是用来生产消息。
示例:
1 | "headers['type']=='dog'") (value = Sink.INPUT, condition = |
作用:
用于消费消息
condition的作用:符合条件,才进入处理方法。
condition起作用的两个条件:
示例:
1 | // 接收INPUT这个channel的消息,并将返回值发送到OUTPUT这个channel |
作用:
用于发送消息
示例:
1 |
|
作用:
表示让定义的方法生产消息。
注:用
InboundChannelAdapter
注解的方法上即使有参数也没用。即下面test方法不要有参数。
示例:
1 | (inputChannel = Sink.INPUT, outputChannel = Source.OUTPUT) |
作用:
表示方法能够处理消息或消息有效内容,监听input消息,用方法体的代码处理,然后输出到output中。
示例:
1 | (inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) |
作用:
和 ServiceActivator
类似,表示方法能够转换消息,消息头,或消息有效内容
示例代码:
1 |
|
如果不想自己做byte数组转换,可以添加配置:
1 | spring: |
作用:
允许消费者控制消费速率。
相关文章:
https://spring.io/blog/2018/02/27/spring-cloud-stream-2-0-polled-consumers
]]>TIPS
本文基于Spring Cloud Greenwich SR1,理论支持Finchley及更高版本。
本节详细探讨Spring Cloud Stream的错误处理。
配置:
1 | spring: |
代码:
1 | 4j |
1 | (value = Processor.INPUT) |
系统处理方式,因消息中间件不同而异。如果应用没有配置错误处理,那么error将会被传播给binder,binder将error回传给消息中间件。消息中间件可以丢弃消息、requeue(重新排队,从而重新处理)或将失败的消息发送给DLQ(死信队列)。
默认情况下,错误消息将被丢弃。虽然在某些情况下可以接受,但这种方式一般不适用于生产。
TIPS
- 虽然RocketMQ也支持DLQ,但目前RocketMQ控制台并不支持在界面上操作,将死信放回消息队列,让客户端重新处理。所以使用很不方便,而且用法也和本节有一些差异。
- 如使用RocketMQ,建议参考上面【应用处理】一节的用法,也可额外订阅这个Topic
%DLQ%+consumerGroup
- 个人给RocketMQ控制台提的Issue:
https://github.com/apache/rocketmq/issues/1334
配置:
1 | spring: |
代码:
1 | (value = Processor.INPUT) |
这样,消息消费失败后,就会放入死信队列。在控制台操作一下,即可将死信放回消息队列,这样,客户端就可以重新处理。
如果想获取原始错误的异常堆栈,可添加如下配置:
1 | spring: |
Rabbit/Kafka的binder依赖RetryTemplate实现重试,从而提升消息处理的成功率。然而,如果设置了spring.cloud.stream.bindings.input.consumer.max-attempts=1
,那么RetryTemplate则不再重试。此时可通过requeue方式处理异常。
添加如下配置:
1 | # 默认是3,设为1则禁用重试 |
这样,失败的消息将会被重新提交到同一个handler进行处理,直到handler抛出 AmqpRejectAndDontRequeueException
异常为止。
RetryTemplate重试也是错误处理的一种手段。
1 | spring: |
测试代码:
1 | (value = Processor.INPUT) |
多数场景下,使用配置方式定制重试行为都是可以满足需求的,但配置方式可能无法满足一些复杂需求。此时可使用编码方式配置RetryTemplate:
1 |
|
然后添加配置:
1 | spring.cloud.stream.bindings.<input channel名称>.consumer.retry-template-name=myRetryTemplate |
]]>注意:
Spring Cloud Stream 2.2才支持设置retry-template-name
TIPS
本文基于Spring Cloud Greenwich SR1
+ spring-cloud-starter-stream-rocketmq 0.9.0
理论兼容:Spring Cloud Finchley+
+ spring-cloud-starter-stream-rocketmq 0.2.2+
MQ使用的是RocketMQ,也可使用Kafka或者RabbitMQ。
本文探讨Spring Cloud Stream & RocketMQ过滤消息的各种姿势。
在实际项目中,我们可能需要实现消息消费的过滤。
举个例子:实现消息的分流处理:
生产者生产的消息,虽然消息体可能一样,但是header不一样。可编写两个或者更多的消费者,对不同header的消息做针对性的处理!
生产者设置一下header,比如my-header,值根据你的需要填写:
1 |
|
1 |
|
如代码所示,使用 StreamListener
注解的 condition
属性。当 headers['my-header']=='你的header'
条件满足,才会进入到方法体。
TIPS
该方式只支持RoketMQ,不支持Kafka/RabbitMQ
1 |
|
接口
1 | public interface MySink { |
注解
1 | @EnableBinding({MySink.class}) |
配置
1 | spring: |
消费代码
1 |
|
日志:
1 | 2019-08-04 19:10:03.799 INFO 53760 --- [MessageThread_1] c.i.u.rocketmq.MyTestStreamConsumer : 带有tag1的消息被消费了:messageBody =消息体 |
TIPS
- 该方式只支持RoketMQ,不支持Kafka/RabbitMQ
- 用了sql,就不要用Tag
RocketMQ支持使用SQL语法过滤消息。官方文档:http://rocketmq.apache.org/rocketmq/filter-messages-by-sql92-in-rocketmq/
Spring Clous Stream RocketMQ也为此特性提供了支持。
默认情况下,RocketMQ的SQL过滤支持是关闭的,要想使用SQL 92过滤消息,需要:
在 conf/broker.conf
添加
1 | enablePropertyFilter = true |
启动RocketMQ
1 | nohup sh bin/mqbroker -n localhost:9876 -c ./conf/broker.conf & |
1 |
|
接口
1 | public interface MySink { |
注解
1 | @EnableBinding({MySink.class}) |
配置
1 | spring: |
消费代码
1 |
|
日志
1 | 2019-08-04 19:58:59.787 INFO 56375 --- [MessageThread_1] c.i.u.rocketmq.MyTestStreamConsumer : index <=1000 的消息被消费了:messageBody =消息体 |
org.springframework.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties
TIPS
近日在个人技术讨论QQ群里,谈论到IDEA的那些事儿。有童鞋居然在某电商网站花钱买激活码。我觉得是助纣为虐(自己用盗版就算了,花钱养卖盗版感觉很无语),遂有此文。
其实IDEA是可以免费使用的。
IDEA是个人最喜欢的IDE,它非常智能,懂我的心,极大地提高了个人编程效率;让人爱不释手,欲罢不能。
然而,这是一款收费软件,价格不菲。IDEA价目详见:https://www.jetbrains.com/idea/buy/#commercial?billing=yearly
。
本文教大家如何 免费,并且 光荣地 使用 正版 IntelliJ IDEA。
在 https://www.jetbrains.com/community/opensource/
,IDEA有一个开源免费协议。简单翻译一下。
从协议不难看出,你只需在GitHub上准备一个维护超过3个月的项目开源项目,就可以免费使用IDEA 1年了,1年到期后,可以按照此步骤再申请一次。
这是一个良好的闭环:
到 https://www.jetbrains.com/shop/eform/opensource?product=ALL
即可提交申请。
点击 APPLY FOR FREE LICENSES
按钮,即可看到类似如下的界面:
等待1天左右,即可前往申请时填写的邮箱,即可收到激活码了。
点击图中的链接,即可进入协议界面,点击 ACCEPT
,即可看到类似如下的界面:
点击图中的链接,并按照提示操作,注册一个账号,或者如果你已经有Jetbrains账号,就直接登录。这一步主要是让你的Jetbrains账号和Liscence绑定。
将激活码填入如下界面即可激活IDEA:
激活后的效果:
可以看到,已经成功激活了。未来过期后,依照本次操作再执行一次即可。当然我本机电脑还没有升级到2019.2,这个无妨。你可以先升级,再激活;也可以先激活再升级。
注:
对照表来自:消息队列对比参照表 ,对比维度比较全面,结果个人比较认同,强烈建议参考。
注:
RocketMQ官方和其他MQ之间的PK,表格非常宽,如显示不全,请点击原文地址阅读。
Messaging Product | Client SDK | Protocol and Specification | Ordered Message | Scheduled Message | Batched Message | BroadCast Message | Message Filter | Server Triggered Redelivery | Message Storage | Message Retroactive | Message Priority | High Availability and Failover | Message Track | Configuration | Management and Operation Tools |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ActiveMQ | Java, .NET, C++ etc. | Push model, support OpenWire, STOMP, AMQP, MQTT, JMS | Exclusive Consumer or Exclusive Queues can ensure ordering | Supported | Not Supported | Supported | Supported | Not Supported | Supports very fast persistence using JDBC along with a high performance journal,such as levelDB, kahaDB | Supported | Supported | Supported, depending on storage,if using kahadb it requires a ZooKeeper server | Not Supported | The default configuration is low level, user need to optimize the configuration parameters | Supported |
Kafka | Java, Scala etc. | Pull model, support TCP | Ensure ordering of messages within a partition | Not Supported | Supported, with async producer | Not Supported | Supported, you can use Kafka Streams to filter messages | Not Supported | High performance file storage | Supported offset indicate | Not Supported | Supported, requires a ZooKeeper server | Not Supported | Kafka uses key-value pairs format for configuration. These values can be supplied either from a file or programmatically. | Supported, use terminal command to expose core metrics |
RocketMQ | Java, C++, Go | Pull model, support TCP, JMS, OpenMessaging | Ensure strict ordering of messages,and can scale out gracefully | Supported | Supported, with sync mode to avoid message loss | Supported | Supported, property filter expressions based on SQL92 | Supported | High performance and low latency file storage | Supported timestamp and offset two indicates | Not Supported | Supported, Master-Slave model, without another kit | Supported | Work out of box,user only need to pay attention to a few configurations | Supported, rich web and terminal command to expose core metrics |
1 | 方式一、git下载,执行如下命令 |
找到rocketmq-console/src/main/resources/application.properties
根据需求,修改配置
1 | # 管理后台访问上下文路径,默认为空 |
笔者只修改了如下两项:
1 | # console端口 |
修改 pom.xml
,修改RocketMQ相关依赖的版本
找到
1 | <rocketmq.version>4.4.0</rocketmq.version> |
修改为
1 | <rocketmq.version>你的RocketMQ版本</rocketmq.version> |
笔者使用的是RocketMQ 4.5.1,故而改为
1 | <rocketmq.version>4.5.1</rocketmq.version> |
修改pom.xml后,org.apache.rocketmq.console.service.impl.MessageServiceImpl#queryMessageByTopic
编译会报错,所以需要解决一下。将
1 | DefaultMQPullConsumer consumer = new DefaultMQPullConsumer(MixAll.TOOLS_CONSUMER_GROUP, null); |
改为:
1 | RPCHook rpcHook = null; |
即可。
1 | 切换到代码根目录 |
笔者已经将修改好的RocketMQ控制台发布到GitHub了。
下载地址:https://github.com/eacdy/rocketmq-externals/releases
1 | java -jar rocketmq-console-ng-1.0.1.jar |
访问 http://localost:17890
(端口用上面 application.properties
中的 server.port=17890
指定,默认是8080) ,即可看到类似如下的界面:
TIPS
本文基于RocketMQ 4.5.1,理论支持RocketMQ 4.0+
本文详细探讨如何搭建RocketMQ
前往 http://rocketmq.apache.org/release_notes/release-notes-4.5.1/
,下载 Binary
文件即可。
例如RocketMQ 4.5.1的下载地址:
解压压缩包
1 | unzip rocketmq-all-4.5.1-bin-release.zip |
切换目录到RocketMQ根目录
1 | cd rocketmq-all-4.5.1-bin-release |
启动Name Server
1 | nohup sh bin/mqnamesrv & |
验证是否启动OK:
1 | tail -f ~/logs/rocketmqlogs/namesrv.log |
启动 Broker
1 | nohup sh bin/mqbroker -n localhost:9876 & |
验证是否启动OK:
1 | tail -f ~/logs/rocketmqlogs/broker.log |
执行如下命令:
1 | export NAMESRV_ADDR=localhost:9876 |
能看到类似如下输出:
1 | SendResult [sendStatus=SEND_OK, msgId=C0A82BC5F36C511D50C05B41... |
执行如下命令:
1 | sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer |
能看到类似如下输出:
1 | ConsumeMessageThread_4 Receive New Messages: [MessageExt [queueId=3, stor.... |
依次执行以下两条命令即可
1 | 命令 |
RocketMQ集群搭建说明 ,集群安装模式非常多,本文不展开了。请各位看客根据自己的需求,选择适合自己的模式自行搭建。
]]>这一节来总结Sentinel的所有配置。
TIPS
本文基于Sentinel 1.6.2编写,未来Sentinel发布新版本后,各位看官可按照本文中的“参考文档”,自行查阅新版本的配置项目。
TIPS
参考文档:
https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/sentinel.adoc
配置项 | 含义 | 默认值 |
---|---|---|
spring.cloud.sentinel.enabled |
Sentinel自动化配置是否生效 | true |
spring.cloud.sentinel.eager |
取消Sentinel控制台懒加载 | false |
spring.cloud.sentinel.transport.port |
应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer | 8719 |
spring.cloud.sentinel.transport.dashboard |
Sentinel 控制台地址 | |
spring.cloud.sentinel.transport.heartbeat-interval-ms |
应用与Sentinel控制台的心跳间隔时间 | |
spring.cloud.sentinel.transport.client-ip |
客户端IP | |
spring.cloud.sentinel.filter.order |
Servlet Filter的加载顺序。Starter内部会构造这个filter | Integer.MIN_VALUE |
spring.cloud.sentinel.filter.url-patterns |
数据类型是数组。表示Servlet Filter的url pattern集合 | /* |
spring.cloud.sentinel.filter.enabled |
Enable to instance CommonFilter | true |
spring.cloud.sentinel.metric.charset |
metric文件字符集 | UTF-8 |
spring.cloud.sentinel.metric.file-single-size |
Sentinel metric 单个文件的大小 | |
spring.cloud.sentinel.metric.file-total-count |
Sentinel metric 总文件数量 | |
spring.cloud.sentinel.log.dir |
Sentinel 日志文件所在的目录 | |
spring.cloud.sentinel.log.switch-pid |
Sentinel 日志文件名是否需要带上pid | false |
spring.cloud.sentinel.servlet.block-page |
自定义的跳转 URL,当请求被限流时会自动跳转至设定好的 URL | |
spring.cloud.sentinel.flow.cold-factor |
冷启动因子 | 3 |
TIPS
参考文档:
https://github.com/alibaba/Sentinel/wiki/启动配置项
名称 | 含义 | 类型 | 默认值 | 是否必需 | 备注 |
---|---|---|---|---|---|
project.name |
指定程序的名称 | String |
null |
否 | |
csp.sentinel.app.type |
指定程序的类型 | int |
0 (APP_TYPE_COMMON ) |
否 | 1.6.0 引入 |
csp.sentinel.metric.file.single.size |
单个监控文件的大小 | long |
52428800 | 否 | |
csp.sentinel.metric.file.total.count |
监控文件的总数上限 | int |
6 | 否 | |
csp.sentinel.log.dir |
Sentinel 日志文件目录 | String |
${user.home}/logs/csp/ |
否 | 1.3.0 引入 |
csp.sentinel.log.use.pid |
日志文件名中是否加入进程号,用于单机部署多个应用的情况 | boolean |
false |
否 | 1.3.0 引入 |
csp.sentinel.statistic.max.rt |
最大的有效响应时长(ms),超出此值则按照此值记录 | int |
4900ms | 否 | 1.4.1 引入 |
其中 project.name
项用于指定应用名(appName)。若未指定,则默认从 sun.java.command
中解析出对应的类名作为应用名。实际项目使用中建议指定应用名。
注意:若需要在单台机器上运行相同服务的多个实例,则需要加入
-Dcsp.sentinel.log.use.pid=true
来保证不同实例日志的独立性。
名称 | 含义 | 类型 | 默认值 | 是否必需 |
---|---|---|---|---|
csp.sentinel.dashboard.server |
控制台的地址,指定控制台后客户端会自动向该地址发送心跳包。地址格式为:hostIp:port |
String |
null |
是 |
csp.sentinel.heartbeat.interval.ms |
心跳包发送周期,单位毫秒 | long |
null |
非必需,若不进行配置,则会从相应的 HeartbeatSender 中提取默认值 |
csp.sentinel.api.port |
本地启动 HTTP API Server 的端口号 | int |
null |
是,且不可冲突 |
所有参数均可通过 JVM -D 参数指定。除 project.name
以及日志的配置项(如 csp.sentinel.log.dir
)之外,其余参数还可通过 properties 文件指定,路径为 ${user_home}/logs/csp/${project.name}.properties
。
优先级顺序:JVM -D 参数的优先级最高,若 properties 和 JVM 参数中有相同项的配置,以 JVM -D 参数配置的为准。
]]>