链路追踪

1、链路追踪介绍 在大型系统的微服务化构建中,一个系统被拆分成了许多模块。这些模块负责不同的功能,组合成系统,最终可以提供丰富的功能。在这种架构中,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。 2.为什么需要链路追踪? 微服务架构是通过业务来划分服务的,使用 REST 调用。对外暴露的一个接口,可能需要很多个服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败。随着业务的不断扩张,服务之间互相调用会越来越复杂。 分布式链路追踪(Distributed Tracing),就是将一次分布式请求还原成调用链路,进行==日志记录==,==性能监控==并将一次分布式请求的调用情况集中展示。比如各个服务节点上的耗时、请求具体到达哪台机器上IP、每个服务节点的请求状态200 500等等。 3.链路追踪使用的组件有哪些? cat 由大众点评开源,基于Java开发的实时应用监控平台,包括实时应用监控,业务监控 。 集成 方案是通过代码埋点的方式来实现监控,比如: 拦截器,过滤器等。 对代码的侵入性很大,集成成本较高。风险较大。 zipkin 由Twitter公司开源,开放源代码分布式的跟踪系统,用于收集服务的定时数据,以解决微 服务架构中的延迟问题,包括:数据的收集、存储、查找和展现《图形化》。该产品结合spring-cloud-sleuth 使用较为简单, 集成很方便, 但是功能较简单。 pinpoint Pinpoint是韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点 是支持多种插件,UI功能强大,接入端无代码侵入。 SkyWalking是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多 种插件,UI功能较强,接入端无代码侵入。目前已加入Apache孵化器。 Sleuth (日志记录每一条链路上的所有节点,以及这些节点所在的机器,和耗时。) log4j SpringCloud 提供的分布式系统中链路追踪解决方案。 注意:SpringCloud alibaba技术栈中并没有提供自己的链路追踪技术的,我们可以采用Sleuth + Zipkin来做链路追踪解决方案。 3.介绍sleuth springCloud Sleuth主要功能就是在分布式系统中提供追踪解决方案。 它大量借用了Google Dapper的设计, 先来了解一下Sleuth中的术语 和相关概念。 *1.Trace* *(一条完整链路--包含很多span(微服务接口))* 由一组Trace Id(贯穿整个链路)相同的Span串联形成一个树状结 构。为了实现请求跟踪,当请求到达分布式系统的入口端点时,只需 要服务跟踪框架为该请求创建一个唯一的标识(即TraceId),同时在 分布式系统内部流转的时候,框架始终保持传递该唯一值,直到整个 请求的返回。那么我们就可以使用该唯一标识将所有的请求串联起 来,形成一条完整的请求链路。 *2.Span* 代表了一组基本的工作单元。为了统计各处理单元的延迟,当请求到 达各个服务组件的时候,也通过一个唯一标识(SpanId)来标记它的 开始、具体过程和结束。通过SpanId的开始和结束时间戳,就能统计 该span的调用时间,除此之外,我们还可以获取如事件的名称。请求 信息等元数据。 *3. Annotation* 用它记录一段时间内的事件,内部使用的重要注释: l cs(Client Send)客户端发出请求,开始一个请求的命令 l sr(Server Received)服务端接受到请求开始进行处理, sr-cs =

python

