Spring Cloud Alibaba 组件

Spring Cloud Alibaba 组件

  1. Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

  2. Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

  3. RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。

  4. Dubbo:Apache Dubbo™ 是一款高性能 Java RPC 框架。

  5. Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。

  6. Alibaba Cloud ACM:一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品。

  7. Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

  8. Alibaba Cloud SchedulerX: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。

  9. Alibaba Cloud SMS: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

线上排查基本操作

线上排查基本操作

1. CPU 飚高

线上 CPU 飚高问题大家应该都遇到过,那么如何定位问题呢?

思路:首先找到 CPU 飚高的那个 Java 进程,因为你的服务器会有多个 JVM 进程。然后找到那个进程中的 “问题线程”,最后根据线程堆栈信息找到问题代码。最后对代码进行排查。

如何操作呢?

通过 top 命令找到 CPU 消耗最高的进程,并记住进程 ID。
再次通过 top -Hp [进程 ID] 找到 CPU 消耗最高的线程 ID,并记住线程 ID.

1
top -Hp [进程 ID]  -- 找到 CPU 消耗最高的线程 ID,并记住线程 ID.

通过 JDK 提供的 jstack 工具 dump 线程堆栈信息到指定文件中。具体命令:

1
2
3
jstack -l [进程 ID] >jstack.log。

由于刚刚的线程 ID 是十进制的,而堆栈信息中的线程 ID 是16进制的,因此我们需要将10进制的转换成16进制的,并用这个线程 ID 在堆栈中查找。使用 printf "%x\n" [十进制数字] ,可以将10进制转换成16进制。

通过刚刚转换的16进制数字从堆栈信息里找到对应的线程堆栈。就可以从该堆栈中看出端倪。
从经验来看,一般是某个业务死循环没有出口,这种情况可以根据业务进行修复。
还有 C2 编译器执行编译时也会抢占 CPU,什么是 C2编译器呢?
当 Java 某一段代码执行次数超过10000次(默认)后,
就会将该段代码从解释执行改为编译执行,也就是编译成机器码以提高速度。
而这个 C2编译器就是做这个的。如何解决呢?项目上线后,可以先通过压测工具进行预热,
这样,等用户真正访问的时候,C2编译器就不会干扰应用程序了。
如果是 GC 线程导致的,那么极有可能是 Full GC ,那么就要进行 GC 的优化。

2. 内存问题排查

说完了 CPU 的问题排查,再说说内存的排查,通常,内存的问题就是 GC 的问题,因为 Java 的内存由 GC 管理。
有2种情况,一种是内存溢出了,一种是内存没有溢出,但 GC 不健康。

内存溢出OOM

内存溢出的情况可以通过加上 -XX:+HeapDumpOnOutOfMemoryError 参数,该参数作用是:在程序内存溢出时输出 dump 文件。

有了 dump 文件,就可以通过 dump 分析工具进行分析了,比如常用的MAT,Jprofile,jvisualvm 等工具都可以分析,这些工具都能够看出到底是哪里溢出,哪里创建了大量的对象等等信息。

GC 的健康问题(第二种情况就比较复杂了)

通常一个健康的 GC 是什么状态呢?

YGC 5秒一次左右,每次不超过50毫秒,FGC 最好没有,CMS GC 一天一次左右。

而 GC 的优化有2个维度:

一是频率,二是时长。

YGC 年轻代GC

首先看频率,如果 YGC 超过5秒一次,甚至更长,说明系统内存过大,应该缩小容量
如果频率很高,说明 Eden 区过小,可以将 Eden 区增大,但整个新生代的容量应该在堆的 30% - 40%之间,
eden,from 和 to 的比例应该在 8:1:1左右,这个比例可根据对象晋升的大小进行调整。

如果YGC时间过长呢?
YGC 有2个过程,一个是扫描,一个是复制,通常扫描速度很快,复制速度相比而言要慢一些,如果每次都有大量对象要复制,
就会将 STW 时间延长,还有一个情况就是 StringTable ,这个数据结构中存储着 String.intern 方法返回的常连池的引用,
YGC 每次都会扫描这个数据结构(HashTable),如果这个数据结构很大,且没有经过 FGC,那么也会拉长 STW 时长,
还有一种情况就是操作系统的虚拟内存,当 GC 时正巧操作系统正在交换内存,也会拉长 STW 时长。

FGC

实际上,FGC 我们只能优化频率,无法优化时长,因为这个时长无法控制。如何优化频率呢?

