SegmentFault 最新的文章 |
- css 的 filter属性竟然如此好玩
- 5种限流算法,7种限流方式,挡住突发流量?
- petite-vue源码剖析-双向绑定`v-model`的工作原理
- Gitlab CI/CD教程及npm包构建发布实战
- 走进开源项目 - urlcat 源码分析
- 什么是 LRU 算法?
- Spring Cloud Ribbon 中的 7 种负载均衡策略
Posted: 14 Mar 2022 09:58 PM PDT css 的 filter属性竟然如此好玩背景 在此之前我对 一、filter 滤镜"滤镜"这个名字很贴切了, 可以理解成为元素添加各种显示效果, 先不用记各种名词咱们直接看效果, 使用方法 & 效果图:
看上图里的这些效果, 比如第一排第一个, 我们会想到在某些特定的纪念日网站整体会变成灰色的样式, 应该就是用的这个属性, 第二排的第一张就可以用与某些事物被"雷击"? 二、做一个'抖动'特效
当然配合上一旋转效果也不错: 原理就是两个图片层叠在一起, 上面的图片进行放大与旋转动画:
三、drop-shadow 阴影
上图可知, 四、drop-shadow 复制 (做一个看图猜人物游戏) 注意: 我这里使用的都是 既然与 所谓 再看一下 看到上面的图我第一反应就是"猜人物"小游戏, 我们把人物的轮廓也就是右图显示出来, 然后在公布答案的时候展示左侧的原图即可。 赋值gif图有bug赋值gif图会有bug, 效果如下: 五、drop-shadow 批量复制 上图可以看出, 第一个复制后是出现了横排的2个, 第二次投射是产生了下方的两个, 并且每次投射都是叠加的, 下面我们看一组更夸张的: 可想而知这种增长方式有多可怕, 稍微写几遍就可以覆盖满屏幕了。 "找不同"小游戏我们可以做一片阴影, 但是其中某个我们单独做一个样式进行覆盖, 考考大家的眼力, 就如图例所示: 这里就是利用 所以只要再写两段代码, 就可以让这个8x8 变成16x16那么多, 应该还挺好玩的。 六、drop-shadow 与 box-shadow的联合
七、drop-shadow 复制后的'运动'既然可以投射出那么多投影, 那么如果我元素进行旋转的话, 投影是否也会进行旋转? 并且它是以什么规律运动的那? 下面演示的是, 物体投影 + 物体本身旋转:
上面是整体以'元素'本身为旋转点进行旋转, 那要如何让'元素'的每个投影都以自身为原点旋转那? 这里的思路就是, 在
八、filter属性着色(svg + png)图片 改变 轮廓的形成 并不是所有的图片被赋予 比如 svg + png 投影变色 我们可以利用
颜色的叠加变色有点强! 有没有办法是直接改变元素本身的颜色? 我尝试将 不管什么颜色无非是三原色合成的颜色, 手动生成那么多的属性不现实, 顺着这个思路我找到了一个真的这样做的网站:
九、局部清晰这里所谓的局部清晰可以想象为, 某张图全部都是模糊的, 但是我们把一个放大镜放在某处, 此处就会变得清晰, 先看我做的效果: 这里的原理是这样的, 一共两层, 下层是模糊滤镜的图片,上层是一个圆形的
end这次就是这样, 希望与你一起进步。 |
Posted: 14 Mar 2022 06:52 PM PDT 大家好啊,我是阿朗,最近工作中需要用到限流,这篇文章介绍常见的限流方式。 文章持续更新,可以关注公众号程序猿阿朗或访问未读代码博客。 前言最近几年,随着微服务的流行,服务和服务之间的依赖越来越强,调用关系越来越复杂,服务和服务之间的稳定性越来越重要。在遇到突发的请求量激增,恶意的用户访问,亦或请求频率过高给下游服务带来较大压力时,我们常常需要通过缓存、限流、熔断降级、负载均衡等多种方式保证服务的稳定性。其中限流是不可或缺的一环,这篇文章介绍限流相关知识。 1. 限流限流顾名思义,就是对请求或并发数进行限制;通过对一个时间窗口内的请求量进行限制来保障系统的正常运行。如果我们的服务资源有限、处理能力有限,就需要对调用我们服务的上游请求进行限制,以防止自身服务由于资源耗尽而停止服务。 在限流中有两个概念需要了解。
2. 固定窗口算法固定窗口算法又叫计数器算法,是一种简单方便的限流算法。主要通过一个支持原子操作的计数器来累计 1 秒内的请求次数,当 1 秒内计数达到限流阈值时触发拒绝策略。每过 1 秒,计数器重置为 0 开始重新计数。 2.1. 代码实现下面是简单的代码实现,QPS 限制为 2,这里的代码做了一些优化,并没有单独开一个线程去每隔 1 秒重置计数器,而是在每次调用时进行时间间隔计算来确定是否先重置计数器。
运行结果:
从输出结果中可以看到大概每秒操作 3 次,由于限制 QPS 为 2,所以平均会有一次被限流。看起来可以了,不过我们思考一下就会发现这种简单的限流方式是有问题的,虽然我们限制了 QPS 为 2,但是当遇到时间窗口的临界突变时,如 1s 中的后 500 ms 和第 2s 的前 500ms 时,虽然是加起来是 1s 时间,却可以被请求 4 次。 简单修改测试代码,可以进行验证:
得到输出中可以看到连续 4 次请求,间隔 250 ms 没有却被限制。:
3. 滑动窗口算法我们已经知道固定窗口算法的实现方式以及它所存在的问题,而滑动窗口算法是对固定窗口算法的改进。既然固定窗口算法在遇到时间窗口的临界突变时会有问题,那么我们在遇到下一个时间窗口前也调整时间窗口不就可以了吗? 下面是滑动窗口的示意图。 上图的示例中,每 500ms 滑动一次窗口,可以发现窗口滑动的间隔越短,时间窗口的临界突变问题发生的概率也就越小,不过只要有时间窗口的存在,还是有可能发生时间窗口的临界突变问题。 3.1. 代码实现下面是基于以上滑动窗口思路实现的简单的滑动窗口限流工具类。
下面是测试用例,设置 QPS 为 2,测试次数 20 次,每次间隔 300 毫秒,预计成功次数在 12 次左右。
下面是测试的结果。
4. 滑动日志算法滑动日志算法是实现限流的另一种方法,这种方法比较简单。基本逻辑就是记录下所有的请求时间点,新请求到来时先判断最近指定时间范围内的请求数量是否超过指定阈值,由此来确定是否达到限流,这种方式没有了时间窗口突变的问题,限流比较准确,但是因为要记录下每次请求的时间点,所以占用的内存较多。 4.1. 代码实现下面是简单实现的 一个滑动日志算法,因为滑动日志要每次请求单独存储一条记录,可能占用内存过多。所以下面这个实现其实不算严谨的滑动日志,更像一个把 1 秒时间切分成 1000 个时间窗口的滑动窗口算法。
代码中把阈值 QPS 设定为 3,运行可以得到如下日志:
5. 漏桶算法漏桶算法中的漏桶是一个形象的比喻,这里可以用生产者消费者模式进行说明,请求是一个生产者,每一个请求都如一滴水,请求到来后放到一个队列(漏桶)中,而桶底有一个孔,不断的漏出水滴,就如消费者不断的在消费队列中的内容,消费的速率(漏出的速度)等于限流阈值。即假如 QPS 为 2,则每 下面是漏桶算法的示意图。 由介绍可以知道,漏桶模式中的消费处理总是能以恒定的速度进行,可以很好的保护自身系统不被突如其来的流量冲垮;但是这也是漏桶模式的缺点,假设 QPS 为 2,同时 2 个请求进来,2 个请求并不能同时进行处理响应,因为每 6. 令牌桶算法令牌桶算法同样是实现限流是一种常见的思路,最为常用的 Google 的 Java 开发工具包 Guava 中的限流工具类 RateLimiter 就是令牌桶的一个实现。令牌桶的实现思路类似于生产者和消费之间的关系。 系统服务作为生产者,按照指定频率向桶(容器)中添加令牌,如 QPS 为 2,每 500ms 向桶中添加一个令牌,如果桶中令牌数量达到阈值,则不再添加。 请求执行作为消费者,每个请求都需要去桶中拿取一个令牌,取到令牌则继续执行;如果桶中无令牌可取,就触发拒绝策略,可以是超时等待,也可以是直接拒绝本次请求,由此达到限流目的。 下面是令牌桶限流算法示意图。 思考令牌桶的实现可以以下特点。
6.1. 代码实现Google 的 Java 开发工具包 Guava 中的限流工具类 RateLimiter 就是令牌桶的一个实现,日常开发中我们也不会手动实现了,这里直接使用 RateLimiter 进行测试。 引入依赖:
RateLimiter 限流体验:
代码中限制 QPS 为 2,也就是每隔 500ms 生成一个令牌,但是程序每隔 250ms 获取一次令牌,所以两次获取中只有一次会成功。
6.2. 思考虽然演示了 Google Guava 工具包中的 RateLimiter 的实现,但是我们需要思考一个问题,就是令牌的添加方式,如果按照指定间隔添加令牌,那么需要开一个线程去定时添加,如果有很多个接口很多个 RateLimiter 实例,线程数会随之增加,这显然不是一个好的办法。显然 Google 也考虑到了这个问题,在 RateLimiter 中,是在每次令牌获取时才进行计算令牌是否足够的。它通过存储的下一个令牌生成的时间,和当前获取令牌的时间差,再结合阈值,去计算令牌是否足够,同时再记录下一个令牌的生成时间以便下一次调用。 下面是 Guava 中 RateLimiter 类的子类 SmoothRateLimiter 的
7. Redis 分布式限流Redis 是一个开源的内存数据库,可以用来作为数据库、缓存、消息中间件等。Redis 是单线程的,又在内存中操作,所以速度极快,得益于 Redis 的各种特性,所以使用 Redis 实现一个限流工具是十分方便的。 下面的演示都基于Spring Boot 项目,并需要以下依赖。
配置 Redis 信息。
7.1. 固定窗口限流Redis 中的固定窗口限流是使用 这里有两点要注意。
由于 Redis 中实现事务的复杂性,所以这里直接只用
下面是使用 Spring Boot 中
代码中虽然限制了 QPS 为 4,但是因为这种限流实现是把毫秒时间戳作为 key 的,所以会有临界窗口突变的问题,下面是运行结果,可以看到因为时间窗口的变化,导致了 QPS 超过了限制值 4。
7.3. 滑动窗口限流通过对上面的基于 这里主要使用
基于上面的四点特性,可以编写出基于
下面是使用 Spring Boot 中
代码中限制 QPS 为 4,运行结果信息与之一致。
这里介绍了 Redis 实现限流的两种方式,当然使用 Redis 也可以实现漏桶和令牌桶两种限流算法,这里就不做演示了,感兴趣的可以自己研究下。 8. 总结这篇文章介绍实现限流的几种方式,主要是窗口算法和桶算法,两者各有优势。
单机限流与分布式限流 上面演示的基于代码形式的窗口算法和桶算法限流都适用于单机限流,如果需要分布式限流可以结合注册中心、负载均衡计算每个服务的限流阈值,但这样会降低一定精度,如果对精度要求不是太高,可以使用。 而 Redis 的限流,由于 Redis 的单机性,本身就可以用于分布式限流。使用 Redis 可以实现各种可以用于限流算法,如果觉得麻烦也可以使用开源工具如 redisson,已经封装了基于 Redis 的限流。 其他限流工具 文中已经提到了 一如既往,文章中的代码存放在:github.com/niumoo/JavaNotes 参考Redis INCR:https://redis.io/commands/incr Rate Limiting Wikipedia:https://en.wikipedia.org/wiki/Rate_limiting SpringBoot Redis:https://www.cnblogs.com/lenve/p/10965667.html 订阅可以微信搜一搜程序猿阿朗或访问未读代码博客阅读。 |
petite-vue源码剖析-双向绑定`v-model`的工作原理 Posted: 14 Mar 2022 12:03 AM PDT 前言双向绑定 深入 |
Posted: 12 Mar 2022 02:03 AM PST !!!实践过程中请留意文档版本号跟你实际使用Gitlab的版本号 前置知识
自定义配置目录默认配置文件目录是在 若需要自定义设置CI脚本文件的路径,如下: 流水线配置
结构大致可以如下:
重要概念Pipeline流水线,一次流水线相当于一次构建任务,里面可以包含多个阶段,比如install -> eslint -> build -> deploy等流程 ; stages表示构建阶段,每个stage串行同步执行。一旦有一个stage中的一个job失败了,那么下一个stage的任务便不会执行。如果当前stage定义了多个任务,那么其中一个任务失败,另外一个任务还是会被继续执行。但是只有当所有 stages 成功完成后,该构建任务 (Pipeline) 才算成功。 jobsjob表示某个stage里面执行的工作 ,一个stage里面可以定义多个job 。 jobs有如下特点 :
gitlab runner执行构建任务的一个服务,里面包含了持续集成的的环境,一般由docker创建。它可以在不同的主机上部署,也可以在同一个主机上设置多个gitlab-runner ,还可以根据不同的环境设置不同的环境,比如我们需要区分研发环境,测试环境以及正式环境等。 关键字imageCI/CD脚本运行环境的docker镜像,镜像就是一种文件存储形式,可以理解为是一个环境的集合,内含多种文件。如指定node环境镜像:
tags指定gitlab 在执行脚本时使用哪个runner。 before_script在单个
stagesCI允许我们进行自定义的流水线阶段配置,可以将一个流水线拆分为多个阶段(
script执行脚本,脚本内容以数组形式配置。如上例子中stage为npm_install阶段执行的脚本为:
先执行yarn命令安装依赖,结束后查看了当前目录下文件及目录的具体信息,是个串行执行的过程。 cache缓存多个流水线任务之间共用的文件和目录,缓存相关概念下文详情讲述。 only & except设置流水线任务执行时机:使用
retryjob重试次数,默认为0,最大重试次数为2,其中 rules:if此字段可以在单个流水线job或者workflow字段下进行配置。
注意: workflow和
当没有规则为 true 时,流水线不会运行。 以下示例中,前两天规则都匹配到不执行时机,当else时,流水线执行。
when控制上一个stage成功或者失败时,当前stage的行为。
模块化使用关键字
缓存重要概念在 GitLab CI/CD 中,我们所使用的 runner 是以 docker 的形式运行不同的任务。普通的 cache 机制(即不指定URL, 分布式缓存分布式缓存需要runner配置支持,开启后需要在cache中配置s3ServerAddress、s3BucketName等信息进行缓存跨runner共享。 缓存路径在配置cache时, 缓存文件信息上会有最后更新时间(重要信息)、文件权限、 缓存绑定文件缓存绑定到当前版本的文件。当这些文件之一发生变化时,将计算一个新的缓存键并创建一个新的缓存,如下:
此时的 多文件缓存cache可以配置多个 禁用缓存使用 继承缓存缓存配置可复用的情况下使用继承写法,可以在当前job下覆盖(重写)某个策略或者设置优先级
回退缓存键13.4版本以上可应用回退缓存键,功能类似缓存备份。你可以使用
手动清除缓存您可以在 GitLab UI 中清除缓存:
在下一次提交时,您的 CI/CD 作业使用新的缓存。 实战:构建发布组件库到npm仓库编写
编写部署脚本,其中主要是模拟
执行结果: 收到npm发布成功反馈邮件: 以上就是gitlab CI/CD的相关知识点以及实战发布npm包的示例,感谢阅读! |
Posted: 13 Mar 2022 09:31 AM PDT 在《走进开源项目 - urlcat》中,对项目整体进行了分析,对如何做开源也有了进一步的了解,该篇再深入研究下 该项目到底做了什么?
源码共 第一段
该项目是在 qs 项目的基础上并使用 typescript 进行开发,其中定义了 2 个类型,有几个不太了解知识点 interface 与 type 的区别
Record 的用途
Partial 的用途将传入的属性变为可选项
Pick 的用途从类型 Type 中,挑选一组属性组成一个新的类型返回。这组属性由 Keys 限定, Keys 是字符串或者字符串并集。
第二段
这部分代码是利用 TypeScript 定义重载函数类型,采用连续多个重载声明 + 一个函数实现的方式来实现,其作用是为了保证在调用该函数时,函数的参数及返回值都要兼容所有的重载。 例如下图,第三个参数类型在重载函数类型中并不存在。 第三段以下代码是核心,作者通过职责分离的方式,将核心方法代码简化。
总结做开源并不一定要造个更好的轮子,但可以让这个轮子变得更好。通过该项目,也发现自己在 TypeScript 方面的不足,继续学习,再接再厉。 参考文章拓展阅读 |
Posted: 13 Mar 2022 06:02 PM PDT
下面就是当我们访问百度时,某些资源命中了协商缓存,服务端返回 但是,缓存并不是无限制的,会有大小的限制。无论是我们的 这个时候就需要涉及到一种算法,需要将超出大小限制的缓存进行淘汰,一般的规则是淘汰掉最近没有被访问到的缓存,也就是今天要介绍的主角:LRU ( 什么是 LRU?LRU ( 为了方便理解 LRU 算法的全流程,画了一个简单的图:
算法实现下面通过一段简单的代码来实现这个逻辑。
基本的结构如上所示,LRU需要实现的就是两个方法:
我们现在看看如何进行数据的存储:
然后,在每次获取数据时,都需要更新
这个时候,其实还没有完全实现,因为除了
可能会有人觉得这种算法在前端没有什么应用场景,说起来,在 Vue 的内置组件 后续应该还会继续介绍一下 |
Spring Cloud Ribbon 中的 7 种负载均衡策略 Posted: 13 Mar 2022 05:49 PM PDT 负载均衡通器常有两种实现手段,一种是服务端负载均衡器,另一种是客户端负载均衡器,而我们今天的主角 Ribbon 就属于后者——客户端负载均衡器。 服务端负载均衡器的问题是,它提供了更强的流量控制权,但无法满足不同的消费者希望使用不同负载均衡策略的需求,而使用不同负载均衡策略的场景确实是存在的,所以客户端负载均衡就提供了这种灵活性。 然而客户端负载均衡也有其缺点,如果配置不当,可能会导致服务提供者出现热点,或者压根就拿不到任何服务的情况,所以我们本文就来了解一下这 7 种内置负载均衡策略的具体规则。 Ribbon 介绍Ribbon 是 Spring Cloud 技术栈中非常重要的基础框架,它为 Spring Cloud 提供了负载均衡的能力,比如 Fegin 和 OpenFegin 都是基于 Ribbon 实现的,就连 Nacos 中的负载均衡也使用了 Ribbon 框架。 Ribbon 框架的强大之处在于,它不仅内置了 7 种负载均衡策略,同时还支持用户自定义负载均衡策略,所以其开放性和便利性也是它得以流行的主要原因。 服务端负载均衡器和客户端负载均衡器的区别如下图所示: 负载均衡设置以 Nacos 中的 Ribbon 负载均衡设置为例,在配置文件 application.yml 中设置如下配置即可:
因为 Nacos 中已经内置了 Ribbon,所以在实际项目开发中无需再添加 Ribbon 依赖了,这一点我们在 Nacos 的依赖树中就可以看到,如下图所示:
重启客户端,执行结果如下图所示: 7种负载均衡策略1.轮询策略轮询策略:RoundRobinRule,按照一定的顺序依次调用服务实例。比如一共有 3 个服务,第一次调用服务 1,第二次调用服务 2,第三次调用服务3,依次类推。
2.权重策略权重策略:WeightedResponseTimeRule,根据每个服务提供者的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性也就越低。
3.随机策略随机策略:RandomRule,从服务提供者的列表中随机选择一个服务实例。
4.最小连接数策略最小连接数策略:BestAvailableRule,也叫最小并发数策略,它是遍历服务提供者列表,选取连接数最小的⼀个服务实例。如果有相同的最小连接数,那么会调用轮询策略进行选取。
5.重试策略重试策略:RetryRule,按照轮询策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试来获取服务,如果超过指定时间依然没获取到服务实例则返回 null。
6.可用性敏感策略可用敏感性策略:AvailabilityFilteringRule,先过滤掉非健康的服务实例,然后再选择连接数较小的服务实例。
7.区域敏感策略区域敏感策略:ZoneAvoidanceRule,根据服务所在区域(zone)的性能和服务的可用性来选择服务实例,在没有区域的环境下,该策略和轮询策略类似。
项目源码https://gitee.com/mydb/spring-cloud-alibaba-example 总结Ribbon 为客户端负载均衡器,相比于服务端负载均衡器的统一负载均衡策略来说,它提供了更多的灵活性。Ribbon 内置了 7 种负载均衡策略:轮询策略、权重策略、随机策略、最小连接数策略、重试策略、可用性敏感策略、区域性敏感策略,并且用户可以通过继承 RoundRibbonRule 来实现自定义负载均衡策略。
|
You are subscribed to email updates from SegmentFault 最新的文章. To stop receiving these emails, you may unsubscribe now. | Email delivery powered by Google |
Google, 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States |
No comments:
Post a Comment