Python 可以方便的实现计算器的功能。数学意义上的加、减、乘、除在Python中分别以符号“+、-、*、/”表示。 试编程实现分两行输入两个非零浮点数,并在4 行中按顺序输出两个数的加、减、乘、除的计算式和计算结果。计算结果str.format()方法严格保留小数点后3位数字。要求输出与如下示例格式相同,符号前后各有一个空格。 浮点数1 + 浮点数2 = 和 浮点数1 - 浮点数2 = 差 浮点数1 * 浮点数2 = 积 浮点数1 / 浮点数2 = 商 示例 输入: 2.66 3.1415926 输出: 2.66 + 3.1415926 = 5.802 2.66 - 3.1415926 = -0.482 2.66 * 3.1415926 = 8.357 2.66 / 3.1415926 = 0.847 a= float(input()) b= float(input()) print(f'{a} + {b} = {a + b:.3f}') print(f'{a} - {b} = {a - b:.3f}') print(f'{a} * {b} = {a * b:.

国内最佳的Respond.io替代品——SaleSmartly(ss客服)

Respond.io也是一个得力的工具,但国内是否也有这样的集成与营销工具呢?用,比如SaleSmartly(ss客服)。 什么是 Respond.io? Respond.io是一个基于网络的消息传递平台,可将客户从任何渠道连接到多个团队 -营销,销售,支持和工程。该公司总部位于香港。 优点: l它易于使用,并具有用户友好的界面。 l客户支持快速且响应迅速。 l您可以创建客户档案,将所有消息传递、网络聊天、短信和电子邮件交互合并到一个地方。这有助于保存客户的完整上下文,无论他们每次向您发送消息时的通信模式如何。 lRespond.io具有简单的自动化功能,例如标记,分配或自动回复消息。 缺点: l这些工具针对的是企业客户,因此定价可能有点麻烦。 l当潜在客户被添加两次时,它不会将它们识别为重复项。这可能会导致上下文丢失和报告问题。 l提供的功能数量导致系统的复杂性。如果您只想通过几个渠道与观众保持联系,这可能会有点不知所措。 SaleSmartly(ss客服) SaleSmartly(ss客服)是一个工具,它提供了一个多渠道收件箱,可以集成来自不同渠道的消息,如电子邮件,Facebook,WhatsApp等。它还可以帮助您设置通过WhatsApp,Messenger等全渠道的聊天机器人,并支持WhatsApp、email,Facebook营销。 那么为什么说SaleSmartly(ss客服)是Respond.io最佳替代品呢? 原因1: 使用SaleSmartly,您可以将即时聊天连接到一个团队收件箱,连接社媒渠道,如Facebook、Instagram、电子邮件、WhatsApp、Line、Telegram甚至于Slack。 SaleSmartly即时聊天还提供了建立聊天机器人的能力,提升客户回复效率,增加团队之间的协作。 原因2: SaleSmartly为中国卖家量身打造,针对国人跨境的网络、时差、翻译等问题,支持实时翻译,多达200+语种高质量互译,覆盖4万多个语言方向,强大的AI机器人与自动化流程助力客户支持,为您的独立站运营降本增效。 原因3: SaleSmartly性价比超高,灵活的价格体系为不同用户提供优质服务。可免费使用几乎所有功能,付费低至每月9刀。

联想Y9000P W11出现 你的PIN不可用,单击以重新设置PIN,也未设置其他的登录方式时的解决办法

win11出现 你的PIN不可用,单击以重新设置PIN,你也未设置其他登录方式时的解决办法。在全内网环境下。 因为没有设置其他的登录方式,导致无法登陆系统。 重启系统,按F9键,进入菜单选择界面。选择System Recovery。 下一步选择重置此电脑,选择是。 下一步选择仅删除我的文件 ,保留系统文件,删除安装的软件。 到此系统就等着重置了。 

kafka send时指定key遇到的问题

楼主以前使用kafka发送的写法是; public ProducerFactory<String, String> producerFactory() {//设置参数 ... } KafkaTemplate<String, String> kafkaTemplate =new KafkaTemplate<>(producerFactory()); 然后发送 kafkaTemplate.send(TopicName, value.toJSONString()); 参与一个项目flink-cdc项目,使用的是 class FlinkKafkaInternalProducer<K, V> implements Producer<K, V>; 使用 public static Producer producer =createProducer(); producer.send(new ProducerRecord(Topic, sendKey, sendValue)); 其中的sendKey 设置,因为没有这种用法,错误传入 String sendKey类型的参数, 下游的消费者在解析时,就发生报错 switched from RUNNING to FAILED with failure cause: org.apache.flink.shaded.jackson2.com.fasterxml.jackson.core,JsonParseException: Unrecopnized token 'XXXXXXXXX' wasexpecting (JSON String, Number, Array, Object or token 'null','true' or 'false')at[source: (byte[])"TXXXXXXXXXX"; line: 1,column: 19] 原因图里大佬说的很明白了;主题包含的数据不是有效的JSON格式,其中的主题的key也要求是 JSON的格式。 后续尝试: key = JSONObject.

pip下载包报错ERROR: No matching distribution found for xxx时的解决方案

前言 当我们使用python自带的pip安装一些包时,可能会报以下错误: 出现这种情况有三种可能: 第一种可能: pip的版本过低,需要升级一下,可以执行以下命令进行尝试 python -m pip install --upgrade pip 第二种可能: 考虑可能是网速的原因,这时可以采用国内的镜像源来加速 pip install 包 -i https://pypi.tuna.tsinghua.edu.cn/simple/ --trusted-host pypi.douban.com ps :–trusted-host pypi.douban.com 这是为了获得ssl证书的认证 常见pip镜像源(国内源) 清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/ 华中理工大学:http://pypi.hustunique.com/ 山东理工大学:http://pypi.sdutlinux.org/ 豆瓣:http://pypi.douban.com/simple/ 第三种可能: 检查下是否开启代理或者VPN,将其关闭再使用国内镜像进行尝试看看是否可以解决,我这边就是代理开启导致网络太慢而报错的。

el-table中的文本居中

el-table中的文本居中 1、整个表格和内容居中的方式: header-cell-style设置头部居中;cell-style设置单元格内容居中 <el-table :data="tableData" :header-cell-style="{'text-align':'center'}" :cell-style="{'text-align':'center'}" style="width: 100%"> </el-table> 2、单个表格的内容居中: 只需要在el-table-column上加上align=‘center’ <el-table-column label="姓名" prop="realname" align="center"> </el-table-column>

C# 数组和集合

数组概述 数组从字面上理解就是存放一组数,但在 C# 语言中数组存放的并不一定是数字,也可以是 其他数据类型。 数组的特点: 1.在一个数组中存放的值都是同一数据类型的。 2.数组中某个指定的元素是通过索引来访问的。 3.所有的数组都是由连续的内存位置组成的。 4.数组从零开始建立索引,即数组索引从零开始。 一维数组的创建、一维数组的初始化、一维数组的使用 一维数组 一维数组在数组中最常用,即将一组值存放到一个数组中,并为其定义一个名称,通过数组中元素的位置来存取值。 定义一维数组的语法形式如下: 1 //定义数组 2 数据类型[] 数组名; 1 //初始化数组中的元素 2 数据类型[] 数组名 = new 数据类型[长度]; 3 数据类型[] 数组名 = {值 1, 值 2, ...} 4 数据类型[] 数组名 = new 数据类型[长度]{值 1,值 2,...} 举例如下: int[] i = {1,2,3,6,5,4,7,8,9 }; for (int i1 = 0; i1 < i.Length; i1++) { MessageBox.Show(i[i1].ToString()); } 多维数组的创建、多维数组的初始化、多维数组的使用 多维数组是指二维或二维以上的数组。一般我们最常用的是二维数组。 定义多维数组的语法形式如下。 1 //定义多维数组 2 数据类型[ , , .

运算放大器基础2——用作缓冲器/跟随器

今天我们学习带有反馈的运放电路。最简单的反馈,就是将运放输出直接接到运放的反相输入端,这种电路有一个特定的名称——“缓冲器/跟随器”(Buffer Amplifier),其输出总是跟随着输入,主要的作用是阻抗变换。以下,我们来逐一分析。 一、缓冲器/跟随器 对于任何有反馈的运放电路,我们需要记住两条原则: 运放反相和正相输入端电压总是相等运放反相和正相输入端没有电流输入 运放作为缓冲器的电路如下: 图1-运放作为缓冲器电路 对于缓冲器电路,由于输出直接连接了反相输入,根据上述两条原则,所以Vout = Vin+ = Vin-。 可见,运放此时并没有放大电压,那运放起了什么作用? 答案是阻抗变换。 二、阻抗变换 我们知道电源有内阻,负载有阻抗(不考虑频率响应的话,阻抗就等于电阻)。 图2-电源内阻与负载阻抗 对于电压型负载来说,电源内阻越小、负载阻抗越大越好,这样它获得的电压越大。 如果电源内阻较大,而负载阻抗较小,那负载就无法获得较高份额的电压。 对于这种情况,需要加入缓冲器: 图3-通过运放缓冲器作为阻抗变换 缓冲器的特点是输入阻抗无穷大,而输出阻抗又很小,在它后面接上负载,可以让负载保证获得较大电压。 三、缓冲器/跟随器案例 我们来构建一个案例,如下图,电源输入是12V,通过稳压二极管获得9V电压,后又经过两个10KΩ电阻分压获得4.5V电压,并以此为负载供电。 那么,假设我们的负载是200Ω,如果直接到10KΩ电阻上,负载上的电压是多少呢?还是4.5V吗? 图4-负载直接接在10KΩ电阻上,负载电压降低 可见,实际负载的电压只有173mV。大家可以通过KVL公式(基尔霍夫电压定律)计算一下是不是这个结果。 如果通过运放缓冲器接到10KΩ电阻上,是什么结果呢? 图5-负载通过缓冲器接在10KΩ电阻上,负载电压稳定 可见,由于运放的高输入阻抗、低输出阻抗,使得最终负载获得的电压还是4.5V。

Spring AOP(面向切面编程)和方法拦截

Spring AOP(面向切面编程)和方法拦截 Spring是一款广泛使用的Java开发框架,提供了丰富的功能和工具,用于简化企业级应用程序的开发。其中一个重要的特性是面向切面编程(AOP)和方法拦截。本文将介绍Spring AOP和方法拦截的概念、工作原理以及在实际开发中的应用。 1. 引言 在软件开发中,常常会面临一些横切关注点(Cross-cutting Concerns),例如日志记录、性能监控、安全验证等。这些关注点会散布在应用程序的不同模块中,造成代码的重复和维护的困难。面向切面编程(AOP)通过将这些关注点从核心业务逻辑中分离出来,实现了更好的模块化和可维护性。 2. Spring AOP的概念 Spring AOP是Spring框架提供的一种AOP实现方式。AOP通过在程序运行期间动态地将额外的行为织入到现有的代码中,以实现横切关注点的功能。Spring AOP基于代理模式,使用动态代理技术生成代理对象,从而实现方法拦截和增强。 3. Spring AOP的工作原理 Spring AOP主要依赖于两个核心概念:切点(Pointcut)和通知(Advice)。 切点定义了在程序执行过程中哪些方法需要被拦截。它使用表达式或者注解来指定目标方法的匹配规则。例如,可以通过表达式匹配所有以"get"开头的方法,或者使用注解标记特定的方法。 通知定义了在切点处执行的额外逻辑。Spring AOP提供了多种类型的通知,包括前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知(Around)。开发人员可以根据需要选择适当的通知类型,并编写对应的逻辑。 在运行时,Spring AOP会根据切点的定义自动识别目标方法,并将通知的逻辑织入到目标方法的前、后或异常处理等关键位置。 4. 方法拦截的应用场景 方法拦截是Spring AOP的一种常见用法,可用于实现各种横切关注点的功能。以下是几个常见的应用场景: 4.1 日志记录 通过方法拦截,可以在方法执行前后记录方法的调用信息,例如方法名、参数和返回值等。这对于调试和追踪应用程序的执行流程非常有帮助。可以在前置通知中记录方法的入参信息,在后置通知中记录方法的返回值,以及在异常通知中记录方法抛出的异常信息。通过方法拦截实现的日志记录功能可以统一管理和配置,提高代码的可读性和可维护性。 4.2 安全验证 在应用程序中进行安全验证是一项重要的任务。方法拦截可以用于实现权限验证、身份验证等安全相关的功能。通过在前置通知中进行验证,可以在方法执行前对用户的身份和权限进行检查,以确保只有具备合法权限的用户才能执行特定的方法。 4.3 性能监控 性能监控是优化和调优应用程序的关键方面之一。方法拦截可以用于实现对方法执行时间的监控和统计。通过在前置通知中记录方法的开始时间,在后置通知中记录方法的结束时间,可以计算方法的执行时间,并进行性能分析和优化。 4.4 事务管理 在数据库操作等涉及到数据一致性的场景中,事务管理是非常重要的。方法拦截可以用于实现声明式的事务管理,即通过在方法执行前后自动开启、提交或回滚事务。这样可以简化事务管理的代码,提高代码的可读性和可维护性。 5. 实例演示 以下是一个简单的示例演示了Spring AOP和方法拦截的使用: public interface UserService { void addUser(User user); } public class UserServiceImpl implements UserService { @Override public void addUser(User user) { // 添加用户的逻辑 } } public class LogInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { // 在方法执行前记录日志 System.

mac如何升级node版本、切换node版本

一、mac如何升级node版本 当前官网稳定版本是18.15.0 所以我从v14.17.4升级到v18.15.0 二、mac如何切换node版本 切换到16.20.0版本 三、mac可以用node.js的多版本管理器n来升级和切换,命令如下: 1、sudo npm cache clean -f //清除node.js的cache 2、sudo npm install -g n //使用npm安装n模块 3、npm view node versions // 查看node所有版本 4、sudo n latest // 升级到最新版本 sudo n stable // 升级到稳定版本 sudo n xx.xx // 升级到具体版本号 5、node -v //查看当前安装的版本号 6、n //检查目前安装了哪些版本的node,会出现已安装的node版本,选一个就可以直接切换了 ⚠️windows可以用nvm切换node版本

Apollo oracle适配

前言:公司数据库统一切换为oracle,减少部署mysql,现需要将Apollo的数据库做oracle适配,当前使用版本为Apollo2.0.0,网上找到最新版本的适配oracle的版本也仅为1.4.0,现决定自己适配。 部分参考了官方介绍的改造文档:https://github.com/apolloconfig/apollo/compare/v0.8.0...vanpersl:db-oracle Apollo版本 2.0.0 Oracle版本:12c 0.oracle添加用户和数据库 添加俩用户 APOLLOPORTALDB 默认数据库为APOLLOPORTALDB APOLLOCONFIGDB 默认数据库为APOLLOCONFIGDB 1.添加oracle驱动,替换掉mysql驱动 搜索引入mysql驱动的地方,删除后添加oracle驱动, <dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc8</artifactId> <version>12.2.0.1</version> </dependency> 2.修改默认jdbc驱动 # DataSource #spring.datasource.hikari.connectionInitSql=set names utf8mb4 spring.datasource.driver-class-name=oracle.jdbc.OracleDriver spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle12cDialect 3.原先数据库初始化脚本改造 3.1 因为oracle不加双引号默认字段和表名会转成大写,所以干脆全转成大写 3.2 oracle索引全局不能重复,但是Apollo不同表索引名有重复的,给每个表索引名称加表名前缀 3.3 oracle不支持自增,SPRING_SESSION表用到了自增,所以需要通过oracle的序列实现自增,这个官方有说明 https://github.com/spring-projects/spring-session/blob/faee8f1bdb8822a5653a81eba838dddf224d92d6/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-oracle.sql 最终修改完的SQL会最后上传 因一个数据库共用一个序列,插入数据的时候可能会出现一个表自增不连续的情况,不影响 4.Hibernate框架的字段表映射统一转大写加双引号 解决原先字段中包括oracle关键字问题 添加类 package com.ctrip.framework.apollo.common.utils; import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; public class OracleUpperCaseStrategy extends PhysicalNamingStrategyStandardImpl { private static final long serialVersionUID = 1383021413247872469L; @Override public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) { // 将表名全部转换成大写,加双引号解决字段或表名是oracle关键字 String tableName = "

(附源码)springboot水环境检测系统的设计与实现 毕业设计041446

水环境检测系统的设计与实现 摘 要 在我国,水源的污染是不可忽视的问题。对于水质监测进行数据的采集工作,目前主要通过人工实现。因此,部分地区的采集工作,实施起来难度很大,比如恶劣环境和偏僻山区等地。所以,目前对于水质监测的研究,主导方向是建立更加高效完善,智能化的水质监测系统。近几年,无线传感器网络迅猛发展,基于此,本文设计研究出一套物联法基础上的水环境监测系统。 系统主要针对水环境监测业务开展,涉及监测点管理、水环境监测数据管理、项目信息管理等方面。本设计主要实现集人性化、高效率、便捷等优点。系统使用Java语言的Springboot框架,采用MVVM模式进行开发,数据方面主要采用的是微软的Mysql关系型数据库来作为数据存储媒介,配合前台技术完成系统的开发。 关键词:水环境监测;Springboot框架;关系型数据库 Design and implementation of water environment detection system Abstract In China, the pollution of water source is a problem that can not be ignored. At present, data collection for water quality monitoring is mainly realized manually. Therefore, the collection work in some areas is very difficult to implement, such as harsh environment and remote mountainous areas. Therefore, the current research on water quality monitoring is to establish a more efficient, perfect and intelligent water quality monitoring system.

垃圾回收器之CMS

CMS是一款基于“标记-清除”算法的垃圾回收器,用于老年代的回收。 CMS的大概处理流程为:初始标记-并发标记-重新标记-并发清除。为什么需要重新标记呢,因为在并发标记阶段,用户线程和标记线程同时运行,这时会出现之前标记的对象发生了变化,需要等并发标记结束后,重新标记这一部分对象。当重新标记结束后,进行并发清除可回收对象。在初始标记和重新标记时,会导致stop the world,但这个时间远比并发标记时间短,可极大压缩停止时间。初始标记只是简单标记下GC ROOTS可达的节点,并发标记时进行GC ROOTS Tracing的过程。 CMS垃圾回收器有一部分缺陷。 1.抢占cpu资源,并发操作就需要创建线程,创建了额外的线程会抢占cpu资源。CMS的默认线程数计算公式为:(cpu数量+3)/4,当cpu数量大于4时,会创建一个线程,这时线程数量占25%,影响不大,但当数量小于4时,会基本占用50%的资源,严重影响业务线程的执行时间。虽然后来提供了i-cms垃圾回收器,在并发标记、清除阶段,试图通过交替运行用户线程,减少这种影响,但效果不明显。 2.无法处理浮动垃圾。在CMS进行并发清除阶段,用户线程也在运行,会产生新的对象,这部分称为浮动垃圾。CMS在清除时,无法处理浮动垃圾,而这部分数据需要内存空间存放,所以CMS不能等到内存空间完全占满时运行,在1.5版本时,达到68%的老年代空间时进行清除,但启动过早,会导致垃圾回收频繁,-XX:CMSInitiatingOccupancyFraction参数可调整阈值。在1.6版本时,此值为92%,大大提供了垃圾回收效率,但是会引发另一个问题Concurrent Mode Failure。此问题是,当预留空间无法满足浮动垃圾需求时发生的。这种情况下,CMS垃圾回收器会被强制转换为serial old,进行回收,而serial old会大大降低系统响应时间,需要更多的stop the world。 3.产生垃圾碎片。CMS垃圾回收器是基于标记清除算法的,所以会生成垃圾碎片,当大对象进来时,老年代没有足够空间提供时,会产生fullGC。CMS提-XX:UseCMSCompactAtFullCollection参数设置当老年代空间不足时,先进行整理,整理后不足才进行fullGc,但整理的过程非常慢,每次都进行整理会导致碎片问题没有了,停顿时间变长了。所以又提供了-XX:CMSFullGCsBeforeCompaction,这个参数用于设置执行多少次不整理的FullGc后,执行一次带整理的,默认值为0,每次都需要整理。 -XX:CMSInitiatingOccupancyFraction=92 和-XX:+UseCMSInitiatingOccupancyOnly -XX:+UseCMSInitiatingOccupancyOnly 只是用设定的回收阈值(上面指定的70%),如果不指定,JVM仅在第一次使用设定值,后续则自动调整. -XX:+CMSScavengeBeforeRemark 在CMS GC前启动一次ygc,目的在于减少old gen对ygc gen的引用,降低remark时的开销-----一般CMS的GC耗时 80%都在remark阶段 当内存增加缓慢的时候,阈值X可以设置大一点,可以使CMS回收的次数降低;如果内存增加比较快,阈值X可以设置小一点,以至于不会出现因在FullGc时空间不足,导致使用serial old回收器的情况 CMS垃圾回收器进行FullGc的情况列举如下: 1). 判断UseCMSInitiatingOccupancyFraction和UseCMSInitiatingOccupancyOnly是否为true,如果为false,设CMS根据数据决定是否要进行GC 2). 如果为true,判断老年代空间使用率是否到达UseCMSInitiatingOccupancyFraction,如果大于则GC,小于则不GC 3). 上一次ygc失败 4). 是否有gc请求,例如调用了System.gc() 5). 是否在进行堆扩容,如果是的话则GC 6). 判断是否会晋升失败(即老年代是否有空间容纳晋升对象),如果晋升失败则GC 7). 在jdk8中会判断Metaspace空间是否需要回收 FullGc条件: 第一个,对象年龄太大了,这种对象一般很少,都是系统中确实需要长期存在的核心组件,他们一般不需要被回收掉,所以在新生代熬过默认15次垃圾回收之后就会进入老年代。第二个,动态年龄判定规则,如果一次新生代gc过后,发现Survivor区域中的几个年龄的对象加起来超过了Survivor区域的50%,比如说年龄1+年龄2+年龄3的对象大小总和,超过了Survivor区域的50%,此时就会把年龄3以上的对象都放入老年代。第三个,新生代垃圾回收过后,存活对象太多了,无法放入 Surviovr中,此时直接进入老年代。 可中断的预清理 可中断的预清理作用如上说的,另外有个重要意义是,如果在这个阶段如果等到了一个YGC,那么新生代会少很多无用的对象,到了重标记阶段就会少扫描很多的新生代对象,停顿时间会少很多。 和预清理的不同的是,可中断的预清理有限制条件,会根据配置的参数来决定是否需要进入或者退出该阶段,几个参数如下: CMSScheduleRemarkEdenSizeThreshold:如果小于该值则不进入该阶段CMSMaxAbortablePrecleanTime:如果执行时间超过该值,则退出该阶段CMSScheduleRemarkEdenPenetration:如果eden使用空间大于该值,则退出该阶段CMSMaxAbortablePrecleanLoops:如果执行次数大于该值,则退出该阶段 并不是内存越大越好,当内存大时,首先新生代增大,会导致youngGc时间变长,而这是最频繁的Gc,正常一次是20ms,当内存增大到16G时,会出现停顿几秒钟的情况,当停顿出现时,会导致请求积压,进而导致系统越来越慢,Gc越来越频繁。 采用G1垃圾回收器,G1可对年轻代进行Gc停顿时间设置,可保证youngGc每次只停顿100ms,回收一部分regin区域的内存,频率会提高,但停顿变小 下面给出通用cms垃圾回收器配置参数: -server -Xms5G -Xmx5G -server -XX:MaxPermSize=256M -Xss256K XX:MaxMetaspaceSize=512m -XX:MetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/export/Logs -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=6 -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled -XX:+UseCMSInitiatingOccupancyOnly