首先,FGC 的原因有几个:
1.Old 区内存不够
2.元数据区内存不够
3.System.gc()
4.执行jmap 或者 jcmd,
5.是CMS Promotion failed 或者 concurrent mode failure,
6.JVM 基于悲观策略认为这次 YGC 后 Old 区无法容纳晋升的对象,因此取消 YGC,提前 FGC。

通常优化的点是 Old 区内存不够导致 FGC。
如果 FGC 后还有大量对象,说明 Old 区过小,应该扩大 Old 区。
如果 FGC 后效果很好,说明 Old 区存在了大量短命的对象,优化的点应该是让这些对象在新生代就被 YGC 掉,
通常的做法是增大新生代,如果有大而短命的对象,通过参数设置对象的大小,不要让这些对象进入 Old 区,还需要检查晋升年龄是否过小。
如果 YGC 后,有大量对象因为无法进入 Survivor 区从而提前晋升,这时应该增大 Survivor 区,但不宜太大。

上面说的都是优化的思路,我们也需要一些工具知道 GC 的状况。

JDK 提供了很多的工具,比如 jmap ,jcmd 等,oracle 官方推荐使用 jcmd 代替 jmap,因为 jcmd 确实能代替 jmap 很多功能。
jmap 可以打印对象的分布信息,可以 dump 文件,注意,jmap 和 jcmd dump 文件的时候会触发 FGC ,使用的时候注意场景。

还有一个比较常用的工具是 jstat,该工具可以查看GC 的详细信息,比如eden ,from,to,old 等区域的内存使用情况。
还有一个工具是 jinfo,该工具可以查看当前 jvm 使用了哪些参数,并且也可以在不停机的情况下修改参数。

包括我们上面说的一些分析 dump 文件的可视化工具,MAT,Jprofile,jvisualvm 等,这些工具可以分析 jmap dump 下来的文件,看看哪个对象使用的内存较多,通常是能够查出问题的。

还有很重要的一点就是,线上环境一定要带上 GC 日志!!!

线上排查基本操作

GC 参数

  1. -Xms2048m 初始堆大小
  2. -Xmx2048m 最大堆大小
  3. -Xss:1024k 设置每个线程堆栈大小,设置每个线程的堆栈大小。
    JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。
    更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
  4. -XX:NewSize=n 设置年轻代大小
  5. -XX:NewRatio=2 设置年轻代和年老代的比值。
  6. -XX:SurvivorRatio=8 年轻代中Eden区与两个Survivor区的比值Eden:S1:S2 = 8:1:1 Eden:Survivor = 8 : 2
  7. -XX:MaxPermSize=64m 设置持久代大小,持久代一般固定大小为64m
  8. -XX:MaxMetaspaceSize=512m 元空间大小
  9. -XX:MetaspaceSize=512m 最大元空间大小

GC:

  1. -XX:+PrintGC 打印GC
  2. -XX:+PrintGCDetails 打印GC,格式不一样,详细
  3. -XX:+PrintGCTimeStamps PrintGCTimeStamps可与上面两个混合使用
  4. -XX:+PrintHeapAtGC 打印GC前后的详细堆栈信息
  5. -Xloggc:D:/temp/gclog/idea.gc.log 与上面几个配合使用,把相关日志信息记录到文件以便分析

垃圾收集器:

  1. -XX:+UseSerialGC:设置串行收集器
  2. -XX:+UseParallelGC:设置并行收集器
  3. -XX:+UseParalledlOldGC:设置并行年老代收集器
  4. -XX:+UseConcMarkSweepGC:设置并发收集器
  5. -XX:InitialBootClassLoaderMetaspaceSize=64M
  6. -XX:MaxTenuringThreshold=6 设置垃圾最大年龄,如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
  7. -XX:+UseConcMarkSweepGC
  8. -XX:CMSFullGCsBeforeCompaction=5 使用并发收集器时,开启对年老代的压缩。由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。

  9. -XX:+CMSParallelRemarkEnabled

  10. -XX:+CMSClassUnloadingEnabled

  11. -XX:+DisableExplicitGC

  12. -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
  13. -XX:ReservedCodeCacheSize=240m
  14. -XX:SoftRefLRUPolicyMSPerMB=50
    -ea
    -Dsun.io.useCanonCaches=false
    -Djava.net.preferIPv4Stack=true
    -XX:+HeapDumpOnOutOfMemoryError
    -XX:-OmitStackTraceInFastThrow

