当前位置: 首页 > news >正文

模板网站seo重庆seo全网营销

模板网站seo,重庆seo全网营销,番禺做网站,做mip网站需要多钱文章目录 一、Entry1、Entry的声明2、使用API自定义资源3、基于SentinelResource注解标记资源 二、Context1、Context介绍2、Context的初始化3、AbstractSentinelInterceptor4、ContextUtil 一、Entry 1、Entry的声明 默认情况下,Sentinel会将controller中的方法作…

文章目录

  • 一、Entry
    • 1、Entry的声明
    • 2、使用API自定义资源
    • 3、基于@SentinelResource注解标记资源
  • 二、Context
    • 1、Context介绍
    • 2、Context的初始化
    • 3、AbstractSentinelInterceptor
    • 4、ContextUtil

一、Entry

1、Entry的声明

默认情况下,Sentinel会将controller中的方法作为被保护资源,那么问题来了,我们该如何将自己的一段代码标记为一个Sentinel的资源呢?

Sentinel中的资源用Entry来表示。

声明Entry的API示例:(try后面直接加括号写上对应的资源,就不用自己再加finally语句去关闭了,即try-with-resource

// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
try (Entry entry = SphU.entry("resourceName")) {// 被保护的业务逻辑// 你想做的操作,比如异常次数+1、调用次数+1// do something here...
} catch (BlockException ex) {// 业务代码抛的异常+限流的异常// 资源访问阻止,被限流或被降级// 在此处进行相应的处理操作
}

try-with-resource的写法需要注意:

特别地,若 entry 的时候传入了热点参数,那么 exit 的时候也一定要带上对应的参数(exit(count, args)),否则可能会有统计错误。这个时候不能使用 try-with-resources 的方式。另外通过 Tracer.trace(ex) 来统计异常信息时,由于 try-with-resources 语法中 catch 调用顺序的问题,会导致无法正确统计异常数,因此统计异常信息时也不能在 try-with-resources 的 catch 块中调用 Tracer.trace(ex)。

不用try-with-resource,手动exit的写法:

Entry entry = null;
// 务必保证 finally 会被执行
try {// 资源名可使用任意有业务语义的字符串,注意数目不能太多(超过 1K),超出几千请作为参数传入而不要直接作为资源名// EntryType 代表流量类型(inbound/outbound),其中系统规则只对 IN 类型的埋点生效entry = SphU.entry("自定义资源名");// 被保护的业务逻辑// do something...
} catch (BlockException ex) {// 资源访问阻止,被限流或被降级// 进行相应的处理操作
} catch (Exception ex) {// 若需要配置降级规则,需要通过这种方式记录业务异常Tracer.traceEntry(ex, entry);
} finally {// 务必保证 exit,务必保证每个 entry 与 exit 配对if (entry != null) {entry.exit();}
}

关于SphU.entry()方法的参数:

在这里插入图片描述
注意:SphU.entry(xxx) 需要与 entry.exit() 方法成对出现,匹配调用,否则会导致调用链记录异常,抛出 ErrorEntryFreeException 异常。常见的错误:

1、自定义埋点只调用 SphU.entry(),没有调用 entry.exit()
2、顺序错误,比如:entry1 -> entry2 -> exit1 -> exit2,应该为 entry1 -> entry2 -> exit2 -> exit1

2、使用API自定义资源

在demo工程的order-service服务中,将OrderServicequeryOrderById()方法标记为一个资源:queryOrderById()方法未修改前:

在这里插入图片描述

  • 首先处理下依赖与配置
<!--sentinel-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
spring:cloud:sentinel:transport:dashboard: localhost:8090 # 这里我的sentinel用了8089的端口
  • 修改OrderService类的queryOrderById方法,创建Entry资源,将要保护的一段代码放入try语句来做为一个资源:
public Order queryOrderById(Long orderId) {// 创建Entry,标记资源,资源名为resource1try (Entry entry = SphU.entry("resource1")) {// 1.查询订单Order order = orderMapper.findById(orderId);// 2.查询用户,基于Feign的远程调用User user = userClient.findById(order.getUserId());// 3.设置order.setUser(user);// 4.返回return order;}catch (BlockException e){log.error("被限流或降级", e);return null;}
}

重启后可以看到自定义资源成功:

在这里插入图片描述
很明显,上面的逻辑在自定义资源时是重复的动作,即创建Entry,再拿个try-catch把要定义的代码包起来。 ⇒ AOP环绕实现,在前面之前try,在之后catch,AOP再兑换成一个注解,这个注解官方已实现,就是@SentinelResource

3、基于@SentinelResource注解标记资源

同样标记Service里的queryOrderById方法:

在这里插入图片描述
从自动装配开始找到源码看下实现:

在这里插入图片描述

匹配@SentinelResource注解做AOP环绕增强的源码:


/*** Aspect for methods with {@link SentinelResource} annotation.** @author Eric Zhao*/
@Aspect
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {// 切点是添加了 @SentinelResource注解的类@Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")public void sentinelResourceAnnotationPointcut() {}// 环绕增强@Around("sentinelResourceAnnotationPointcut()")public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {// 获取受保护的方法Method originMethod = resolveMethod(pjp);// 获取 @SentinelResource注解SentinelResource annotation = originMethod.getAnnotation(SentinelResource.class);if (annotation == null) {// Should not go through here.throw new IllegalStateException("Wrong state for SentinelResource annotation");}// 获取注解上的资源名称String resourceName = getResourceName(annotation.value(), originMethod);EntryType entryType = annotation.entryType();int resourceType = annotation.resourceType();Entry entry = null;try {// 创建资源 Entryentry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());// 执行受保护的方法Object result = pjp.proceed();return result;} catch (BlockException ex) {return handleBlockException(pjp, annotation, ex);} catch (Throwable ex) {Class<? extends Throwable>[] exceptionsToIgnore = annotation.exceptionsToIgnore();// The ignore list will be checked first.if (exceptionsToIgnore.length > 0 && exceptionBelongsTo(ex, exceptionsToIgnore)) {throw ex;}if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) {traceException(ex);return handleFallback(pjp, annotation, ex);}// No fallback function can handle the exception, so throw it out.throw ex;} finally {if (entry != null) {entry.exit(1, pjp.getArgs());}}}
}

简单来说,@SentinelResource注解就是一个标记,而Sentinel基于AOP思想,对被标记的方法做环绕增强,完成资源(Entry)的创建。

二、Context

在这里插入图片描述
如图,除了簇点链路中的controller方法,以及我自定义的资源,还有一个默认的入口节点:sentinel_spring_web_context,它是一个EntranceNode类型的节点,这个节点是在初始化Context的时候由Sentinel帮我们创建的。

1、Context介绍

  • Context 代表调用链路上下文,贯穿一次调用链路中的所有资源( Entry),基于ThreadLocal。
  • Context 维护着入口节点(entranceNode)、本次调用链路的 curNode(当前资源节点)、调用来源(origin)等信息。
  • 后续的Slot都可以通过Context拿到DefaultNode或者ClusterNode,从而获取统计数据,完成规则判断
  • Context初始化的过程中,会创建EntranceNode,contextName就是EntranceNode的名称

创建Context的API为:

// 创建context,包含两个参数:context名称、 来源名称
ContextUtil.enter("contextName", "originName");

2、Context的初始化

查看Sentinel依赖包下的spring.factories:
在这里插入图片描述

spring.factories声明需要就是自动装配的配置类:

在这里插入图片描述
先看SentinelWebAutoConfiguration这个类:

在这里插入图片描述

这个类实现了WebMvcConfigurer,我们知道这个是SpringMVC自定义配置用到的类,可以配置HandlerInterceptor:

在这里插入图片描述
可以看到这里泛型中配置了一个SentinelWebInterceptor的拦截器。SentinelWebInterceptor的声明如下:

在这里插入图片描述
发现它继承了AbstractSentinelInterceptor这个类,而AbstractSentinelInterceptor最终实现了HandlerInterceptor

在这里插入图片描述
HandlerInterceptor拦截器会拦截一切进入controller的方法,执行preHandle前置拦截方法,而Context的初始化就是在这里完成的。

3、AbstractSentinelInterceptor

HandlerInterceptor拦截器会拦截一切进入controller的方法,执行preHandle前置拦截方法,而Context的初始化就是在这里完成的。来看看这个类的preHandle`实现:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {try {// 获取资源名称,一般是controller方法的@RequestMapping路径,例如/order/{orderId}String resourceName = getResourceName(request);if (StringUtil.isEmpty(resourceName)) {return true;}// 从request中获取请求来源,将来做 授权规则 判断时会用String origin = parseOrigin(request);// 获取 contextName,默认是sentinel_spring_web_contextString contextName = getContextName(request);// 创建 ContextContextUtil.enter(contextName, origin);// 创建资源,名称就是当前请求的controller方法的映射路径Entry entry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_WEB, EntryType.IN);request.setAttribute(baseWebMvcConfig.getRequestAttributeName(), entry);return true;} catch (BlockException e) {try {handleBlockException(request, response, e);} finally {ContextUtil.exit();}return false;}
}

4、ContextUtil

创建Context的方法就是 ContextUtil.enter(contextName, origin); 我们进入entry方法:

public static Context enter(String name, String origin) {if (Constants.CONTEXT_DEFAULT_NAME.equals(name)) {throw new ContextNameDefineException("The " + Constants.CONTEXT_DEFAULT_NAME + " can't be permit to defined!");}return trueEnter(name, origin);
}

进入trueEnter方法:

protected static Context trueEnter(String name, String origin) {// 尝试获取contextContext context = contextHolder.get();// 判空if (context == null) {// 如果为空,开始初始化Map<String, DefaultNode> localCacheNameMap = contextNameNodeMap;// 尝试获取入口节点DefaultNode node = localCacheNameMap.get(name);if (node == null) {LOCK.lock();try {node = contextNameNodeMap.get(name);if (node == null) {// 入口节点为空,初始化入口节点 EntranceNodenode = new EntranceNode(new StringResourceWrapper(name, EntryType.IN), null);// 添加入口节点到 ROOTConstants.ROOT.addChild(node);// 将入口节点放入缓存Map<String, DefaultNode> newMap = new HashMap<>(contextNameNodeMap.size() + 1);newMap.putAll(contextNameNodeMap);newMap.put(name, node);contextNameNodeMap = newMap;}} finally {LOCK.unlock();}}// 创建Context,参数为:入口节点 和 contextNamecontext = new Context(node, name);// 设置请求来源 origincontext.setOrigin(origin);// 放入ThreadLocalcontextHolder.set(context);}// 返回return context;
}

画图表示Entry和Context两个核心API完成资源的创建,不管是controller中的资源还是自定义的资源,接下来就是执行ProcessorSlotChain插槽链,关于ProcessorSlotChain的执行,见下篇。

在这里插入图片描述

http://www.hengruixuexiao.com/news/46759.html

相关文章:

  • 网址查询ip解析磐石网站seo
  • 如何做旅游网站的供应商免费p站推广网站入口
  • 新疆网站建设品牌直销怎么做才最快成功
  • 如何有效的推广宣传北京网优化seo公司
  • 做门户网站代码质量方面具体需要注意什么seo搜索引擎优化工资多少钱
  • 郑州威客网站建设新浪新闻疫情
  • 珠海网站制作首页长沙网站推广服务公司
  • 动态网站建设实训周实训心得爱站网络挖掘词
  • go语言 做网站提高百度搜索排名工具
  • 专业服务网站建设企业推广公司
  • 网站建设柒金手指花总14百度惠生活怎么优化排名
  • 中企动力做网站多久能好专业培训心得体会
  • 北京响应式网站建设山东服务好的seo
  • 云虚拟主机建设网站一定要域名seo优化查询
  • 网站首页为什么不收录如何让百度收录
  • 长春星宿网站建设公司怎么样seo外链建设的方法有
  • 建设电影推荐网站的项目背景百度应用市场下载安装
  • 毕设做网站些什么比较简单百度一下 你就知道官方
  • 欢迎回来请牢记网站域名搜索百度一下
  • 网站定制报价表seo网站排名
  • 如何建网站教程视频宁波seo在线优化哪家好
  • 买实体服务器做网站黑帽seo技术论坛
  • 体育网站的制作哪里可以做互联网最赚钱的行业
  • 赣州网站建设联系方式推广普通话手抄报内容资料
  • 网站的首页需要什么内容世界杯比分查询
  • 网站的数据库丢失西安网站seo排名优化
  • 集团公司网站案例我想做百度推广
  • 网站代码是多少求职seo
  • 做网站用小公司还是大公司长沙网络公关公司
  • 乌兰察布建设局网站怎样在百度上做广告