【Vue3+TS项目】硅谷甄选day02--后台管理系统模板搭建/项目配置

1 项目初始化 一个项目要有统一的规范,需要使用eslint+stylelint+prettier来对我们的代码质量做检测和修复,需要使用husky来做commit拦截,需要使用commitlint来统一提交规范,需要使用preinstall来统一包管理工具。 1.1 环境准备 node v16.14.2 pnpm 8.0.0 1.2 初始化项目 本项目使用vite进行构建,vite官方中文文档参考:cn.vitejs.dev/guide/ pnpm:performant npm ,意味“高性能的 npm”。pnpm由npm/yarn衍生而来,解决了npm/yarn内部潜在的bug,极大的优化了性能,扩展了使用场景。被誉为“最先进的包管理工具” pnpm安装指令: npm i -g pnpm 项目初始化命令: pnpm create vite 进入到项目根目录pnpm install安装全部依赖,安装完依赖运行程序:pnpm run dev 运行完毕项目跑在http://127.0.0.1:5173/,可以访问你得项目啦 可能出现的问题 Cannot find module './App.vue' or its corresponding type declarations 报错原因:typescript 只能理解 .ts 文件,无法理解 .vue文件 解决方法1:安装 volar 插件,输入 volar ,有多个扩展程序,能起作用的是 Typescript Vue Plugin(Volar) 之前 vscode 检测到 vue3 ,自动推荐安装了 Vue Language Feature(Volar),但用它扔有类型报错。官方推荐,使用它时禁用 Vetur,以免有冲突。 解决方法2:创建vite项目后,项目根目录会有一个 “env.d.ts” 文件,找到该文件,在里面添加一下代码 declare module "*.vue" { import { DefineComponent } from "

CesiumJs学习笔记4

此为课程Three.js可视化企业实战WEBGL课的CesiumJs篇学习笔记 加载 GEOJSON 数据 json数据 在阿里云 下载 加载初始化 // 加载geojson数据 let dataGeo = Cesium.GeoJsonDataSource.load( "https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json", ); // 可以直接add这个promise // viewer.dataSources.add(dataGeo); dataGeo.then((dataSources) => { console.log(dataSources); viewer.dataSources.add(dataSources); }); 设置边框和内填充色 // 加载geojson数据 let dataGeo = Cesium.GeoJsonDataSource.load( "https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json", { stroke: Cesium.Color.RED, fill: Cesium.Color.SKYBLUE.withAlpha(0.5), strokeWidth: 3 } ); dataGeo.then((dataSources) => { viewer.dataSources.add(dataSources); }); 获取实体并且改变样式 // 加载geojson数据 let dataGeo = Cesium.GeoJsonDataSource.load( "https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json", { stroke: Cesium.Color.RED, fill: Cesium.Color.SKYBLUE.withAlpha(0.5), strokeWidth: 3 } ); dataGeo.then((dataSources) => { viewer.dataSources.add(dataSources); let entities = dataSources.

整理了18个Python爬虫实战案例

目录 爬虫小工具 文件下载小助手 爬虫实战 笔趣看小说下载 VIP视频下载 百度文库文章下载_rev1 百度文库文章下载_rev2 《帅啊》网帅哥图片下载 构建代理IP池 《火影忍者》漫画下载 财务报表下载小助手 一小时入门网络爬虫 抖音App视频下载_rev1 抖音App视频下载_rev2 抖音App视频下载_rev3 GEETEST验证码破解 12306抢票小助手 百万英雄答题辅助系统 网易云音乐批量下载 B站视频和弹幕批量下载 其它 爬虫小工具 downloader.py:文件下载小助手 一个可以用于下载图片、视频、文件的小工具,有下载进度显示功能。稍加修改即可添加到自己的爬虫中。 动态示意图: 爬虫实战 1、biqukan.py:《笔趣看》盗版小说网站,爬取小说工具 第三方依赖库安装: pip3 install beautifulsoup4 使用方法: python biqukan.py 2、video_downloader:爱奇艺等主流视频网站的VIP视频破解助手(暂只支持PC和手机在线观看VIP视频!) 感谢Python3二维码生成器作者: https://github.com/sylnsfar/qrcode 编译好的软件下载连接:https://pan.baidu.com/s/1bqSTNJL 密码:p8bs 解压密码:cuijiahua.com 无需Python3环境,在Windows下,解压即用!软件使用方法 源码可查看video_downloader,运行源码需要搭建Python3环境,并安装相应第三方依赖库: 在video_downloader文件夹下,安装第三方依赖库: pip3 install -r requirements.txt 使用方法: python movie_downloader.py 运行环境: Windows, Python3Linux, Python3Mac, Python3 3、baiduwenku.py: 百度文库word文章爬取 原理说明: http://blog.csdn.net/c406495762/article/details/72331737 代码不完善,没有进行打包,不具通用性,纯属娱乐,以后有时间会完善。 4、shuaia.py: 爬取《帅啊》网,帅哥图片 《帅啊》网URL:http://www.shuaia.net/index.html 原理说明: http://blog.csdn.net/c406495762/article/details/72597755 第三方依赖库安装: pip3 install requests beautifulsoup4 5、daili.

如何调用api接口获取其中的数据

part1.API接口可以运用到的场景,主要包括以下几个方面: 1. 应用程序集成:API可以使不同的应用程序相互之间进行集成,比如将某个应用程序的数据传递给另一个应用程序,或者调用另一个应用程序的功能。 2. 数据共享:API可以用来共享数据,从而使不同的应用程序可以访问同一组数据。这样做可以降低重复代码的数量,并使开发过程更加高效、稳定。 3. 服务端编程:API可以用于服务端编程,其可以向客户端提供服务。比如计算某个值、存储或获取某个数据等。 4. 移动应用程序编程:API可以用于移动应用程序中,从而实现各种功能。比如,使用地图API以显示地图、调用社交媒体API以分享或访问社交媒体数据等。 5. 自动化流程编程:API可用于帮助自动化流程编程,比如能调用企业内部系统的API,让系统之间的信息沟通起来,进而自动建设和运营流程,节省手动操作成本和时间。 总的来说,API接口具有广泛的应用场景,可以使不同的应用程序互相沟通、集成、共享数据、提供服务,进而减少重复代码,提高开发效率和应用程序的质量。 part2.调用API接口获取数据的具体步骤如下: 1. 确认API接口的请求地址和所需参数:需要先查看API文档,了解所要访问的API接口的请求地址和请求参数,以便正确地构造请求和获取数据。 2. 发送API请求:需使用HTTP协议发出请求,包括POST、GET、PUT等请求方式。其中GET方式一般用于获取数据,POST方式一般用于提交数据,PUT方式一般用于更新数据。根据接口要求,构造相应的请求方式并发送API请求。 3. 等待响应结果:API接口请求发送完成后,需要等待API响应结果。一般来说,在请求成功的情况下,API接口会返回应答内容,如果请求失败,则返回错误信息。 4. 解析API响应:获取API接口返回的内容后,需要将返回的内容进行解析,取出所需要的数据。 5. 对数据进行处理:获取数据后,需要将其转换为程序可以使用的格式,并进行相应的处理和操作。 6. 显示或存储数据:最后,需要将获取到的数据进行显示或存储,根据具体的业务需求进行相应的操作。 需要注意的是,调用API接口获取数据涉及到网络连接,需要保证网络状况良好。同时需要检查API文档,确保请求参数和响应的数据格式正确,以确保数据能够被正确地解析和使用。建议开发者使用专业的API请求工具,如Postman、Insomnia等工具进行测试和调试,以提高开发效率和准确性。

CSS transform属性

一,transform(变形) 1.transform字面的意思就是变形的意思,在CSS3中,transform支持的几个操作有 (1)旋转rotate、 (2)扭曲skew、 (3)缩放scale (4)移动translate (5)矩阵变形matrix。 2.transform不会触发回流,和重绘。 二,transform各操作使用介绍 1.rotate(xx deg)(2D), rotateX()(3D), rotateY()(3D):以中心为基点,deg表示旋转的角度,为负数时表示逆时针旋转。 2.translate(x,y) ,translateX(x) ,translateY(y):以中心为基点按照设定的x,y参数值,对元素进行进行平移。 3.scale(x,y),scaleX(x,1), scaleY(1,Y):缩放基数为1,如果其值大于1元素就放大,反之其值小于1为缩小。 4.skew(x,y), skewX(x), skewY(y):以中心为基点,第一个参数是水平方向扭曲角度,第二个参数是垂直方向扭曲角度。 三,基点 1.所有操作的默认的基点都在中心位置,我们可以使用transform-origin:(x,y)来改变元素基点。 x可以取left,center ,right,是水平方向取值,也可以取对应的百分值为left=0%;center=50%;right=100% y可以取top ,center, bottom,是垂直方向的取值,其中top=0%;center=50%;bottom=100%; #tran{ transform-orgin:(left,top); transform:rotate(30deg); } 四,浏览器兼容 1.目前transform只支持IE10+,对IE9不支持,要兼容浏览器需要添加前缀 { transform:translate(10,10) // W3c标准 -webkit-transform:translate(10,10) // Safari Chrome -moz-transform:translate(10,10) // firefox -ms-transform:translate(10,10) // IE9 -o-transform:translate(10,10) // opera }

从零开始手写一个http-basic认证服务器