Sentinel工作原理

Sentinel

英 [ˈsentɪnl]

官方文档

基本概念

资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。
在接下来的文档中,我们都会用资源来描述代码块。

只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。
大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。

规则

围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。

Sentinel 功能和设计理念

流量控制

什么是流量控制

流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。
然而,从系统稳定性角度考虑,在处理请求的速度上,也有非常多的讲究。
任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。
Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示:

流量控制设计理念

资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
运行指标,例如 QPS、线程池、系统负载等;
控制的效果,例如直接限流、冷启动、排队等。

Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。

熔断降级

什么是熔断降级

除了流量控制以外,及时对调用链路中的不稳定因素进行熔断也是 Sentinel 的使命之一。
由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,可能会导致请求发生堆积,进而导致级联错误。

Sentinel 和 Hystrix 的原则是一致的: 当检测到调用链路中某个资源出现不稳定的表现,
例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,
让请求快速失败,避免影响到其它的资源而导致级联故障。

熔断降级设计理念

在限制的手段上,Sentinel 和 Hystrix 采取了完全不一样的方法。

Hystrix

Hystrix 通过 ==线程池隔离== 的方式,来对依赖(在 Sentinel 的概念中对应 资源)进行了隔离。
这样做的好处是资源和资源之间做到了最彻底的隔离。缺点是除了增加了线程切换的成本(过多的线程池导致线程数目过多),
还需要预先给各个资源做线程池大小的分配,并且对于一些使用了 ThreadLocal 的场景来说会有问题(如 Spring 事务)。

Sentinel

通过==并发线程数==进行限制

和资源池隔离的方法不同,Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。
这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间变长,
对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。
堆积的线程完成任务后才开始继续接收请求。

针对==慢调用和异常==对资源进行降级

除了对并发线程数进行控制以外,Sentinel 还可以根据响应时间和异常等不稳定因素来快速对不稳定的调用进行熔断。
当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新渐进式地恢复。

系统自适应保护

Sentinel 同时提供系统维度的自适应保护能力。防止雪崩,是系统防护中重要的一环。
当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。
在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。
如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。

针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。

Sentinel 工作机制

Sentinel 的主要工作机制如下:

对主流框架提供适配或者显示的 API,来定义需要保护的资源,并提供设施对资源进行实时统计和调用链路分析。

根据预设的规则,结合对资源的实时统计信息,对流量进行控制。同时,Sentinel 提供开放的接口,方便您定义及改变规则。

Sentinel 提供实时的监控系统,方便您快速了解目前系统的状态。

Sentinel 注解式支持

Sentinel 注解式支持

@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性:

  • value:资源名称,必需项(不能为空)
  • entryType:entry 类型,可选项(默认为 EntryType.OUT)
  • blockHandler / blockHandlerClass

blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

  • fallback / fallbackClass

fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。
fallback 函数签名和位置要求:

  1. 返回值类型必须与原函数返回值类型一致;
  2. 方法参数列表需要和原函数一致,或者可以额外多一个Throwable类型的参数用于接收对应的异常。
  3. fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • defaultFallback(since 1.6.0):

默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。

defaultFallback 函数签名要求:

  1. 返回值类型必须与原函数返回值类型一致;
  2. 方法参数列表需要为空,或者可以额外多一个Throwable类型的参数用于接收对应的异常。
  3. defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • exceptionsToIgnore:用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

public class TestService {

// 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,并且必须为 static 函数.
@SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {ExceptionUtil.class})
public void test() {
System.out.println("Test");
}

// 原函数
@SentinelResource(value = "hello", blockHandler = "exceptionHandler", fallback = "helloFallback")
public String hello(long s) {
return String.format("Hello at %d", s);
}

// Fallback 函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
public String helloFallback(long s) {
return String.format("Halooooo %d", s);
}

// Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
public String exceptionHandler(long s, BlockException ex) {
// Do some log here.
ex.printStackTrace();
return "Oops, error occurred at " + s;
}
}

(二)Redis 数据类型之字符串List

(二)Redis 数据类型之字符串List

List的实现原理是双向循环链表

List

image

查找方向可以是从左往右也可以是从右往左,但是要实现从右往左还需要终端节点的地址,所以通常会设计成双向的循环链表;

若链表为空:

image

lpush

1
2
3
4
5
6
7
8
9
10
11
12
lpush key element [element ...]