简单了解HTTP HTTP是英文HyperText Transfer Protocol首字母缩写,是目前WWW万维网通讯标准协议,在属于OSI第七层(应用层)协议,要实现HTTP协议通常需要基于TCP-Socket套接字作为传输层的支撑。 什么是http-basic http-basic是http协议的认证模块,http-basic也是http协议下的协议。下面先来看一下http-basic协议流程图: 流程图说明: 第一步:当客户端通过浏览器访问实现了http-basic的后端服务器时,后端服务器首先会校验是否携带Authorization请求头,如果没有则返回Code=401: http.setCode(401); http.setStatus("Unauthorized"); // 其中Basic表示认证类型为Basic,Realm用来描述后端应用名称,例如OA,CRM,可自定义 // 除了Basic认证类型外,后面还会将另一种类型:Digest http.setHeader("WWW-Authenticate", "Basic Reaml=\"HTTP Demo Server\""); 下面是谷歌浏览器默认抓包截图: 此时用户就会收到浏览器弹出的登陆输入框: 第二步:当用户输入用户名和密码,点击登陆按钮时,浏览器会将表单的用户名和密码按规则:BASE64(用户名:密码)编码后放到请求头为HTTP-Request-Header=Authorization: Basic cm9vdDoxMjM0NTY= 方式提交给服务器进行认证,具体截图如下: 第三步:后端服务器接收到请求后,仍然会校验是否携带Authorization请求头,如果携带,则通过BASE64解码出来得到用户名:密码字符串,然后通过":"进行分隔得到用户名和密码进行验证,如果验证失败,继续第一步的内容,如果验证成功,后端服务可能会进一步验证URL资源权限等,如果验证资源权限不通过,此时参考第一步的方式返回(注意此时返回Code=403): http.setCode(401); http.setStatus("Forbidden"); http.setHeader("WWW-Authenticate", "Basic Reaml=\"HTTP Demo Server\""); 如果验证通过,则返回Code=200即可: http.setCode(200); http.setStatus("OK"); http-basic缺陷 http-basic(当响应头WWW-Authenticate:Basic Reaml=xxx)存在以下缺陷: 1、用户名和密码明文(仅仅只是Base64编码而已)传输,需要配合HTTPS来保证信息传输的安全。 2、就算HTTPS将密码加密传输,也仍然存在重放攻击风险。 3、代理和中间节点的防护措施弱,很容易通过伪装服务器来骗过认证,诱导用户输入用户名和密码。 下面将介绍http-basic升级版更为安全的摘要认证http-digest。 了解http-digest流程 http-digest流程比http-basic流程复杂很多,流程图如下: 下面对http-digest涉及的字段作用进行说明: WWW-Authentication:用来定义使用何种方式(Basic、Digest、Bearer等)去进行认证以获取受保护的资源。 realm:表示Web服务器中受保护文档的安全域(比如OA、CRM系统域等),用来指示需要哪个域的认证。 qop:保护质量,包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略,可以为空,但不推荐为空值。 nonce:服务端向客户端发送质询时附带的一个随机数,这个数会经常发生变化。客户端计算密码摘要时将其附加上去,使得多次生成同一用户的密码摘要各不相同,用来防止重放攻击。 nc:nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量。例如,在响应的第一个请求中,客户端将发送“nc=00000001”。这个指示值的目的是让服务器保持这个计数器的一个副本,以便检测重复的请求。 cnonce:客户端随机数,这是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护。 response:这是由用户代理软件计算出的一个字符串,以证明用户知道口令。 Authorization-Info:用于返回一些与授权会话相关的附加信息。 nextnonce:下一个服务端随机数,使客户端可以预先发送正确的摘要 rspauth:响应摘要,用于客户端对服务端进行认证。 stale:当密码摘要使用的随机数过期时,服务器可以返回一个附带有新随机数的401响应,并指定stale=true,表示服务器在告知客户端用新的随机数来重试,而不再要求用户重新输入用户名和密码了。 http-digest流程说明 第一步:当客户端通过浏览器访问实现了http-digest的后端服务器时,后端服务器首先会校验是否携带Authorization请求头,如果没有则返回Code=401: http.setCode(401); http.setStatus("Unauthorized"); // 其中Basic表示认证类型为Basic,Realm用来描述后端应用名称,例如OA,CRM,可自定义 // 除了Basic认证类型外,后面还会将另一种类型:Digest http.setHeader("WWW-Authenticate", "Basic Reaml=\"HTTP Demo Server\"

Element-UI el-select多选表单校验问题

在使用 el-select 多选下拉菜单配置表单校验时, 如果form表单绑定的form对象对应属性值为空字符串或者null(其他未尝试),表单中的多选下拉框会立刻执行校验并弹出校验信息,代码如下: <el-form :model="form" :rules="settingFormRules"> <el-form-item prop="level"> <span slot="label"> 级别<span style="color: #B9BBC4">(支持多选)</span> </span> <el-select v-model="form.level" multiple placeholder="请选择" style="width:100%"> <el-option v-for="item in levelOptions" :key="item.id" :label="item.level_name" :value="item.id" /> </el-select> </el-form-item> <el-form-item prop="info"> <span slot="label"> 信息<span style="color: #B9BBC4">(支持多选)</span> </span> <el-select v-model="form.info" multiple placeholder="请选择" style="width:100%"> <el-option v-for="item in infoOptions" :key="item.id" :label="item.infor_name" :value="item.id" /> </el-select> </el-form-item> </el-form> data() { return { form: { level: '', info: null }, rules: { level: [{ required: true, message: '请选择级别', trigger: 'change' }], info: [{ required: true, message: '请选择信息', trigger: 'change' }], } } } 正确方式如下: 将多选下拉框对应的属性值默认值设置未空数组即可

哈夫曼树(结合王卓老师课程内容)

目录 1、哈夫曼树的基本概念 2、哈夫曼树的构造方法 3、哈夫曼树的算法实现 先分析: 第一步: 第二步: 再实现: 第一步 : 第二步: 4、哈夫曼树编码思想 5、哈夫曼编码的算法实现。 6、文件的编码和译码 7、根据哈夫曼树求哈夫曼编码的完整代码: 8、 以26个英文字母的频率为权构造一棵哈夫曼树: 1、哈夫曼树的基本概念 路径从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径。路径长度路径上的分支数目称作路径长度。树的路径长度从树根到每一结点的路径长度之和。结点的带权路径长度从该结点到树根之间俺的路径长度与结点上权值的乘积。树的带权路径长度树中所有叶子结点的带权路径长度之和。(WPL) 2、哈夫曼树的构造方法 ██ 哈夫曼算法口诀:1、构造森林全是根;2、选用两小造新树;3、删除两小添新人;4、重复2、3剩单根。 ██ 上面的例子,有四个结点,由哈夫曼算法口诀,先找出两个小的结点,即 c 和 d,由 c 和 d结合造一棵新树 ,即图中蓝色区域,然之后在第一个黑框中重复2、3;即在7,5,6这三个结点里选择另个小的结点,组成一棵树即绿框区域。接着再将7,11,这两个结点结合成一棵树。 ✔总结哈夫曼树的特点: 1、哈夫曼树的结点的度数为0或者2,没有度为1的结点。 2、在哈夫曼算法中,初始时有n棵二叉树,要经过n-1次合并最终形成哈夫曼树。 3、经过n-1次合并产生n-1个新结点,且n-1个新结点都是具有两个孩子的分支结点。 所以哈夫曼树中共有2n-1个结点,且其所有的分支结点的度均不为1. 3、哈夫曼树的算法实现 先分析: 第一步: 采用顺序储存结构——一维结构数组 (哈夫曼树中共有2n-1个结点,我们不适用0下标,所以定义数组大小为2n) 举个栗子: 有n=8,权值为W={7,19,2,6,32,3,21,10} 构造哈夫曼树。 由上面的哈夫曼算法口诀“构造森林全是根”,所以先将结点的父母和左右子树全置为0.然后将结点1-8的权值先附上。 第二步: 然后口诀里的下一步是“选用两小造新树”,那么我们就在1-8里找权值最小的,也就是2和3,然后我们就把它们结成一个新树,如上右图。第三句口诀是“删除两小添新人”。删除也就是把两个权值小的结点的双亲改为非0. 添新人,也就是把合并两个小的权值作为一个新结点的权值依次存放如数组。在这里例子里,也就是2和3的权值和为5,那就将5存放在9的位置。(完成添新人这一操作) 然后将权值为2和3的结点的双亲改为9. (完成删两小这一操作) 那么这一步的操作就完成了。接下来依次循环。那么最后的哈夫曼树如下: 再实现: 第一步 : 也就是口诀里的第一步“构造森林全是根”。 上面例子的话就是将结点的父母和左右子树全置为0.然后将结点1-8的权值先附上的这一步。 第二步: 也就是口诀里的2、选用两小造新树;3、删除两小添新人; 即上述例子里的第二步。 红色框框里的Select() 是选择两个权值最小的结点的函数 具体如下: void Select(HuffmanTree HT,int len,int &s1,int &s2) { int i,min1=0x3f3f3f3f,min2=0x3f3f3f3f;//先赋予最大值 for(i=1;i<=len;i++) { if(HT[i].

springboot结合ip2region

1.需求 产品要求:按用户ip自动获取城市。 2.解决 在网上找了挺久的,找到一个是线上版本和离线版本 1.线上版本 线上链接 还有离线版本经过技术主管的选型决定使用离线版本,因为跟我们的实际情况贴近。 2.离线版本开源项目ip2region 1.导入Maven包 GitHub地址:https://github.com/lionsoul2014/ip2region 它有分新版跟旧版不建议旧版因为有坑,我已经踩过建议喜新厌旧。 <dependency> <groupId>org.lionsoul</groupId> <artifactId>ip2region</artifactId> <version>2.7.0</version> </dependency> 2.导入ip2region.xdb 注意是放在resources底下 3.获取IP地址工具类 package io.geekidea.springbootplus.framework.util; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.lionsoul.ip2region.xdb.Searcher; import org.springframework.core.io.ClassPathResource; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.io.InputStream; import java.net.InetAddress; import java.net.UnknownHostException; /** * 获取IP地址工具类 * @author geekidea * @date 2018-11-08 */ @Slf4j public final class IpUtil { private static final String UNKNOWN = "unknown"; private static final String IPV6_LOCAL = "

开发功能归纳

例子都有对应测试数据可以跑通查看 目录 1.搜索跳转,判空后再执行后续动作2.自定义下拉框,点击后需要赋值给匹配name名的input存值3.同级标签切换类名逻辑4.页面滚动某个距离给标签添加类名5.监听鼠标滚轮 滚动事件(需要引入jquery.mousewheel.min.js)6.swiper-点击按钮实现开启或者停止自动轮播7.swiper 设置进度条8.获取数据类型9.数据判空11.遍历数据返回以及遍历数据查找对应数据12.把相同楼名归类后,下属楼层放入一个list中13.获取文本是否超出了行高13.页面滚动时,判断某个元素开始漏出 1.搜索跳转,判空后再执行后续动作 // 回车动作 $('.check_empty').off("keydown").on("keydown", function (e) { let { keyCode } = e; let p = $(this).closest('.search-form') if (keyCode == 13) { $(this).val($(this).val().trim()) let val = p.find('.check_empty').val() let reg = /^[\u4e00-\u9fa5_a-zA-Z0-9]+$/; flag = reg.test(val); if (flag) { // $(this).attr("type", "submit"); } else { return false } } }); // 点击搜索动作 $('.search-btn').off("click").on("click", function (e) { let p = $(this).closest('.search-form') let val = p.find('.check_empty').val() let reg = /^[\u4e00-\u9fa5_a-zA-Z0-9]+$/; flag = reg.

Android之 Activity活动详解

一 四大组件 1.1 Activity组件,它一个单独的窗口,程序流程都必须在Activity中运行。 1.2 service组件,用于在后台完成用户指定的操作。 1.3 content provider组件,会为所有的应用准备一个内容窗口,并且保留数据库、文件。 1.4 broadcast receiver组件,是程序之间传递信息时的一种机制,作用就是接收或者发送通知。 二 Activity简介 2.1 Activity是四大组件中用的最多的,是数据显示的载体,也是用户视觉显示和行为操控的界面。 2.2 一个程序包含一个或者多个Activity,Activity之间的跳转和数据通信依赖于Intent(意图)。 三 Activity的创建 3.1 Actvity是一个Java类,先创建一个Class,继承于Activity或者 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } } 3.2 创建xml布局文件 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> ................... </FrameLayout> 3.3 在清单文件AndroidManifest.xml注册Activity组件 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyApplication"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="

四十六、Ansible-自动化运维

1、简介 随着互联网IT运维飞速发展,目前市场上涌现了大量的自动化配置维护工具,例如 PSSH、Puppet、Chef、SaltStack、Ansible等。目前互联网企业使用最多的两款自动化配置工具是Ansible和Saltstack。 1.1 Puppet自动运维工具 Puppet是早期的Linux自动化运维工具,是一种Linux、Unix、Windows平台的集中配置管理系统,发展至今目前已经非常成熟,可以批量管理远程服务器,模块丰富,配置复杂,基于Ruby语言编写。最典型的C/S模式,需要安装服务端与客户端。 puppet采用C/S星状的结构,所有的客户端和一个或几个服务器交互,每个客户端周期的(默认半个小时)向服务器发送请求,获得其最新的配置信息,保证和该配置信息同步。 每个puppet客户端每半小时(可以设置)连接一次服务器端, 下载最新的配置文件,并且严格按照配置文件来配置客户端. 配置完成以后,puppet客户端可以反馈给服务器端一个消息,如果出错也会给服务器端反馈一个消息。 Puppet适用于服务器管理的整个过程,比如初始安装、配置、更新以及系统下线。 1.2 Saltstack自动运维工具 Saltstack与Puppet均是C/S模式,需安装服务端与客户端,基于Python编写,加入MQ消息同步,可以使执行命令和执行结果高效返回,但其执行过程需等待客户端全部返回,如果客户端未及时返回或未响应的话,可能会导致部分机器没有执行结果。 1.3 Ansible自动运维工具 Ansible与Saltstack均是基于Python语言开发,Ansible只需要在一台普通的服务器上运行即可,不需要在客户端服务器上安装客户端。因为Ansible是基于SSH远程管理,而Linux服务器大都离不开SSH,所以Ansible不需要为配置工作添加额外的支持。Ansible安装使用非常简单,而且基于上千个插件和模块实现各种软件、平台、版本的管理,支持虚拟容器多层级的部署。很多读者在使用Ansible工具时,认为Ansible比Saltstatck执行效率慢,其实不是软件本身慢,是由于SSH服务慢,可以优化SSH连接速度及使用Ansible加速模块,满足企业上万台服务器的维护和管理。 Ansible运维工具原理: Ansible是一款极为灵活的开源工具套件,能够大大简化Unix管理员的自动化配置管理与流程控制方式。它利用推送方式对客户系统加以配置,这样所有工作都可在主服务器端完成。其命令行机制同样非常强大,允许大家利用商业许可Web UI实现授权管理与配置。可以通过命令行或者GUI来使用Ansible,运行Ansible的服务器这里俗称“管理节点”;通过Ansible进行管理的服务器俗称“受控节点”。权威媒体报道Ansible于2015年被Red Hat公司1.5亿美元收购,新版Red Hat内置Ansible软件。 Ansible自动运维管理工具优点: 轻量级,更新时,只需要在操作机上进行一次更新即可; 采用SSH协议; 不需要去客户端安装agent; 批量任务执行可以写成脚本,而且不用分发到远程就可以执行; 使用python编写的,维护更简单; 支持sudo普通用户命令; 去中心化管理。 Ansible自动运维管理工具工作原理拓扑: 2、Ansible 安装配置 Ansible 可以工作在Linux、BSD、Mac OS X 等平台,对Python环境的版本最低要求为Python2.6以上,如果操作系统Python软件版本为2.4,需要升级方可使用Ansible工具。Red Hat、CentOS操作系统可以直接基于YUM工具自动安装Ansible,CentOS6.x或者CentOS7.x安装前,需先安装epel扩展源。 [root@localhost ~]# yum install -y ansible Ansible工具默认主目录为:/etc/ansible/,其中hosts文件为被管理机IP或者主机名列表,ansible.cfg为ansible主配置文件,roles为角色或者插件路径,默认该目录为空。 [root@localhost ~]# ll /etc/ansible/ 总用量 28 -rw-r--r-- 1 root root 19985 3月 7 12:43 ansible.cfg -rw-r--r-- 1 root root 1067 3月 30 21:33 hosts -rw-r--r-- 1 root root 1016 3月 30 21:12 hosts.

【Kali】Linux 长时间不启动 时间不对 无法更新 无法打开网页 无有效签名 无法安装程序

给大家菜踩过一遍雷了 如标题中所写,这一切原因都是因为系统时间与现实时间相差太大导致。 本人也是小白一个,搜索了一堆,都各种说法,设置时区,重启NTP服务啥的都不行 试了下重装NTP,结果显示没有发现这个软件包,然后提示了“ntpsec”可能会取代它 最后去系统目录找了下 发现有个叫做“ntpsec”的东西,然后试了下这个命令: /etc/init.d/ntpsec restart 好了,哈哈哈哈哈

没有比这更详细的-压测工具Jmeter介绍及使用了

一、压测工具选型 1.1、前言 压力测试是每一个Web应用程序上线之前都需要做的一个测试,他可以帮助我们发现系统中的瓶颈问题,减少发布到生产环境后出问题的几率;预估系统的承载能力,使我们能根据其做出一些应对措施。所以压力测试是一个非常重要的步骤,关于java应用的压力测试,业界常用工具为Apache Jmeter。(http://jmeter.apachne.org)。 1.2、工具概述 Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。 它可以用于测试静态和动态资源,例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库、FTP 服务器, 等等。JMeter 可以用于对服务器、网络或对象模拟巨大的负载,来自不同压力类别下测试它们的强度和分析整体性能。另外,JMeter能够对应用程序做功能/回归测试,通过创建带有断言的脚本来验证你的程序返回了你期望的结果。为了最大限度的灵活性,JMeter允许使用正则表达式创建断言。 Apache jmeter 可以用于对静态的和动态的资源(文件,Servlet,Perl脚本,java 对象,数据库和查询,FTP服务器等等)的性能进行测试。它可以用于对服务器、网络或对象模拟繁重的负载来测试它们的强度或分析不同压力类型下的整体性能。你可以使用它做性能的图形分析或在大并发负载测试你的服务器/脚本/对象。 二、压测工具安装 2.1、软件版本 本次测试,选择Jmeter官方最新版本进行。由于只有windows操作系统具备Jmeter的可视化界面,因此本次选择windows版本进行安装,以方便进行压测配置。 2.2、安装步骤 下载Jmeter:https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.5.tgz 解压到指定文件夹:D:\software\Dev-Env\Jmeter\apache-jmeter-5.5 配置到环境变量:主要配置JMETER_HOME=D:\software\Dev-Env\Jmeter\apache-jmeter-5.5\bin以及CLASSPATH配置%JMETER_HOME%\bin; 运行Jmeter:在安装目录下bin文件夹,找到jmeter.bat,双击运行即可。成功后显示如下: 注意该窗口的提示信息,意思就是:不要使用GUI运行压力测试,GUI仅用于压力测试的创建和调试;执行压力测试请不要使用GUI。使用下面的命令来执行测试: 三、应用平台压测(登录接口) 3.1、配置线程池 考虑到目前的用户量,配置500个线程,循环1次。 3.2、配置请求头 在我们刚刚创建的线程组上右键 【添加】-->【配置元件】-->【HTTP请求默认值】。配置我们需要进行测试的程序协议、地址和端口。 当所有接口测试访问域名和端口都一样时,可使用该元件,一旦服务器地址变更,只需要修改请求默认值。 3.3、配置接口HTTP请求 在“线程组”右键 【添加-】->【samlper】-->【HTTP 请求】设置我们需要测试的API的请求路径和数据。Taier登录接口用的form-data,需要在请求头进行设置。 3.4、添加请求头 上一步骤中涉及到的数据请求方式等,都可以在此配置。 3.5、添加断言 在我们刚刚创建的线程组上右键 【添加】-->【断言】-->【响应断言】。根据响应的数据来判断请求是否正常。我在这里只判断的响应代码是否为200。还可以配置错误信息 3.6、添加查看结果树 在我们刚刚创建的线程组上右键 【添加】-->【监听器】-->【察看结果树】。直接添加,然后点击运行按钮就可以看到结果了。 3.7、添加汇总报告 在我们刚刚创建的线程组上右键 【添加】-->【监听器】-->【Summary Report】。直接添加,然后点击运行按钮就可以看到结果了。 3.8、保存执行计划 3.9、执行测试计划 前面我们说过,执行测试计划不能用GUI,需要用命令行来执行。 在命令行执行以上命令 结束之后会在当前目录下生成压测报告、压测结果和压测日志 jmeter.log resulet.txt 3.10、获取压测报告 进入压测报告文件夹,双击打开index.html即可获取压测报告详情。 总体报告: 响应报告 

手把手教小白安装Jenkins

一、Jenkins简介 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。 简而言之,Jenkins就是一款将构建,打包,发布,测试,部署等一系列繁琐的操作自动化的工具。 在软件测试过程中,构建自动化脚本是比较常见的一种场景,例如设置自动化脚本每天晚上运行,有失败的用例及时发送邮件预警,是提前发现Bug的一种比较好的手段。 二、Jenkins环境部署 以Linux环境为例,系统版本是CentOS Linux release 7.4.1708 (Core): 一)安装JDK 步骤暂不分享,百度一下即可。 注意安装JDK的版本,我装的JDK版本是11,Jenkins版本是Jenkins 2.346.1,比较顺畅,如果JDK和Jenkins的版本不匹配,会出现很多未知的问题。 二)安装Jenkins 1、进入官网War Jenkins Packages下载 2、启动Jenkins,在jenkins.war所在目录输入命令:nohup java -jar jenkins.war --httpPort=8080 & 3、注意点查看防火墙 如果服务器防火墙没有关闭,需要把端口号加入防火墙: firewall-cmd --zone=public --add-port=8888/tcp --permanent firewall-cmd --reload 4、浏览器访问Jenkins 在浏览器中输入http://ip:8080,ip是你的服务器 ip地址 5、填写密码 将目录下的密码复制填入管理员密码框内  6、选择安装插件  7、等待插件安装 8、设置初始用户和密码  9、进入系统,安装完成  10、进入界面 PS:全网同名,转载注明出处

基于 ChatGLM-6B 搭建个人专属知识库

之前树先生教过大家如何利用微调打造一个垂直领域的 LLM 专属模型。但是微调一方面需要专业知识,通常需要很多计算资源和时间,以便在不同的超参数设置上训练多个模型并选择最佳的一个,另一方面动态扩展比较差,新增和修改原有的数据都要重新微调一次。总得来说对非专业人员不友好。 ChatGLM-6B 部署与 P-Tuning 微调实战 今天树先生教大家无需微调就能实现垂直领域的专业问答,利用 ChatGLM-6B + langchain 实现个人专属知识库,非常简单易上手。 技术原理 项目实现原理如下图所示,过程包括加载文件 -> 读取文本 -> 文本分割 -> 文本向量化 -> 问句向量化 -> 在文本向量中匹配出与问句向量最相似的top k个 -> 匹配出的文本作为上下文和问题一起添加到 prompt 中 -> 提交给 LLM 生成回答。 从上面就能看出,其核心技术就是向量 embedding,将用户知识库内容经过 embedding 存入向量知识库,然后用户每一次提问也会经过 embedding,利用向量相关性算法(例如余弦算法)找到最匹配的几个知识库片段,将这些知识库片段作为上下文,与用户问题一起作为 promt 提交给 LLM 回答,很好理解吧。一个典型的 prompt 模板如下: """ 已知信息: {context} 根据上述已知信息,简洁和专业的来回答用户的问题。如果无法从中得到答案,请说 “根据已知信息无法回答该问题” 或 “没有提供足够的相关信息”,不允许在答案中添加编造成分,答案请使用中文。 问题是:{question} """ 更多关于向量 embedding 的内容可以参考我之前写的一篇文章。 ChatGPT 引爆向量数据库赛道 使用场景 可以调整 prompt,匹配不同的知识库,让 LLM 扮演不同的角色 上传公司财报,充当财务分析师上传客服聊天记录,充当智能客服上传经典Case,充当律师助手上传医院百科全书,充当在线问诊医生 等等等等。。。。 实战 这里我们选用 langchain-ChatGLM 项目示例,其他的 LLM 模型对接知识库也是一个道理。