lpush mylist 'test'
lpush mylist 'test2'
lpush mylist 'test3'
lpush mylist 'test4'
lrange mylist 0 -1

1) "test4"
2) "test3"
3) "test2"
4) "test"

从左边插入元素, 从左边依次追加进栈,先进后出,后进先出

rpush

1
2
3
4
5
6
7
8
9
10
11
12
rpush key element [element ...]

rpush mylist2 'test'
rpush mylist2 'test2'
rpush mylist2 'test3'
rpush mylist2 'test4'
lrange mylist2 0 -1

1) "test"
2) "test2"
3) "test3"
4) "test4"

从右边插入元素, 从右边依次追加进队列,先进先出,后进后出

lrange

根据起止下标查询列表元素

LRANGE key start stop

start: 从指定下标开始检索
stop: 检索几个元素 -1 表示全部元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
lrange key 0 -1 #表示查看全部元素
lrange key -1 -1 #表示查看最右边的元素

lrange mylist2 0 -1

1) "-1"
2) "0"
3) "0"
4) "test"
5) "test2"
6) "test3"
7) "test4"
8) "test5"
9) "test6"

lrange mylist2 -1 -1

1) "test6"

lpushx

1
lpushx key element [element ...]

与string类型中的nx类似,只有当list存在时才会从左边依次追加元素。

rpushx

1
rpushx key element [element ...]

与string类型中的nx类似,只有当list存在时才会从右边依次追加元素。

linsert

从list中指定的元素的前/后 插入一个新元素:

linsert key BEFORE|AFTER pivot element

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
lrange mylist3 0 -1 查看列表
1) "-1"
2) "0"
3) "1"

linsert mylist3 before -1 -2-1的前面插入-2
lrange mylist3 0 -1
1) "-2"
2) "-1"
3) "0"
4) "1"

linsert mylist3 after 1 21的后面插入2
lrange mylist3 0 -1
1) "-2"
2) "-1"
3) "0"
4) "1"
5) "2"

lrem

lrem key count element

从指定列表左侧开始,删除count个指定元素element

1
2
3
4
5
6
7
8
9
10
11
12
13
lrem mylist3 1 2 从左侧开始删除12
lrange mylist3 0 -1

1) "-2"
2) "-1"
3) "0"
4) "1"
lrem mylist3 1 -2 从左侧开始删除1-2
lrange mylist3 0 -1

1) "-1"
2) "0"
3) "1"

lset

lset key index element

根据下标修改元素内容,下标从左边算起,以0开始:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
lrange mylist 0 -1
1) "-1"
2) "test4"
3) "test3"
4) "test2"
5) "test"

lset mylist 1 test 设置第一个元素为test
lrange mylist 0 -1
1) "-1"
2) "test"
3) "test3"
4) "test2"
5) "test"

ltrim

ltrim key start stop

将原列表截取为从下标start到下标stop闭区间的列表

1
2
3
4
5
6
7
8
9
10
11
lrange mylist 0 -1
1) "-1"
2) "test"
3) "test3"
4) "test2"
5) "test"
ltrim mylist 0 2 ## 截取从0-2的元素为一个新的List
lrange mylist 0 -1
1) "-1"
2) "test"
3) "test3"

llen

llen key

查看指定List中元素的个数

1
llen mylist

lindex

llindex key index
根据指定数组index检索元素

1
2
3
4
5
6
lrange mylist 0 -1
1) "-1"
2) "test"
3) "test3"
lindex mylist 0 ##查找第0个元素
"-1"

lpop

lpop key

左侧消费数据,消费完删除, 这里可以把List当成一个消息队列去看。

rpop

rpop key

从右侧消费数据,消费完删除

Sentinel 主流框架的适配

Sentinel 主流框架的适配

适配

为了减少开发的复杂程度,Sentinel对大部分的主流框架,例如 Web Servlet、Dubbo、Spring Cloud、gRPC、Spring WebFlux、Reactor 等都做了适配。您只需要引入对应的依赖即可方便地整合 Sentinel。
包括以下配置:

Web 适配

  • Spring Boot/Spring Cloud
  • Web Servlet
  • Spring WebFlux

    RPC 适配

  • Apache Dubbo
  • gRPC
  • Feign
  • SOFARPC

    HTTP client 适配

  • Apache HttpClient
  • OkHttp
  • Reactive 适配
  • Reactor

    API Gateway 适配

  • Spring Cloud Gateway
  • Netflix Zuul 1.x
  • Netflix Zuul 2.x
  • Apache RocketMQ