ts 节流和防抖

/** * @param func * @param delay * @param immediate * @param resultCallback */ type Func = (...args: any[]) => any //防抖 export function debounce(func: Func, delay: number, immediate?: boolean, resultCallback?: Func) { let timer: null | ReturnType<typeof setTimeout> = null; let isInvoke = false; const _debounce = function(this: unknown, ...args: any[]) { return new Promise((resolve, reject) => { if (timer) clearTimeout(timer); if (immediate && !isInvoke) { try { const result = func.

docker 安装jdk

1.查看jdk 镜像:docker search jdk 2.拉取镜像:docker pull 你选择的镜像 (如:docker pull eclipse/ubuntu_jdk8) 3.运行jdk镜像:docker run -it --name jdk1.8 -d eclipse/ubuntu_jdk8 4.查看是否安装成功 docker ps,并查看版本 java -version

Solidity中的事件驱动编程

在以太坊智能合约开发中,Solidity语言是最常用的编程语言之一。它为开发人员提供了一个强大而灵活的工具来构建去中心化应用程序(DApps)。事件驱动编程是Solidity中的一个重要概念,它允许合约与外部世界进行通信,并提供了一种机制来跟踪和记录合约中发生的重要事件。本文将深入探讨Solidity中的事件驱动编程,包括事件的定义、声明和使用,以及事件的优势和实际应用。 一、事件的定义与声明 在Solidity中,事件是合约中的一种特殊类型,用于向外部应用程序传达信息。事件可以被认为是合约中的通知机制,它允许合约在特定条件满足时触发事件,并将相关数据传递给监听合约或外部应用程序。 在Solidity中,声明事件的语法如下所示: event EventName(type indexed arg1, type arg2, ...); 其中,EventName是事件的名称,type是事件参数的数据类型,indexed关键字用于标记事件参数是否可被索引。事件参数可以包含多个,并且可以指定它们的数据类型。 例如,假设我们要声明一个名为"Transfer"的事件,它用于通知外部应用程序发生了资金转移操作,我们可以这样声明: event Transfer(address indexed from, address indexed to, uint256 amount); 在上面的声明中,我们定义了三个事件参数:from(资金发送者地址)、to(资金接收者地址)和amount(转移的金额)。其中,from和to参数使用indexed关键字进行了标记,以便在事件触发后进行索引和过滤。 二、事件的使用 声明了事件之后,我们可以在合约的适当位置使用它们来触发事件,并将相关数据传递给事件监听器。 在Solidity中,触发事件的语法如下所示: emit EventName(arg1, arg2, ...); 例如,我们可以在一个名为"transfer"的函数中使用我们之前定义的"Transfer"事件,当资金转移完成时触发该事件,并传递相关的参数: function transfer(address to, uint256 amount) public { // 资金转移操作 ... // 触发事件 emit Transfer(msg.sender, to, amount); } 在上述示例中,我们首先执行了资金转移操作,然后通过emit关键字触发了"Transfer"事件,并将发送者地址(msg.sender)、接收者地址(to)和转移金额(amount)作为参数传递给事件。 三、事件的优势 事件驱动编程在Solidity中具有许多优势,使得它成为合约开发人员的首选。 实时通知和监听:事件允许合约实时通知外部应用程序或其他合约发生的重要事件。通过事件,外部应用程序可以监听并及时响应合约中的状态变化。这种实时通知和监听机制对于构建复杂的DApps至关重要,可以实现实时交互和响应。 数据传递和查询:事件允许合约在触发事件时传递相关数据。这对于外部应用程序来说非常有价值,因为它们可以获取到合约内部状态的更新情况,并基于这些数据进行后续处理。合约开发人员可以选择在事件中传递需要的数据,以便外部应用程序能够更好地理解和利用合约的状态变化。 可索引和过滤:通过使用indexed关键字标记事件参数,Solidity允许对事件参数进行索引和过滤。这意味着外部应用程序可以根据特定参数的值进行查询,并过滤出符合条件的事件。例如,在资金转移的例子中,外部应用程序可以根据发送者或接收者地址来查询特定的转账记录,而不必遍历所有的转账事件。 可追溯性和审计:事件作为合约中发生的重要事务的记录,提供了可追溯性和审计的价值。通过查看事件日志,可以了解合约中的所有重要操作和状态变化。这对于合约开发人员、用户和监管机构来说都非常有用,因为它们可以追踪合约的历史记录,并进行审计和验证。 与外部应用程序的集成:事件驱动编程使得合约可以与外部应用程序进行无缝集成。外部应用程序可以通过订阅事件并实时监听合约状态的变化,从而与合约进行交互。这种集成性为DApp的开发提供了更大的灵活性和互操作性,使得合约可以与其他系统和服务进行协同工作。 四、事件驱动编程的实际应用 事件驱动编程在Solidity中有广泛的应用场景,以下是几个常见的实际应用示例: 常用的ERC-20代币合约中,通过定义事件来记录代币的转账和交易操作。外部应用程序可以监听这些事件来跟踪代币的转账记录,并进行相应的处理和统计。 在去中心化交易所(DEX)中,事件可以用于记录交易的执行和订单状态的更新。外部应用程序可以监听这些事件来获取交易执行的详细信息,并进行相关的后续操作。 在众筹合约中,事件可以用于记录众筹项目的捐款情况和众筹进展。外部应用程序可以监听这些事件来获取众筹项目的实时状态,并提供相关的统计和展示。 在多签名钱包合约中,事件可以用于记录钱包的操作和交易签名情况。外部应用程序可以监听这些事件来获取钱包的操作历史,并进行审计和验证。 在游戏合约中,事件可以用于记录游戏的关键动作和结果。外部应用程序可以监听这些事件来实时跟踪游戏进展,并提供相应的游戏数据和分析。 总结 Solidity中的事件驱动编程为智能合约开发人员提供了一种强大而灵活的工具来实现合约与外部世界的通信和交互。通过定义和触发事件,合约可以向外部应用程序传递信息并实现实时通知、数据传递、可索引和过滤、可追溯性等功能。事件驱动编程在众多的实际应用中发挥着重要的作用,为构建功能强大且与其他系统无缝集成的去中心化应用提供了支持。通过充分理解和应用Solidity中的事件驱动编程,合约开发人员可以提高合约的灵活性、可靠性和互操作性,从而推动区块链技术的发展和应用的创新。

css隐藏右侧滚动条 但是还能继续滚动

css隐藏右侧滚动条 但是还能继续滚动: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .outer-container { width: 360px; height: 200px; position: relative; overflow: hidden; background-color: aqua; } .inner-container { position: absolute; left: 0; top: 0; right: -17px; bottom: 0; overflow-x: hidden; overflow-y: scroll; } </style> </head> <body> <div class="outer-container"> <div class="inner-container"> 编写 JSX 语法的标签 你在前面看到的标记语言(markup syntax)称为 JSX。JSX 不是必须要用的,但是因为使用方便,所以大多数 React 项目都使用 JSX。所有 我们推荐的用于本地开发的工具 都自带对 JSX 的支持。 JSX 的语法比 HTML 更严格。类似 <br /> 这样的标签是必须要关闭的。并且,组件也不能返回多个并列最高层级的 JSX 标签,你必须为所有最高层级的标签添加一个共同的父标签,例如使用 <div>.

接收Promise的返回值的方法

第一种:使用.then(res=>{ },err=>{ }); Promise对象.then(res=>{ },err=>{ }); 第二种:使用.then(res=>{ }).catch(err=>{ }); Promise对象.then(res=>{ }).catch(err=>{ }); 第三种:使用async、await async 函数名(){ await Promise对象; }; 第四种:使用try{ } catch(error) { } + async、await async 函数名(){ try{ await Promise对象; } catch(error){ } };

Spring Security详解

第一节 Spring Security 简介 Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。 用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。 用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。 对于上面提到的两种应用情景,Spring Security 框架都有很好的支持。在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID 和 LDAP 等。在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制。 第二节 Spring Security 核心组件 1. Authentication 认证 <span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#aa5500">//这个接口的实现类都是Token,称为票据,UsernamePasswordAuthenticationToken</span> <span style="color:#aa5500">//我们自定义实现就可以叫MobileCodeAuthenticationToken</span> <span style="color:#770088">public</span> <span style="color:#770088">interface</span> <span style="color:#0000ff">Authentication</span> <span style="color:#770088">extends</span> <span style="color:#000000">Principal</span>, <span style="color:#000000">Serializable</span> { ​ <span style="color:#aa5500">/**</span> <span style="color:#aa5500">* 权限列表</span> <span style="color:#aa5500">*/</span> <span style="color:#000000">Collection</span><span style="

如何读懂JMeter聚合报告参数?

线程组参数解释 线程数(即并发数): 一个用户占一个线程,200个线程就是模拟200个用户; Ramp-Up 时间(秒): 设置线程需要多长时间全部启动;如果线程数为200,准备时长为10,那么需要1秒钟启动20个线程;也就是每秒钟启动20个线程; 循环次数: 一次场景下来,请求的数量=线程数 * 循环次数;如果线程数为200,循环次数为10 ,那么每个线程发送10次请求;总请求数为200*10=2000 ;如果勾选了“永远”,那么所有线程会一直发送请求,直到选择停止运行脚本; JMeter聚合报告参数解释 Label:每个JMeter的element的Name值,例如HTTP Request的Name; 样本:发出请求数量;模拟20个用户,循环100次,所以显示了2000; 平均值:平均响应时间(单位:ms);默认是单个Request的平均响应时间,当使用了Transaction Controller时,也可以以Transaction为单位显示平均响应时间; 中位数:50%的用户响应时间小于这个值; 95%百分位:95%的用户响应时间小于这个值; 99%百分位:99%的用户响应时间小于这个值; 最小值:用户响应时间最小值; 最大值:用户响应时间最大值; 异常%:测试出现的错误请求数量百分比;请求的错误率 = 错误请求的数量/请求的总数;若出现错误就要看服务端的日志查找定位原因; 吞吐量:Throughput简称TPS,吞吐量,默认情况下表示每秒处理的请求数,也就是指服务器处理能力,TPS越高说明服务器处理能力越好; KB/sec:每秒从服务器端接收到的数据量; 压测结果分析 异常%:确认是否允许错误的发生或者错误率允许在多大的范围内; 吞吐量:吞吐量每秒请求的数大于并发数,则可以慢慢的往上面增加;若在压测的机器性能很好的情况下,出现吞吐量小于并发数,说明并发数不能再增加了,可以慢慢的往下减,找到最佳的并发数; 最大的TPS:不断的增加并发数,加到TPS达到一定值开始出现下降,那么那个值就是最大的TPS; 最大的并发数: 最大的并发数和最大的TPS是不同的概率,一般不断增加并发数,达到一个值后,服务器出现请求超时,则可认为该值为最大的并发数; 压测的时候要时刻关注应用服务器数据库服务器等CPU、内存、网络等使用情况; 压测过程出现性能瓶颈,若压测客户端任务管理器查看到的CPU、网络和CPU都正常,未达到90%以上,则可以说明服务器有问题,压测客户端没有问题; 影响性能考虑点包括:数据库、应用程序、中间件(php-fpm、nginx、redis…)、网络和操作系统等方面; 循环控制器 目的:循环该控制器下面子节点的次数。 线程组里循环次数设置了n次,循环控制器下的循环次数也设置了m次,则该控制器下的请求运行的次数是(n*m)次。 如果(If)控制器 目的:判断条件,可以引用变量。当为 true 时,执行子节点 Interpret Condition as Variable Expression? 如果选择了此项,则条件必须是一个表达式,需要使用 ${__jexl3 } 或 ${__groovy } 表达式) Evaluate for all children 勾选:对所有采样器执行前都判断一次 不勾选:仅入口判断一次 如果是字符串的比较,需要加”” "${url}"=="baidu" 注意事项: 在if逻辑控制器的Expression中不能直接填写条件表达式,需要借助函数将条件表达式计算为true/false,可以借助的函数有__jexl3和__groovy函数 END绵薄之力 最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走: 这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

Shell逐行读取文件的4种方法分享。

这篇文章主要介绍了Shell逐行读取文件的4种方法,本文介绍了while循环法、重定向法、管道法、文件描述符法等一些方法,需要的朋友可以参考下 在Linux中有很多方法逐行读取一个文件的方法,其中最常用的就是下面的脚本里的方法,而且是效率最高,使用最多的方法。为了给大家一个直观的感受,我们将通过生成一个大的文件的方式来检验各种方法的执行效率。 方法1:while循环中执行效率最高,最常用的方法。 代码如下: function while_read_LINE_bottm(){ While read LINE do echo $LINE done < $FILENAME } 注释:我习惯把这种方式叫做read釜底抽薪,因为这种方式在结束的时候需要执行文件,就好像是执行完的时候再把文件读进去一样。 方法2 : 重定向法;管道法: cat $FILENAME | while read LINE 代码如下: Function While_read_LINE(){ cat $FILENAME | while read LINE do echo $LINE done } 注释:我只所有把这种方式叫做管道法,相比大家应该可以看出来了吧。当遇见管道的时候管道左边的命令的输出会作为管道右边命令的输入然后被输入出来。 方法3: 文件描述符法 代码如下: Function while_read_line_fd(){ Exec 3<&0 Exec 0<$FILENAME While read LINE Do Echo $LINE Exec 0<&<3 } 注释: 这种方法分2步骤,第一,通过将所有内容重定向到文件描述符3来关闭文件描述符0.为此我们用了语法Exec 3<&0 。第二部将输入文件放送到文件描述符0,即标准输入。 方法4 for 循环。 代码如下: function for_in_file(){

使用FastGithub解决国内访问GitHub失败的问题

问题提出 在ArduinoIDE安装开发板开发包、库时经常由于这些包和库的索引指向的是github下面的开源项目,所以安装失败的可能性极高。开启了FastGithub后,更新成功率和速度都快了很多! 问题解决 使用FastGithub开源工具(支持Win,Mac,Linux);FastGithub是一款基于DNS和HTTP代理的GitHub加速工具,可以加速GitHub的访问速度。 从这个地址下载https://github.com/dotnetcore/FastGithub Windows下运行 解压后,运行FastGithub.UI.exe即可,如下图,一般不需要设置,用默认即可。 Linux下运行 # yum install lrzsz # yum install libicu //一定要安装这个,否即FastGitHub运行提示缺少libicu,启动失败。 # cd ~ # rz # unzip fastgithub_linux-x64.zip # cd fastgithub_linux-x64 # ./fastgithub start //多种启动方式,我是以Service启动 # systemctl status fastgithub ● fastgithub.service - fastgithub Loaded: loaded (/etc/systemd/system/fastgithub.service; enabled; vendor preset: disabled) Active: active (running) since Mon 2023-05-15 17:50:25 CST; 17min ago Main PID: 70755 (fastgithub) Tasks: 25 (limit: 23157) Memory: 71.5M CPU: 4.141s

ant design 日期组件,设置可选范围的一些方法

<RangePicker disabledDate={this.forbidPartDate} /> 1, 将选择的范围小于或者等于今天 //endOf()是将其设置为时间单位的末尾,可以参考moment的API forbidPartDate(current) { return current > moment().endOf('day') }, 2,将选择的范围小于今天 //subtract(1, 'days')是增加一日,还有参数'years'、'months'和'weeks',也可以用负数去减相应的单位 forbidPartDate(current) { return current > moment().subtract(1, 'days').endOf('day') }, 3,选择范围大于或者等于今天 //注意:这里如果不加上subtract(),在选择一次日期之后今天就不能选了 forbidPartDate(current) { return current && current <= moment().subtract(1, 'days').endOf('day') }, 4,选择范围只可以是昨天,今天或者后天 //注意:这里如果不加上subtract(),在选择一次日期之后今天就不能选了 forbidPartDate(current) { return !(current > moment().subtract(2, 'days').endOf('day') && current < moment().subtract(-1, 'days').endOf('day')) }, 5. 将可选的时间控制到一年期限之内 const centerForbidLessStartDate = (current: any) => { return ( current <= moment(searchDateStart).subtract(1, 'month').endOf('month') || current < moment(searchDateEnd).

解决docker pull xxxx,报error pulling image configuration: Get https://production.cloudflare.docker.com/

Centos 下 给docker 安装 jdk ,拉去jdk提示:error pulling image configuration: Get https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/13/13041d54229cc20958f6524b6256964a99b6bea415204e7ed29f96bdc60b0f56/data?verify=1684120931-vwrbuWx70iYgTGg%2FSYJ9CfK%2F1eU%3D: EOF 问题 解决方法: 1编辑 /etc/resolv.conf 往里面加入:nameserver 8.8.8.8,保存 关闭docker:systemctl stop docker 启动docker:systemctl start docker 在拉取就可以了

Mysql 优化的几种方法

MySQL是当前最流行的一个关系型数据库管理系统,广泛应用于各种互联网应用场景中。然而在实际的开发和运维过程中,我们经常会遇到一些性能问题,如查询慢、请求堆积等,需要通过MySQL优化来解决。本文将详细讲解MySQL优化的原理、方法和工具,帮助读者全面了解和掌握MySQL的性能优化技术。 一、MySQL优化概述 MySQL优化是指通过调整MySQL的各项参数和配置,以及优化SQL语句的编写和执行,提高MySQL系统的性能和可用性。MySQL优化的主要目标是尽可能快地响应用户请求,提高系统的处理能力和并发性能,减少资源消耗和硬件成本。MySQL优化涉及多个方面,包括: 1.硬件配置:包括CPU、内存、磁盘等硬件资源的选择和配置,以满足系统的负载和性能需求。 2.软件配置:包括MySQL的参数设置和调整,如缓存大小、连接数、并发处理数等,以适应不同的负载和访问模式。 3.SQL语句优化:包括查询语句的重构、优化和索引设计,以提高查询效率和响应速度。 4.数据结构优化:包括表结构设计和数据类型选择,以减小数据存储和访问的成本。 5.架构优化:包括MySQL主备、分片等高可用、高可扩展架构的选择和部署,以实现系统的稳定性和可扩展性需求。 二、MySQL性能瓶颈 在进行MySQL优化前,需要先了解MySQL的性能瓶颈,从而有针对性地进行优化。MySQL的性能瓶颈主要包括以下几个方面: 1.磁盘IO:由于磁盘是MySQL的主要数据存储介质,因此磁盘IO是MySQL性能的瓶颈之一。磁盘IO的速度受到磁盘类型、容量、转速、缓存等多种因素的影响。 2.内存使用:MySQL需要使用大量的内存资源来提高查询效率和性能,主要包括缓存、临时表、排序等。如果内存不足,则可能导致频繁的IO操作和性能下降。 3.CPU使用:MySQL的查询处理和数据计算都需要大量的CPU资源,如果CPU负载过高,会导致系统响应缓慢和请求堆积现象。 4.网络延迟:由于MySQL通常运行在分布式环境中,网络延迟也是一个重要的性能因素,会影响MySQL的响应速度和并发处理能力。 5.SQL语句质量:SQL语句的效率直接影响MySQL的性能和查询速度,不合理的SQL语句可能导致索引失效、查询锁表等问题,进而降低MySQL的性能。 三、MySQL优化方法 为了解决MySQL的性能瓶颈,我们需要采取一系列优化方法来提高MySQL的性能和可用性。下面将介绍MySQL的优化方法和策略。 1.硬件配置优化 硬件配置优化是MySQL性能优化的基础,对于MySQL系统的性能和稳定性都有着非常重要的影响。常见的硬件配置优化方法包括: (1)升级硬件设备:如增加CPU的数量、提升内存容量、增加磁盘缓存等,以满足MySQL的性能需求。 (2)选择适当的硬件设备:根据MySQL的实际工作负载和访问模式,选择适当的硬件设备,如磁盘容量、网卡带宽等。 (3)RAID技术的应用:RAID技术可以提高磁盘IO的性能和数据安全性,通过数据备份和冗余存储等方式提供数据存储保障和性能增强。 (4)SSD的应用:SSD具有更快的读写速度和更低的延迟,可以有效提高MySQL的查询性能和并发处理能力。 2.软件配置优化 软件配置优化是MySQL性能优化的另一个重要方面,它主要包括MySQL参数的设置和调整。常见的软件配置优化方法包括: (1)修改缓冲区大小:通过修改MySQL的缓存区大小来提高MySQL的性能和响应速度。例如,增加查询缓存的大小可减少查询时间,增加连接池大小可加快并发处理能力。 (2)调整连接数:MySQL的最大连接数决定了系统同时能处理的最大请求数量,需要根据实际负载情况进行调整来避免资源浪费。 (3)优化查询语句:通过合理的SQL语句设计和索引优化,可以减少查询次数和IO操作,从而提高MySQL的查询效率和响应速度。 (4)优化表结构:对于大型数据表,需要考虑拆分成更小的子表或使用分区表等方式来减少单个表的数据量,以提高查询速度和响应时间。 (5)使用主从复制:主从复制是常用的MySQL架构优化方法,它可以提供高可用性和高可扩展性,通过异地备份和读写分离等方式优化系统架构。 SQL语句优化 SQL语句优化是MySQL性能优化的关键,合理的SQL语句设计和索引优化可以显著提高系统的查询效率和响应速度。常见的SQL语句优化方法包括: (1)使用索引:索引是MySQL查询的关键,通过合理的索引设计和使用,可以加快查询速度和减少IO操作,从而提高MySQL的性能。 (2)避免全表扫描:全表扫描是效率低下的查询方式,需要尽量避免使用。可以通过索引和条件过滤等方式优化查询语句,提高查询效率。 (3)合理使用JOIN:JOIN是SQL语句中常用的操作,但如果JOIN的表过多或不合理使用,会导致性能问题。需要合理选择JOIN的表和方式,避免无意义的JOIN操作。 (4)优化子查询:子查询是复杂查询的一种常见方式,但如果不合理使用,会导致性能问题。需要尽量避免嵌套过多的子查询和不必要的查询操作。 MySQL工具优化 MySQL还提供了多种工具来帮助进行性能优化和调试。常用的MySQL优化工具包括: (1)EXPLAIN:用于分析和优化SQL语句执行计划。 (2)slow query log:用于记录查询时间超过阈值的慢查询日志,帮助找出查询效率低下的SQL语句。 (3)Percona Toolkit:包含多个实用工具,如pt-query-digest、pt-stalk等,可用于MySQL性能监控和调试。 (4)MySQL Enterprise Monitor:用于MySQL企业版的监控和管理,可帮助进行性能优化和故障诊断。 服务器环境优化 除了MySQL自身的优化,还可以通过优化服务器环境来提高MySQL的性能和响应速度。 (1)操作系统优化:操作系统也会影响MySQL的性能和稳定性,需要根据实际情况进行优化,如调整内核参数、优化网络设置等。 (2)网络优化:因为MySQL经常用于分布式环境中,网络优化是提升MySQL性能的有效方法。可以使用专门的网络加速工具、调整TCP/IP参数、优化HTTP协议等方式来提升网络传输性能。 (3)安全优化:安全也是服务器环境优化的重要方面,MySQL的安全问题主要包括SQL注入、权限控制、SSL/TLS加密等,需要采取一系列措施来保护MySQL的安全性。 数据库设计优化 除了对MySQL本身进行优化,对数据库结构和数据表的设计也可以显著影响MySQL的性能。以下是一些常用的数据库设计优化方法: (1)冗余数据的处理:避免在多个数据表中存储相同的信息,这会增加查询和更新操作的负担。 (2)合理使用数据类型:选择恰当的数据类型可以减小数据表大小,从而提高查询和更新操作的效率。 (3)合理设计索引:索引是提高查询效率的关键,需要根据实际情况选择合适的字段作为索引,并避免创建过多或不必要的索引。 (4)分区表设计:对于单个数据表数据量较大的情况,可以采用分区表的方式将数据表划分成多个子表,以提高查询效率和响应速度。 (5)使用存储过程和触发器:存储过程和触发器可以在MySQL内部执行,减少通信开销,从而提高MySQL的性能。 总之,MySQL的性能优化是一个细致而长期的过程,需要不断学习和实践,综合运用多种方法和工具,才能最大程度地提高MySQL的性能和可用性。此外,还需要定期对MySQL进行健康检查和故障预警,及时发现并解决潜在的问题。

深度学习垃圾分类数据集

随着科技的发展,人工智能逐渐走进我们的生活。在这个过程中,数据集的重要性不言而喻。为了推动环保事业的发展,我们需要更多高质量的垃圾分类数据集。今天,我们将探讨一个包含2500+样本的垃圾分类数据集,它涵盖了6大类别:纸板、玻璃、金属、纸张、塑料和其他垃圾。 此数据集是通过网络搜集结合Trash数据集制作而成。 数据集概述 该垃圾分类数据集共有2500+个样本,分为6大类别。这些类别分别为: 纸板玻璃金属纸张塑料其他垃圾 数据集的样本数量分布均匀,每个类别都有足够的样本量。这有助于训练出更好的机器学习模型,提高分类准确率。 类别详解 现在让我们详细了解一下这6大类别: 1. 纸板 纸板类别主要包括各种厚度和形状的纸板,如:瓦楞纸板、硬纸板等。纸板通常可以回收利用,用于制造新的纸制品。 2. 玻璃 玻璃类别涵盖了各种玻璃制品,如:瓶子、罐子、窗户玻璃等。 3. 金属 金属类别包括各种金属制品,如:易拉罐、金属瓶盖、金属工具等。 4. 纸张 纸张类别主要包括各种纸质制品,如:报纸、杂志、书籍、纸巾等。 5. 塑料 塑料类别涵盖了各种塑料制品,如:塑料瓶、塑料袋、塑料餐具等。 6. 其他垃圾 其他垃圾类别包括了无法归类到上述五类的垃圾,如:陶瓷碎片、橡胶制品等。 应用场景 这个垃圾分类数据集可广泛应用于各种场景,例如: 基于图像识别的垃圾分类应用垃圾处理设备的智能识别系统垃圾回收站的自动分类系统 下载链接:trashnet-dataset-master.zip 

微信最新版本解除【文件只读】

问题 某一天开始,微信自动升级到3.9版本,最大的改变就是接收到的文件是只读属性,网上目前有两个办法,1.降到3.8甚至更早版;2.将version.dll补丁文件复制到微信安装目录,但3.9.2版本就不能用了。 解决办法 使用小工具Quicker,它可以自定义编程,支持事件触发器功能。经过设置之后,它会自动监视微信存储文件的文件夹,每当微信接收新文件,工具会自动解除新文件的只读属性。 1.下载并安装Quicker 下载 - Quicker (getquicker.net) 安装过程不难,差不多一直next就行,但是改不了安装路径。 2.安装完之后可以在右下角看到Quicker的小图标 3.复制这个网址 https://getquicker.net/Sharedaction?code=39ee090b-5b59-4aef-eca1-08db14a936d9 4.按Ctrl键或者点击小图标,打开Quicker 5.在空白灰色的地方右击鼠标,点击【粘贴分享的动作】 (点击之后就会出现第一行第二个取线只读属性的动作) 6.点击这个小齿轮,打开设置窗口 7.复制下面这段内容 [ { "Id": "dc76691f-9c81-4fa1-a9a9-e050ae29a258", "Note": "取消微信文件只读属性", "IsEnabled": true, "EventType": "FileSystemChange", "DebounceTimMs": 0, "Params": { "Path": "要监控的路径", "Filter": "*.*", "IncludeSubdirectories": true, "WatchCreated": true, "WatchChanged": false, "WatchDeleted": false, "WatchRenamed": true, "WatchError": false }, "LastEditTimeUtc": "2023-02-23T01:53:56.1881171Z", "ValidForMachines": "", "ActionIdOrName": "取消只读属性", "ActionParam": "$${FullPath}", "SkipFurtherTasks": false, "DelayMs": 2000, "EventFilterExpression": "$=File.Exists({FullPath}) \r\n && Path.GetExtension({Name}).Length < 10\r\n && (new FileInfo({FullPath})).

Vue.nextTick()【问题引入和分析】

Vue.nextTick() 前言 在此之前,你需要了解:事件循环,重排和重绘,Diff算法,会让你更好的理解本文 内容 先引入一个问题 <template> <div> <p>{{ message }}</p> <button @click="changeMessage">Change Message</button> </div> </template> <script> export default { data() { return { message: 'Hello Vue!' } }, methods: { changeMessage() { this.message = 'Updated Message' console.log(this.$el.textContent) // 输出 "Hello Vue!" this.$nextTick(function () { console.log(this.$el.textContent) // 输出 "Updated Message" }) } } } </script> 在 changeMessage 方法中,更改了组件的 message 数据,并尝试记录 $el.textContent 的值。 但是,由于 Vue 在进行数据更改后不会立即更新DOM(虚拟DOM异步处理),所以在记录文本内容时 $el.textContent 仍然是旧值 Hello Vue! 那么为什么进行数据更改后不会立即更新呢?

Kali-linux使用OpenVAS

OpenVAS(开放式漏洞评估系统)是一个客户端/服务器架构,它常用来评估目标主机上的漏洞。OpenVAS是Nessus项目的一个分支,它提供的产品是完全地免费。OpenVAS默认安装在标准的Kali Linux上,本节将介绍配置及启动OpenVAS。 5.2.1 配置OpenVAS OpenVAS默认在Kali Linux中已经安装。如果要使用该工具,还需要进行一些配置。配置OpenVAS具体操作步骤如下所示。 (1)在终端窗口中切换到OpenVAS目录,为OpenVAS程序创建SSL证书。执行命令如下所示: root@kali:~# cd /usr/share/openvas/ root@kali:/usr/share/openvas# openvas-mkcert 执行以上命令后,将输出如下所示的信息: 以上提示的信息,可以配置也可以不配置。如果不想配置的话,直接按下Enter键接收默认值即可。以上信息设置完后,将显示以下信息: ----------------------------------------------- Creation of the OpenVAS SSL Certificate ----------------------------------------------- Congratulations. Your server certificate was properly created. The following files were created: . Certification authority: Certificate = /var/lib/openvas/CA/cacert.pem Private key = /var/lib/openvas/private/CA/cakey.pem . OpenVAS Server : Certificate = /var/lib/openvas/CA/servercert.pem Private key = /var/lib/openvas/private/CA/serverkey.pem Press [ENTER] to exit 输出的信息显示了创建的OpenVAS证书及位置。此时按下Enter键,退出程序。 (2)使用OpenVAS NVT Feed同步OpenVAS NVT数据库,并且更新最新的漏洞检查。执行命令如下所示: root@kali:/usr/share/openvas# openvas-nvt-sync [i] This script synchronizes an NVT collection with the 'OpenVAS NVT Feed'.

《计算机网络—自顶向下方法》 Wireshark实验(二):HTTP协议分析

HTTP 协议工作于客户端-服务端架构上。浏览器作为 HTTP 客户端通过 URL 向 HTTP 服务端即 WEB 服务器发送所有请求。 WEB 服务器有:Apache服务器,IIS服务器(Internet Information Services)等。URL:即统一资源定位符(Uniform Resource Locator),用来唯一地标识万维网中的某一个文档。URL由协议、主机和端口(默认为80)以及文件名三部分构成。如: HTTP 默认端口号为80,但是你也可以改为8080或者其他端口。 HTTP 协议是属于应用层协议,并建立在 TCP/IP 的基础之上的超文本传输协议。当用户访问 WEB 服务器上的一个网页时,首先向 WEB 服务器提出连接请求,WEB 服务器接受并解析 HTTP 请求,然后从服务器的文件系统获取所请求的文件,将响应消息发送给客户端,客户端浏览器将收到的文件内容显示出来。如果请求的文件不存在于服务器中,则服务器应该向客户端发送“ 404 Not Found ”差错报文。 本实验通过对具体的请求响应过程中协议内容的分析来理解和掌握 HTTP 协议的通信过程。 1 HTTP 协议 1.1 HTTP 基本请求与应答 HTTP 请求包括三部分,分别是请求行(请求方法)、请求头(消息报头)和请求正文。HTTP 请求第三行为请求正文,请求正文是可选的,它最常出现在 post 请求方式中,get 请求无正文,所以回车之后为空。示例如下: 请求行 由三部分构成:第一部分说明请求类型为 get 方法请求,第二部分(用/分开)是资源 URL,第三部分说明使用的是 HTTP1.1 版本。 GET /success.txt HTTP/1.1\r\n 常见的请求方法如下图所示: 其中用得最多的方法是 get 方法和 post 方法,二者的区别: get 直接在浏览器输入,post 需要工具发送请求;get 用 url 或者 cookie 传参,post 将数据放在 body 中;get 的 URL 有长度限制,post 数据可以非常大;post 比 get 安全,因为 URL 看不到数据;get 用来获取数据,post 用来发送数据。 请求头

Flink窗口-计数窗口(CountWindow)

文章目录 Flink窗口-CountWindow使用(一)数量窗口的本质(二)数量窗口的使用(1)调用Window API(2)Window触发时执行计算逻辑① 匿名内部类方式② 自定义WindowFunction③ 示例演示 Flink窗口-CountWindow使用 (一)数量窗口的本质 前篇中,我们已经初略讲解了Flink中的数量窗口与时间窗口。 无论是哪一种窗口,他们的作用都类似于计算器(计算数量、时间)仅仅只是让数据堆积(不会像默认的流处理,来一条处理一条),只有当满足触发计算时机的时候,便开始计算,比如五个数据才计算,或者五秒钟才计算一次… 数量窗口的核心,便是数量的定义,当我们数据达到定义的量时,便会触发窗口计算逻辑 那么数量窗口究竟如何使用呢?哎,让我们来一探究竟! (二)数量窗口的使用 我们首先还是回顾下Flink计算程序步骤 获取执行环境 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setRuntimeMode(RuntimeExecutionMode.STREAMING); env.setParallelism(1); 加载数据源 DataStreamSource<Location> locationSource = env.addSource(new LocationSource()) 数据转换处理 //todo 我们这里,数据转换就使用CountWindow 数据输出 // 例如输出到mysql result.addSink(new MysqlSink()); // 例如输出到控制台 result.print(); 执行 env.execute("count-window"); 窗口使用前提: 在使用窗口前,我们必须要确保已经有了数据源 根据选择是否使用KeyBy算子(后边会讲) (1)调用Window API 我们直接使用我们的数据源来调用Window API即可 ex: source.countWindow(一个窗口容纳数据数量); 返回值,返回了一个WindowedStream<Location, Integer, GlobalWindow> 类型的数据流. 这步代码仅表示此计算程序使用的是CountWindow,且窗口的大小为1,如此设置,那么每来一个数据触发一次窗口计算,设置为2,则每相同的KEY出现两次,才会执行对应数据窗口计算(正如上方所说,起到了一个计算器的作用,那么我这里则是一个数据触发一次计算时机) 但需要注意,这里窗口并不涉及到计算逻辑!!!!!! (2)Window触发时执行计算逻辑 上边,我们的窗口已经拿到了数据了,拿到窗口后的数据,如何触发计算呢? 如果需要窗口中执行逻辑,我们要调用apply算子;apply算子,必须作用在WindowedStream ex: DataStream<T> result = windowedStream.apply(算子逻辑实现); 我们使用IDEA 参数提示,来看下我们的的apply算子究竟需要什么参数 查阅发现,WindowFunction 是一个接口,其中还有一个apply抽象方法 IN:入参 OUT:出参