防火墙开放端口

Linux 防火墙开放端口

如果想开放端口(如:8889)

(1)通过vi /etc/sysconfig/iptables 进入编辑增添一条-A INPUT -p tcp -m tcp –dport 8889 -j ACCEPT 即可

(2)执行 /etc/init.d/iptables restart 命令将iptables服务重启

#(3)保存 /etc/rc.d/init.d/iptables save

注:如若不想修改iptables表,可以直接输入下面命令:

1
iptables -I INPUT -p tcp --dport 8889 -j ACCEPT

附:参考自:http://www.cnblogs.com/alimac/p/5848372.html

若/etc/sysconfig/iptables不存在,

原因:在新安装的linux系统中,防火墙默认是被禁掉的,一般也没有配置过任何防火墙的策略,所有不存在/etc/sysconfig/iptables文件。

解决:

在控制台使用iptables命令随便写一条防火墙规则,如:

1
iptables -P OUTPUT ACCEPT

使用

1
service iptables save

进行保存,默认就保存到了/etc/sysconfig目录下的iptables文件中

Linux 高版本nginx Centos7

Linux 高版本nginx Centos7

Install the prerequisites:

1
sudo yum install yum-utils

To set up the yum repository, create the file named

1
vi /etc/yum.repos.d/nginx.repo

with the following contents:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

By default, the repository for stable nginx packages is used. If you would like to use mainline nginx packages, run the following command:

1
sudo yum-config-manager --enable nginx-mainline

To install nginx, run the following command:

1
sudo yum install nginx

When prompted to accept the GPG key, verify that the fingerprint matches 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62, and if so, accept it.

Sentinel快速入门

Sentinel快速入门

如下的代码任然是侵入式的使用方式,也提供了注解支持模块

应用使用 pom 工程,则在 pom.xml 文件中加入以下代码即可:

1
2
3
4
5
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.7.2</version>
</dependency>

First Demo 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package sentinel;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;

public class SentinelDemo {

public static void main(String[] args) {
initFlowRules();
while (true) {
Entry entry = null;
try {
entry = SphU.entry("HelloWorld");
/* 您的业务逻辑 - 开始 */
System.out.println("hello world");
/* 您的业务逻辑 - 结束 */
} catch (BlockException e1) {
/* 流控逻辑处理 - 开始 */
System.out.println("block!");
/* 流控逻辑处理 - 结束 */
} finally {
if (entry != null) {
entry.exit();
}
}
}
}

// 接下来,通过规则来指定允许该资源通过的请求次数
// 例如下面的代码定义了资源 HelloWorld 每秒最多只能通过 20 个请求。
private static void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("HelloWorld");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// Set limit QPS to 20.
rule.setCount(20);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}

Demo 运行之后,我们可以在日志里看到下面的输出:

1
2
3
4
5
6
7
8
9
10
11
window机器位于 C:\Users\shengwangzhong\logs\xxxx
~/logs/csp/${appName}-metrics.log.xxx

输出:
|--timestamp-|------date time----|-resource-|p |block|s |e|rt
1529998904000|2018-06-26 15:41:44|HelloWorld|20|0 |20|0|0
1529998905000|2018-06-26 15:41:45|HelloWorld|20|5579 |20|0|728
1529998906000|2018-06-26 15:41:46|HelloWorld|20|15698|20|0|0
1529998907000|2018-06-26 15:41:47|HelloWorld|20|19262|20|0|0
1529998908000|2018-06-26 15:41:48|HelloWorld|20|19502|20|0|0
1529998909000|2018-06-26 15:41:49|HelloWorld|20|18386|20|0|0

其中 p 代表通过的请求, block 代表被阻止的请求, s 代表成功执行完成的请求个数, e 代表用户自定义的异常, rt 代表平均响应时长。

结合控制台使用:

首先需要保证控制台处于启动状态:

1
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

其中 -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080

此外针对上面的应用需要添加依赖:

1
2
3
4
5
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.7.2</version>
</dependency>

同时需要添加程序启动参数:

1
2
3
-Dcsp.sentinel.dashboard.server=consoleIp:port
↓↓↓↓↓↓↓
-Dcsp.sentinel.dashboard.server=localhost:8080

若启动多个应用,则需要通过 -Dcsp.sentinel.api.port=xxxx 指定客户端监控 API 的端口(默认是 8719)。

这时候,在启动程序以后,可以再dashboard页面能对具体的应用进行实时监控。