全球直播下载
让更多人看到你
Hi, 请登录     我要注册     找回密码

基于bat脚本的前端发布流程的优化

totozhan阅读(68)

前面在根据bat脚本的前端发布流程规划与完成中,我现已介绍了规划与完成,这一篇首要是针对其的一个优化折腾(分两步走,第一步先搞出来,第二步再想着怎样去优化它),我首要做了以下几件事。
“各个击破”——更细粒度地拆分构建、打包、上传模块,逻辑更清晰,保护更简洁,程序更鲁棒
“条条大路通杭州”——更改了压缩zip的完成逻辑(npmpkg-archiver)
“打扫洁净屋子再请客”—–追加了整理之前的文件的逻辑
“鸡蛋放一个篮子里”——把生成的文件移到根目录,更加直观了
“火影兼顾术”——支持多进程打包,可以并行搞多个子项目
“一扫而光”——抽离了上传的逻辑放最终一把梭哈
下面我以一个项目为例,侧重向咱们介绍我是怎样一步步折腾的。
archiver包完成文件打包
这儿你问我为什么之前现已完成了bat脚本结合vbs脚本的文件压缩,还要再搞一套?我也很难回答你为什么,便是玩哇,学编程搞技术爱折腾呗,我是个jser,一起也是个tser,想到用npm构建也入情入理。我这儿首要是用到了一个库叫archiver,它的官网是https://www.archiverjs.com/,代码的一些细节我现已写了注释了,这儿就不过多介绍,我大致的思路是,在文件构建完今后,定义下要打包的目录,然后依照${项目名}-dist-${时刻}.zip的格局打包,这儿需求留意的是,当月份小于10的时候它下面代码输出的是M而不是MM,这个自身是做一个标识,要抹平这部分差异无非也便是多写几句话,我在这件事情上没有强迫症,一切我就没抹平。

bat
constfs=require(‘fs’)
constpath=require(‘path’)
constarchiver=require(‘archiver’)
//项目的文件目录
constbaseDir=path.join(__dirname,’../’)
//格局化当时时刻,这儿需求留意假如月份小于10的话是M而不是MM输出,仅做个发版符号,那就没必要强迫症对齐YYYY-MM-DDhh:mm:ss
const[foo,bar]=newDate().toLocaleString().split(”)
consttime=`${foo.replaceAll(‘/’,”)}${bar.replaceAll(‘:’,”)}`
//这儿用数组,是因为假如你还想打包其他的文件目录或者文件,就放到这个数组里
consttarget=[‘dist’]
//打包输出*-dist-*.zip
constoutput=fs.createWriteStream(`${baseDir}/app-dist-${time}.zip`)
constarchive=archiver(‘zip’,{
zlib:{level:9}
})
//打包错误处理
archive.on(‘error’,(err)=>{
throwerr
})
//结束撒花,输出文件途径,文件巨细
output.on(‘close’,()=>{
console.log(`生成打包文件成功,巨细为${(archive.pointer()/1024/1024).toFixed(1)}MB,系统途径在${baseDir}app-dist-${time}.zip`)
})
archive.pipe(output)
//eslint-disable-next-lineno-restricted-syntaxfor(constitemoftarget){
archive.directory(item,item)
}
archive.finalize()
值得一提的是,之前咱们都是打包到对应的子目录,这姿态我还要翻几下去看,给它优化掉去吧,直接打包完放根目录
关于构建脚本粒度细化这件事
软件工程上面说,你要做好一个东西,不能写的一坨浆糊相同,应该考虑每个模块它干了什么,模块的职责应该是单一的,一起保护起来也应该是简单的,从这些方面考虑,咱们重构之前写的脚本,分三步哈,先整理——>再构建完打包——>再上传,流程是这姿态的。
先整理
前次忘掉说整理这件事了,为什么我前次会忘呢?这儿我还要谢谢git,它打包完后传到linux服务器,不是可以经过discardchange这个魔法让打包后的文件消失嘛,所以我之前便是经过这么干的。
那咱们来完成下删去打包后的*.zip文件,其实也很简单
cd%~dp0
del/a/f/q”*.zip”
假如说你想层级递归/s加一下就可以了。
再构建完打包
在子项目中构建没什么好说的,大部分项目npmrunbuild一把梭。打包这儿咱们分两步走,在子文件的package.json里边贴入如下内容:
…”scripts”:{
“zip”:”nodezip.js”,
“build:zip”:”npmrunbuild&&npmrunzip”}

然后新建一个build.bat,内容如下:
callnpmrunbuild:zipexit
这儿call表明,等楼上的npm命令履行完再往下走,就会走到exit那里,这儿这么写为了更好地利用cpu来处理,有或许你有很多个项目,但一个时刻段就开一个进程去构建,显然是有点冤枉了我那8核的CPU,这么搞今后,在父项目下履行构建就可以一起构建多个项目了,构建完自动退出,这不便是小时候看的动画片中的影兼顾嘛。
在父项目中的build.bat脚本如下
cd/D%~dp0\NotePBL-app
startcallbuild.batcd/D%~dp0\NotePBL-biz
startcallbuild.batcd/D%~dp0\NotePBL-fin
startcallbuild.bat
再上传
上传这儿,为了防止每次输入密码,我主张你参考我之前写的第一篇,配到ssh里边,然后就很简单了,需求用到哪个包就传哪个,
cd%~dp0
scpapp-*.ziproot@这儿填对应服务器的地址:这儿填写对应服务器的途径
scpbiz-*.ziproot@这儿填对应服务器的地址:这儿填写对应服务器的途径
scpfin-*.ziproot@这儿填对应服务器的地址:这儿填写对应服务器的途径
最终整合的deploy.bat便是这样啦
@echooff
setlocalenabledelayedexpansion
@REM中电惠融项目构建脚本,ZhengJiangTao(admin@qq.com)
chcp65001
clscd/D%~dp0echo==========(∩??ω??)?-*?中电惠融项目构建脚本?*-?(??ω??∩)==========
:startcd%~dp0
callclean.batcd/D%~dp0
start/waitcallbuild.batcd/D%~dp0
start/waitcallupload.batecho========*:??(?′?`)??:*中电惠融项目构建脚本*:??(?′?`)??:*========
:finishexit/b
这次不是自动挡的车,带了点手动挡,除了把模块拆分之外,也给与相关开发手动发车的感觉,嗯。
FAQ
假如项目就单纯的一个,没有这么多子项目有什么好的主张吗?
那我主张你直接npm一把梭,具体是这姿态的。有个npm包叫rimraf,地址是https://www.npmjs.com/package/rimraf,可以完成删去文件,装置一下把package.json构建脚本改下

“scripts”:{
“clean”:”rimrafapp-dist-*.zip”,
“zip”:”nodezip.js”,
“build:cz”:”npmrunbuild&&npmrunclean&&npmrunzip”,
}

假如多个项目,只改了其中一两个子项目有什么好的主张吗?
这便是我上面说的手动挡留的口子,在对应的build.bat文件和upload.bat文件下把不要的注释掉就好了。

字节Pico走“小”路

totozhan阅读(34)

比照Pico玩家和Quest玩家,你会发现两者存在巨大差异。
一位资深VR从业人员表明:“Pico玩家多是以休闲文娱为主,而且多为首次触摸VR的小白玩家,而Quest玩家多是硬核游戏玩家,触摸VR时刻普遍较长。”
造成这一状况的原因与两家在生态建设上的打法有关。
从Pico前期进行大规模曝光时,就将演示场景会集在了家庭文娱、视觉效果等泛文娱方向,PicoStore上长时间引荐的应用也是《OhsHape》、《多合一运动VR》等运动类、节奏类小游戏。
相反在QuestStore长时间霸榜的则是《Blade&Sorcery》《Onward》等相对硬核的游戏高文。
别的近期Pico在内容生态建设、更新上也更偏向休闲文娱。5月17日举办了郑钧“WeAre”VR私家唱聊会;6月6日,又与迪斯尼等影视公司打造“Pico3D大片重燃方案”。
从运动类小游戏到短视频、再到3D影视作品,如今的Pico在内容生态建设上似乎现已构成一套差异于Quest的打法。仅仅这种以小广博的打法效果如何?在快速推开后,可以进步用户留存,养成二次消费的习惯吗?Pico生态真的不需求高文吗?
Part.1
小制造盯上小白
在走完与Quset类似的硬件铺设路途后,Pico在生态建设上改变了打法。
上一年8月,字节跳动以97亿元人民币的价格将Pico收入囊中,彻底改变了它的命运。从抖音开屏广告、24小时不间断直播、各种信息流推送,到登上春晚,赞助综艺,再到大规模开设线下体会店,字节为Pico打造的一些列“洗脑式”营销将其推到国内VR硬件商场的一线。
本年初,Pico推出打卡半价送的活动,直接拉低了消费门槛,也进步了用户粘性,甚至在一波又一波激烈营销攻势下,Pico在5月还将2022年的销售方针从100万台上调至180万台,要知道上一年一年Pico的销量仅为50万台。
依照PicoCEO周雄伟所想,Pico的转型分为“硬件导向-营销导向-内容导向”三个阶段。巨大的营销投入,指向的是快速翻开商场的短期方针,也便是第二阶段。而在销量和活泼用户达到必定的量级后,Pico也开端在内容上有所动作。
不过与Quest用爆款3A高文游戏点着商场的战略不同,Pico挑选了从更易上手,而且开发门槛更低的小游戏切入,一同向视频、社交等泛文娱方向转移。这点从Pico组成的团队上便可窥知一二。
此前晚点LatePost报道称,字节跳动多位内容负责人现已转岗Pico部分,建立内容及营销团队。
据悉,西瓜视频负责人任利峰、抖音综艺负责人宋秉华、抖音文娱总监吴作敏已相继转岗至VR产品部分。
这其中宋秉华曾任阿里文娱集团大优酷综艺监制中心总经理,担任过优酷综艺《演技派》项目负责人、《这!便是街舞》《火星情报局》等爆款节目总监制。可见字节跳动对Pico影视内容的重视。
营销思路的不同,实践上是对应的人群不同。
差异于Quset等国外VR产品从硬核玩家开端起步的道路,Pico的打法一方面是招引过往触摸数码设备较少的小白人群。
近期数据显现,抖音论题#玩VR选Pico#的男性观众占比仅为32.9%,女人观众占比为67.91%。此前2019年Pico公布的男女用户比仍是9:1,而2021年虽未有详细数据,但周雄伟也表明过Pico的用户主要仍是以一二线城市男性为主。
另一方面这也是在字节跳动的干预下,Pico内容生态所产生的必然结果。众所周知,字节跳动在自研游戏方面的实力并不出色。
2021年开端,字节跳动游戏事务便坏事不断,先是休闲游戏OHAYOO被爆裁员,后来包括《StrikeRoyale》、《完结战场》在内的多款中重度游戏也被下架或者停服,就连上一年底刚成立的朝夕光年游戏板块,在本年5月以后也屡次被传出事务在收缩。
相反,以短视频发家的字节跳动,在文娱、影视方面有必定优势以及资源储藏。所以Pico选用这种泛文娱生态建设的打法,也能将字节跳动的优势彻底汲取。
不过这种以泛文娱为中心的低本钱打法,也有点饥不择食的滋味。
Part.2
小本钱下的大问题
实践体会中,不管玩游戏仍是看电影,用Pico都略显为难。在与不同的用户群体触摸后,可以得出这样的定论。
“我算是被Pico营销洗脑买的那批人,当时想着买来追追剧,跟idol近距离触摸一下,但没想到真实用起来如此鸡肋。”初夏向「科技新知」感叹道。
沉溺式、近距离、8K高清、3DVR,是Pico在宣传其观影体会时提到最多的几点,特别最近发布“3D大片重燃方案”后,引起不少影视迷重视。
其中之一的初夏表明,“最开端仍是感觉比较新颖,但两天往后,新鲜劲散去就暂时搁置了,跟我一同买的姐妹大多也这样,当然这也与个人实践体会有关。”。
关于“眼睛党”来说,在戴Pico之前需求长时刻调整,包括位置、紧密度等等,以便解决水汽问题,“即使Neo3有排气孔设计,但仍是不能彻底解决水汽问题”。
别的关于初夏这种影视用户来说,Pico整体佩带的舒适度也并不出色。
“感觉像头上绑了一块石头一样,可以显着感到颈部存在的压力。由于VR眼睛毕竟是戴在头上的,而且观影时也基本是躺着的状况,设备压脸不可避免。原装是压脸,换了后面带电池的头带,感觉上是前后比较平行了,但仍是有压脸感。“初夏解释道。
其实硬件上的缺乏还可以自行进行辅助调整,最要害的是内容体会上的下风,短时刻内无法改变。
“坦白讲,我身边很多人在买Pico之前,都以为只需带上这个VR眼睛,就能像成为剧中人那样,可以前后左右看清细节,就像线下VR体会店体会到的那样。”初夏自嘲地说。
现实状况却是,仅有单个视频可以完成真实的感同身受,Pico宣传的漫威大片、迪斯尼大片等,仍是以3D形式出现,左右两头均是黑幕,“跟坐在电影院第一排看3D影片感觉类似,还不如投影观看时自由”。
Pico这样的做法其实与资金、时刻本钱有较大联系。据悉早前Oculus制造的VR电影《LOST》时长不到十分钟,却花费了1000万美元。而且想要达到VR效果,电影在拍照时就需求选用专业的拍照手段,关于还处在前期铺量环节的Pico来说,显然没有更多精力来制造真实的VR影片。
在游戏体会方面,Pico更为一般。
“能直接安装在VR一体机中的游戏少得不幸,而且大部分质量偷工减料,简直便是4399的水平。”资深VR游戏玩家明东讲到。
据悉,在Pico商城中,较为火热的游戏大多为体育类、节奏类小游戏,而《亚利桑那阳光》和《SUPERSHOT》等VR游戏高文,也是在上线许久后才挑选引进。
“VR圈里串流比较火,简直一切硬核玩家都离不开串流。简略来说便是将VR与电脑链接起来,充任显现器的角色,串流后就可以玩更多游戏。”明东说。
但在官方要求的网络环境和设备装备下,Neo3的游戏串流仍是存在画质损耗和音画推迟的问题,特别是在无限串流的时候,即使是调到最差的流畅画质,仍然会存在卡顿现象。假如没有一台高性能电脑做支撑,串流体会就会大打折扣。
“比照Quest,Pico的打法的确招引小白用户,但关于游戏玩家来说,Pico的确还差点意思。”明东表明。
由此也引发出一个新的问题,在Pico泛文娱化的生态中,真的不需求高文吗?

 

Pico
Part.3
Pico不需求高文吗?
根据文娱软件协会的数据,美国1.69亿游戏玩家中,大约有29%的人具有VR设备。这是Oculus在游戏内容上深耕的用户基础,但中国商场由于各种要素,用户们更倾向于手游而非主机游戏。
再加上VR游戏的高开发门槛以及偏低的爆款概率,就不难解释字节跳动为什么走向与Quest不同的路。但长远来看,Pico在开展泛文娱生态的一同,也需求高文来引爆商场带动营收。
有数据计算,2020年3月在《Half-Life:Alxy》推出之后,Steam当月所计算的VR设备用户数量增长超越百万;别的,彼时OculusQuest上也有20款游戏的收入超越百万美元,而且该数据还在持续上升;2021年11月,Meta宣布《节奏光剑》在OculusQuest单渠道上的收入超越1亿美元。
此外,《塞尔达传说》《动物森友会》《健身环大冒险》等爆款游戏也肉眼可见地带动了Switch的销量。
而且关于Pico来说,用爆款游戏内容带来的用户,必定程度上要比当下泛文娱内容带来的用户价值更高。
当下Pico的存量用户一般分为两类,一类是已有VR设备的老用户,也便是硬核游戏玩家;另一类是第一次触摸VR的新用户,由于考虑到性价比、使用便携性等要素而入手了VR一体机。
Pico这种内容战略下带来的用户大多为第二种用户,而且正如上文所提到的,在相关论题中,女人用户现已远超男性用户,也便是说这类新用户中的女人用户增长幅度显着高于男性。
但就VR游戏的付费意愿而言,男性用户的付费份额更高。
一方面,有查询研究显现,大多数女人对画面制造优秀、互动故事类型的VR游戏更感兴趣,而且更愿意为游戏中的道具、皮肤付费;另一方面,据国外研究人员查询,有22.6%的女人用户频繁经历VR晕动症,是男性用户(7.2%)的3倍以上,在体会不好的状况下,用户也很难进一步付费。
此外,现在Pico的硬件也还处在遍及铺设阶段。在各大电商渠道,仍能看到Pico推出的“打卡返半价”福利活动,也便是说用户假如完成应战,只需一千多元就能拿下一台Neo3。数据显现,现在参加活动的顾客完成率大概在50%左右。
贱价战略一方面意味着Pico在硬件上简直是赔钱在卖,另一方面该战略简略影响部分顾客激动购物的心情。
这些晕动症患者和激动型顾客究竟能提供多少留存率,能否将其转化为活泼用户,这或许是Pico在推行泛文娱内容生态时,需求面临的核心问题。
靠小游戏以及影视建立起的“小白用户生态”,在后续内容营收上的效果可能并不出色。长远来看Pico仍是需求用一些爆款应用来进步用户质量以及用户留存率。
站在字节跳动的立场上,显然是想在国内VR商场还未彻底迸发时,一面依靠超流量曝光来谋取硬件销量,快速铺开商场份额;一面将自家共同的内容生态移植到VR产品中,以完成销量和内容生态上完成双线扩张,抢先占据用户心智和商场话语权。
这种思路是否正确,能否在销量和内容上完成打破,现在还没有明确答案。但在VR行业里有一个现实是,不管走“大道”仍是走“小路”,都没那么简略。

Java基础入门之多态和目标类型转换

totozhan阅读(54)

一、多态
1.假定完成一个动物发出的叫声办法,咱们知道不同的动物,它们的叫声是不一样的。当在办法中传入一个参数类型,例如猫的叫声、狗的叫声。在同一个办法,当参数不同它们的履行结果各不相同,这便是多态。
2.多态是把子类目标赋给父类引证时,调用重写的办法时,表明的是子类的行为。
3.怎样完成多态例子
//界说接口FruitinterfaceFruit{voidinfo();//界说抽象办法info()}//界说Cherry类完成Fruit接口classCherryimplementsFruit{doubleweight=66;//weight特点为分量//完成info()办法publicvoidinfo(){System.out.println(“我是一个樱桃!”+”分量为:”+weight+”g”);}}//界说Apple类完成Fruit接口classAppleimplementsFruit{doubleweight=250;//weight特点为分量//完成info()办法publicvoidinfo(){System.out.println(“我是一个苹果!”+”分量为:”+weight+”g”);}}publicclassp30{publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubFruitf1=newCherry();//创立Cherry目标,Fruit类型变量f1引证Fruitf2=newApple();//创立Apple目标,Fruit类型变量f2引证fruitInfo(f1);//调用fruitInfo()办法,把f1参数传入fruitInfo(f2);//调用fruitInfo()办法,把f2参数传入}//界说静态的fruitInfo()办法,承受一个Fruit的参数fpublicstaticvoidfruitInfo(Fruitf){f.info();}}
运行的结果是:
我是一个樱桃!分量为:66.0g我是一个苹果!分量为:250.0g
从上面代码中,界说了一个Fruit接口,界说了抽象办法info()。界说Cherry类和Apple类完成Fruit接口,界说变量weight特点和完成info()办法。“Fruitf1=newCherry()、Fruitf2=newApple()”完成子类目标赋给父类引证,调用fruitInfo()办法,父类引证了两个子类目标别离传入f1和f2参数。

 

Java
二、目标类型转化
1.子类目标是能够主动转化成父类。
2.父类转化成子类目标就需要强制转化。
例如:
//界说接口FruitinterfaceFruit{voidinfo();//界说抽象办法info()}//界说Cherry类完成Fruit接口classCherryimplementsFruit{doubleweight=66;//weight特点为分量//完成info()办法publicvoidinfo(){System.out.println(“我是一个樱桃!”+”分量为:”+weight+”g”);}//界说pro()办法voidpro(){System.out.println(“产地:浙江”);}}publicclassp31{publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubFruitf1=newCherry();//创立Cherry类的实例目标fruitInfo(f1);//调用fruitInfo()办法,把f1参数传入}//界说静态办法fruitInfo(),承受一个Fruit参数fpublicstaticvoidfruitInfo(Fruitf){f.info();//调用传入参数f的info()办法f.pro();//调用传入参数f的pro()办法}}
运行的结果是:
从上面能够看出编译出错了,调用fruitInfo()办法传入Cherry目标,办法参数是Fruit类型的,把Cherry的子类当作父类运用导致程序编译呈现过错,程序在运行到f.pro()这行代码发现这个办法没有界说。因为传入的是Cherry类,在Cherry类中界说了pro()办法需要强制转化才能够运行,便是把Fruit类型变量强制转化成Cherry类型。
修改后代码如下所示:
//界说静态办法fruitInfo(),承受一个Fruit参数fpublicstaticvoidfruitInfo(Fruitf){Cherryf1=(Cherry)f;f1.info();//调用传入参数f的info()办法f1.pro();//调用传入参数f的pro()办法}
再次运行的结果是:
我是一个樱桃!分量为:66.0g产地:浙江
三、instanceof关键字
1.instanceof关键字作用
判别一个实例目标是否归于一个类,它的语法如下:
目标instanceof类
2.在进行引证类型转化前先运用instanceof关键字判别,例如:
if(finstanceofCherry){//如果f指的是Cherry目标类型时,返回的是true。Cherryf1=(Cherry)f;}
四、总结
本文首要介绍了多态、目标类型转化、instanceof关键字。
多态是子类目标赋给父类引证时,调用重写的办法时,表明的是子类的行为。通过怎样完成多态例子协助了解这个用法。
目标类型转化是子类目标是能够主动转化成父类、父类转化成子类目标就需要强制转化。
instanceof关键字用来判别一个实例目标是否归于一个类,期望大家通过本文的学习,对你有所协助!

it技术员工资一般多少(适合女生的it方向)

totozhan阅读(62)

  it技术员工资一般多少

个人觉得现在IT职业也是依照个人能力分为三六九等的,就像阿里、华为、腾讯几个巨头内部的技能等级制度
1、初级,薪资根本在5K以内,在公司内部根本也就依照上级安置的任务,按时按质完成即可,只要是正常人,满意这些根本要求应该都不成问题
2、中级,薪资根本在5k到8K之间,此类人员除了要满意初级人员要求以外,要求有较强的责任心,上进心,能给直接领导分忧,帮助初级人员解决问题,开始测验带做项目
3、高档,薪资根本在8k到15k之间,此类人员要求有满足独立性,带领团队做事,对公司有明显贡献。
4、架构级,薪资根本在15到20k之间,此类人员根本不会负责项目,根本都是做公司底层的使用支撑,架构搭建等高深技能或难点霸占。
5、体系级、薪资从20K上不封顶,此类人员根本从事技能的引入,体系的布局,类似于总工程师这样一个角色,做到这个份上,根本也就告别自己干活的时代……
以上分析基于无锡地区,其他城市需要在同等级的待遇上乘以一定的系数。
区分的5个等级也仅仅个大概,其实还能够持续往详尽的区分,如果有需要,阿里、腾讯等内部的技能等级有一定的代表性,能够参考!
IT职业包括极广,其间包括信息技能的产业,诸如银行,咨询,医院,出,制造,影视等等,一起的特色都是依赖于信息和信息体系。计算机软硬件,因特网和其他各种连接上述所有的东西的网络环境当然还有从事规划,保护,支撑和办理的人员一起形成了一个无所不在的IT产业。

 

it

适合女生的it方向

IT职业的发展前景剖析可以看出,IT已经成为现在求职者挑选的热门职业,多元化的发展趋势下,IT职业中女人从业者所占据的比重也越来越大,女生关于工作的完结和处理上同样可以做好,这也是现在越来越少的企业在招聘时不会刻意标示只限男生的主要原因。并且在沟通方面、美感方面女生也比男生更有优势,那么关于想要入行IT的人来说,下面的岗位相对是比较合适女生去挑选的。
软件开发类
软件开发是依据用户要求建造出软件系统或者系统中的软件部分的过程。软件开发是一项包含需求捕捉、需求剖析、规划、完成和测验的系统工程。软件一般是用某种程序规划语言来完成的。
软件开发相关岗位中Python开发、Web前端开发、软件测验等是比较合适女生从事的,这些开发技能学习起来难度相对偏低,可是岗位需求却在逐年递增,薪资待遇非常可观。
视觉规划类
视觉规划是针对眼睛功能的主观形式的表现手段和成果。具体细分为包装规划、图像规划、广告规划、界面规划等。规划类的工作需要规划师对时髦趋势有敏锐的洞察力,在这方面,女生相对而言愈加有优势,并且现在用户体验至上,企业关于规划类的岗位愈加注重,无疑也是工作的一个很好的挑选方向。
网络营销类
网络营销是基于网络及社会关系网络连接企业、用户及公众,向用户及公众传递有价值的信息与服务,为完成顾客价值及企业营销目标所进行的规划、实施及运营管理活动。
网络营销类岗位包含有新媒体运营、SEO优化、直播带货等多个方向,在这些领域里,尤其是直播带货中,女生已然成为了中坚力量,假如关于这方面感兴趣的话,以此作为未来的工作方向也是很好的。
总体来看,女生在IT职业中所承担的角色越来越重要,群众关于IT从业者性别上的成见也在逐步淡化,现在以及未来都将会看到各行各业都有女生的身影,所以,性别并不是女生挑选工作岗位时的约束因素。

Redis各种业务场景下的使用

totozhan阅读(56)

  Redis各种业务场景下的使用

Redis作为一种内存型的非联系型的数据库,不管在互联网大厂,小厂,大项目和小项目中,简直都会被运用。为什么Redis会遭到如此喜爱呢?关于这个问题,可能许多的程序员仅仅看着他人用而用,缺少对Redis一个全面的了解。
Redis运用场景
缓存
缓存现在简直是所有中大型网站都在用的必杀技,合理的运用缓存不仅能够提高网站拜访速度,还能大大下降数据库的压力。Redis供给了键过期功用,也供给了灵敏的键筛选战略,所以,现在Redis用在缓存的场合非常多。
排行榜
许多网站都有排行榜运用的,如京东的月度销量榜单、产品按时刻的上新排行榜等。Redis供给的有序调集数据类构能完成各种复杂的排行榜运用。
计数器
什么是计数器,如电商网站产品的阅读量、视频网站视频的播放数等。为了确保数据实时效,每次阅读都得给+1,并发量高时假如每次都请求数据库操作无疑是种挑战和压力。Redis供给的incr指令来完成计数器功用,内存操作,功用非常好,非常适用于这些计数场景。
分布式会话
集群模式下,在运用不多的状况下一般运用容器自带的session复制功用就能满足,当运用增多相对复杂的体系中,一般都会建立以Redis等内存数据库为中心的session服务,session不再由容器办理,而是由session服务及内存数据库办理。
分布式锁
在许多互联网公司中都运用了分布式技能,分布式技能带来的技能挑战是对同一个资源的并发拜访,如全局ID、减库存、秒杀等场景,并发量不大的场景能够运用数据库的失望锁、达观锁来完成,但在并发量高的场合中,运用数据库锁来操控资源的并发拜访是不太抱负的,大大影响了数据库的功用。能够运用Redis的setnx功用来编写分布式的锁,假如设置回来1阐明获取锁成功,不然获取锁失利,实践运用中要考虑的细节要更多。
交际网络
点赞、踩、重视/被重视、一起老友等是交际网站的基本功用,交际网站的拜访量通常来说比较大,而且传统的联系数据库类型不适合存储这种类型的数据,Redis供给的哈希、调集等数据结构能很便利的的完成这些功用。
最新列表
Redis列表结构,LPUSH能够在列表头部插入一个内容ID作为关键字,LTRIM可用来限制列表的数量,这样列表永远为N个ID,无需查询最新的列表,直接依据ID去到对应的内容页即可。
音讯体系
音讯行列是大型网站必用中间件,如ActiveMQ、RabbitMQ、Kafka等流行的音讯行列中间件,首要用于事务解耦、流量削峰及异步处理实时性低的事务。Redis供给了发布/订阅及堵塞行列功用,能完成一个简略的音讯行列体系。别的,这个不能和专业的音讯中间件相比。
怎么运用
上面提到了各种运用场景,在这些场景运用中,无非便是对Redis数据类型的操作。就需要对Redis数据类型有所了解。在Redis中有这些数据类型。String、Hash、List、Set、Zset、GEO、Stream、HyperLogLog、BitMap。

Redis
数据运用场景
String类型
String类型是一种字符串类型,类似一种键值对的方式。
一般咱们用String类型用来存储产品数量、用户信息和分布式锁等运用场景。
存储产品数量。
setgoods:count:11233
setgoods:count:2100
用户信息。
setuser:1″{“id”:1,”name”:”张三”,”age”:12}”
setuser:2″{“id”:2,”name”:”李四”,”age”:12}”
分布式锁。
#设置一个不存在的键名为id:1值为10,过期时刻为10秒。
127.0.0.1:6379>setid:110ex10nx
OK
127.0.0.1:6379>getid:1
“10”
#当时的键还未过期,在次设置则不会设置成功。
127.0.0.1:6379>setid:110ex10nx
(nil)
#当10秒之后去获取,当时的键则为空。
127.0.0.1:6379>getid:1
(nil)
用Redis完成分布式锁的原理,当一个键存在则设置失利。
hash类型
hash类型是一种类似联系型数据库结构的数据结构。有一个键名,键存的内容是以键值对的方式存在。
运用hash结构,咱们能够用来存储用户信息、目标信息等事务场景。
存用户信息。
127.0.0.1:6379>hsetuser:1id1namezhangsanage12sex1
(integer)4
127.0.0.1:6379>hsetuser:2id2namelisiage14sex0
(integer)4
127.0.0.1:6379>hmgetuser:1idnameagesex
1)”1″
2)”zhangsan”
3)”12″
4)”1″
存储目标信息。
127.0.0.1:6379>hsetobject:useridpublic-1nameprivate-zhangsan
(integer)2
127.0.0.1:6379>hmgetobject:uesridname
1)(nil)
2)(nil)
127.0.0.1:6379>hgetobject:userid
“public-1″
127.0.0.1:6379>
这儿存储一个user目标,目标里面有两个特色,别离是id和name字,别离存储的是特色的拜访权限和默认值拼接。
list类型
list类型是一个列表类型的数据结构。用一个键,依照顺序排列数据。
list一般用在的场景是行列、栈和秒杀等场景。
行列。
127.0.0.1:6379>lpushlist:10123456
(integer)7
127.0.0.1:6379>rpoplist:11
1)”0″
127.0.0.1:6379>rpoplist:11
1)”1″
127.0.0.1:6379>rpoplist:11
1)”2”
运用list完成行列,是由于行列遵从先进先出的特色。
栈。
127.0.0.1:6379>lpushlist:13456
(integer)3
127.0.0.1:6379>lpoplist:1
“6”
127.0.0.1:6379>lpoplist:1
“5”
127.0.0.1:6379>lpoplist:1
“4”
127.0.0.1:6379>lpoplist:1
“3”
运用list完成行列,是由于行列遵从后进先出的特色。
秒杀。
127.0.0.1:6379>lpushorder:user111214151617
(integer)6
在秒杀场景下,咱们能够将秒杀成功的用户先写进行列,后续的事务在依据行列中数据进行处理。
set类型
zet是一种调集类型,而且这种调集内的元素是无需且不会重复的。
set类型一般能够用在用户报到、网站拜访核算、用户重视标签、老友引荐、猜奖、随机数生成等事务场景。
某日用户报到状况。
127.0.0.1:6379>saddsign:2020-01-1612345678
(integer)8
127.0.0.1:6379>smemberssign:2020-01-16
1)”1″
2)”2″
3)”3″
4)”4″
5)”5″
6)”6″
7)”7″
8)”8″
键为详细某日,存储的值则是报到用户的id。
用户重视标签。
127.0.0.1:6379>sadduser:1:friend123456
(integer)6
127.0.0.1:6379>sadduser:2:friend11227456
(integer)6
127.0.0.1:6379>sinterstoreuser:relationuser:1:frienduser:2:friend
(integer)3
127.0.0.1:6379>smembersuser:relation
1)”4″
2)”5″
3)”6″
用户1重视了id为1,2,3,4,5,6的栏目。用户2重视了id为11,22,7,4,5,6的栏目。这儿取两个用户一起重视的栏目。
猜奖。
127.0.0.1:6379>spopuser:2:friend1
1)”5″
用set完成猜奖,首要是运用了随机抛出调集类的元素的特色。
zset类型
zset类型和set类型都是属于调集类型,两者不同点,在设置zset数据时要设置一个分数,这个分数能够用来做数据排序,而且zset类型的数据是有序的,因此zset也被叫做有序调集。
zset除了能够用在set能够用的场景下,更多的是能够用在排序的场景,如排行榜、延迟行列,就像未付出的订单在多少时刻内就失效。
报到排行榜。
127.0.0.1:6379>zaddgoods:order16108129871
(integer)1
127.0.0.1:6379>zaddgoods:order16108129802
(integer)1
127.0.0.1:6379>zaddgoods:order16108129503
(integer)1
127.0.0.1:6379>zaddgoods:order16108149504
(integer)1
127.0.0.1:6379>zcardgoods:order
(integer)4
127.0.0.1:6379>zrangebyscoregoods:order16108129501610812987
1)”3″
2)”2″
3)”1″
将用户的报到时刻作为排行的分数,最终查询指定范围内报到用户的id。
Bitmaps类型
Bitmaps底层存储的是一种二进制格式的数据。在一些特定场景下,用该类型能够极大的削减存储空间,由于存储的数据只能是0和1。为了便于了解,能够将这种数据格式了解为一个数组的方式存储。
运用该特色,能够将该类型用在一些拜访核算、报到核算等场景。
某个用户一个月的报到记载。
127.0.0.1:6379>setbituser:2020-0101
(integer)0
127.0.0.1:6379>setbituser:2020-0111
(integer)0
127.0.0.1:6379>setbituser:2020-0121
(integer)0
127.0.0.1:6379>bitcountuser:2020-0104
(integer)3
核算出该用户这个月只要4天报到。
核算某一天网站的报到数量。
127.0.0.1:6379>setbitsite:2020-01-1711
(integer)0
127.0.0.1:6379>setbitsite:2020-01-1731
(integer)0
127.0.0.1:6379>setbitsite:2020-01-1741
(integer)0
127.0.0.1:6379>setbitsite:2020-01-1761
(integer)0
127.0.0.1:6379>bitcountsite:2020-01-170100
(integer)4
127.0.0.1:6379>getbitsite:2020-01-175
(integer)0
这儿将用户的id作为偏移量,报到便是1。能够核算出详细拜访的总数,一起能够依据某个用户的id查询是否在当时报到。假如依据偏移量重复设置一个值,此刻不会被重复增加,仅仅Redis会回来1表明当时现已存在。
核算某段时刻内,都报到的用户数量。
127.0.0.1:6379>setbitsite:2020-01-1861
(integer)0
127.0.0.1:6379>setbitsite:2020-01-1841
(integer)0
127.0.0.1:6379>setbitsite:2020-01-1871
(integer)0
127.0.0.1:6379>bitopandcontinue:sitesite:2020-01-18site:2020-01-17
(integer)1
运用该场景,是由于该数据类型能够核算出多个key的交集(and)。一起能够取并集(or),或(or),异或(xor)。
HypefLogLog类型
HypefLogLog类型从运用上来说,有点类似于调集类型。该类型实践是一种字符串类型的数据结构。运用该类型最大的好处便是削减空间、但是也存在一定的误差率。该类型也是不允许同一个key存在重复元素。该类型也支撑合并多个key的值。
该数据类型一般用在一些不需要精确核算的核算类场景。
用户报到核算。
127.0.0.1:6379>pfadd2020:01:sgin12345678
(integer)1
#测验重复增加
127.0.0.1:6379>pfadd2020:02:sgin12345678
(integer)0
127.0.0.1:6379>pfadd2020:02:sgin9
(integer)1
127.0.0.1:6379>pfadd2020:02:sgin10
(integer)1
127.0.0.1:6379>pfadd2020:02:sgin11
(integer)1
127.0.0.1:6379>pfcount2020:02:sgin
(integer)11
GEO类型
GEO类型是一种存储地理信息的数据格式,基于该数据特色。能够用在一些间隔核算、附近引荐等事务场景。
间隔核算
127.0.0.1:6379>geoaddcity:distancenx121.3242.36beijing121.2038.56
shanghai100.3638.56sichuan
(integer)3
127.0.0.1:6379>geoposcity:distancebeijingshanghaisichuan
1)1)”121.32000178098678589″
2)”42.36000020595371751″
2)1)”121.19999974966049194″
2)”38.55999947301710762″
3)1)”100.3599974513053894″
2)”38.55999947301710762″
#核算出北京到上海的间隔
127.0.0.1:6379>geodistcity:distancebeijingshanghaikm
“422.7819”
Stream类型
Stream类型是Redis在5.0之后版别新增的一种数据结构。该数据结构首要用户音讯行列的场景。Redis自身是有一个Redis发布订阅(pub/sub)来完成音讯行列的功用,但它有个缺陷便是音讯无法持久化,假如呈现网络断开、Redis宕机等,音讯就会被丢掉。
音讯行列
#增加音讯行列
127.0.0.1:6379>xaddmessage*namezhangsanage12
“1610873104343-0″
127.0.0.1:6379>xrangemessage-+
1)1)”1610873104343-0″
2)1)”name”
2)”zhangsan”
3)”age”
4)”12″
#获取音讯行列
127.0.0.1:6379>xrevrangemessage+-count1
1)1)”1610873104343-0″
2)1)”name”
2)”zhangsan”
3)”age”
4)”12″

华为手表未来或将完成血糖风险评估

totozhan阅读(56)

华为运动健康军团CEO张炜发布了华为正在推动的三大健康研讨项目,即立异血糖、肺功用健康、高原健康研讨,并对华为运动健康全栈战略和立异技能进行深入解读。经过共享HUAWEI TruSeen 生命体征监测技能IP的迭代升级。
目前,HUAWEI TruSeen自研生命体征监测技能历时7年,融合华为运动健康科学实验室和华为全球研讨所的立异技能与研发实力。
2016年,TruSeen 1.0技能支撑静态心率监测;2017年TruSeen 2.0完成6种类型的动态心率监测, 而且支撑科学睡眠和压力测试,对健康数据的监测更多维。2018年,TruSeen 3.0完成了24小时实时心率监测;2019年,TruSeen 3.5打破血氧、游水心率及登高缺氧提醒。2020年TruSeen 4.0技能完成了医疗级心电图检测才能的打破,一同带来了周期性接连血氧监测功用。到2021年TruSeen 5.0+,动态心率准确性大幅提升,新增高原血氧监测才能,并完成了医疗级的血压检测才能。

手表
算法才能的不断提升,也得益于HUAWEI TruSeen心率技能在硬件方面才能的不断打破。在心率模组上,从4通道升级到8通道环形光路规划,内置传感器规划由分散到内聚,丈量设备的工艺品质、抗干扰才能得到大幅提升。在外观规划上,手表背部规划由平面演进为弧面蓝宝石表底,提升了心率监测信号质量的一同,佩带更舒适贴合。
因而除了软硬件层面的研讨,为了确保和不断提升心率的监测精准度。针对影响心率监测的三大变量要素:多样化的运动场景、广泛的人群差异以及改变的环境要素,华为还针对腕部进行了精细化研讨。
2021年,HUAWEI WATCH D经过国家药品监督管理局二类医疗器械注册证,并经过多家专业机构临床验证。
HUAWEI WATCH D比较于上臂式电子血压计,分量仅约为其1/6,一同选用立异微型气泵,面积仅为一角硬币巨细。气泵加压范围可达300mmHg,确保可测最高血压到达230mmHg,与传统血压仪丈量范围相同。双层窄气囊规划,当气囊充气后,双层气囊鼓胀使之更贴合手臂,增加贴合度和压迫效果,更“精准”感知脉息波改变。
首创Hybrid血压丈量技能,让随时随地监测血压成为可能。经过业界首创微泵与PPG的Hybrid血压丈量技能,HUAWEI WATCH D智能手表可经过微泵加压,完成单次精准血压丈量,除此之外,手表还可经过PPG技能完成接连无感的血压趋势监测,获得全天候的血压改变趋势。
2022年,华为将开展三大全新健康研讨,分别是立异血糖、肺功用健康及高原健康管理。
血糖研讨范畴,华为在有创、微创、无创技能上多路径探究,带来更快捷、舒适的高血糖风险筛查和管理。
一同,华为在呼吸慢病范畴继续发力,启动了肺功用研讨及慢阻肺筛查研讨两大呼吸范畴健康难题。
此外,在高原游览已成为潮流的当下,用户对高原健康监测有着更高的要求,华为穿戴设备在高原血氧监测功用的基础上,也有了更进一步的研讨成果。
针对运动,华为研发了一个科学运动体系TruSport,2021年在跑步场景下,华为推出的跑步才能衡量目标-跑力指数(RAI),跑力指数是用于衡量跑者的耐力水平和跑步技能效率的归纳目标,它依据跑者能够到达的最佳成果来划定。通常情况下跑力指数越高的跑者,意味着在比赛中会获得更好的成果。
在用户开启野外跑步并到达一定的跑步强度和时长后,根据HUAWEI WATCH GT Runner获取全面的专业的跑步的数据,例如配速、心率、跑步间隔等监测目标,智能评估跑力指数和练习压力,及阶段练习负荷、康复程度等。
根据TruSport规范框架,未来还将从跑步扩展到更多不同的运动场景,如游水、骑行,一同敞开TruSport才能,与职业伙伴一同在细分运动范畴进行研讨与服务的探究。

Cypress10.x版本迁移指南

totozhan阅读(52)

最近两年测验界最火的测验东西莫过于Cypress,作为测验工程师弯道超车必备、下一代UI主动化测验利器,Cypress开发团队也一直在拼命干事,这不,Cypress10.x重磅发布了。
Cypress10.x是迄今为止Cypress最大一次改版,假如你买了书,你会发现书上部分界面截图跟你装置Cypress10.x后看到的不一致,不要紧,底层没变,测验用例的编写和运转也没有任何改动。
所以当你看书时碰见装置、升级的问题,不要慌,能够先看这一篇<[最新版]Cypress10.x版别装置使用指南>,假如还有问题,直接Cypress我国群里问。
最大的改动
Cypress10.x最大的改动有如下3点:
1.引进了ComponentTesting(这块我会专门出个文章来讲)
Cypress官方将“ComponentTesting”重磅引进到了测验团队。测验人员又能够将自己的势力版图向开发侧移动一下啦:)
2.Cypress彻底区分了E2ETest和ComponmentTest
在老版别的Cypress中,Cypress没有过分着重E2ETest和ComponmentTest的不同。但在新版别的Cypress中,E2ETest和ComponmentTest将作为两种彻底独立的测验类型存在,测验装备也悉数独立。
这个也是Cypress做用户画像,将自己的优势聚焦的成果。Cypress官方声称没怎么见过有测验社区重视ComponmentTest,这次Cypress把自己的优势摘出来,把ComponmentTest生成独自的组件,愈加能凸显自己的差异性。另外也能够加速企业的购买决策。
3.重构了CypressAPP
Cypress10.x里看不到Cypress交互式测验运转器了,Cypress将它和DashBoard集成到一块,统称为CypressAPP,Cypress官方说新的Cypress版别更像一个产品,而不是一个开发东西。这也能够看到Cypress的野望,它希望以完整产品的方法存在。一起也带来了必定弊端,会让数据安全愈加凸显(Cypress的DashBoard服务类似于AWS,可是Cypress还不够出名和满足强大,所以企业难免会想我的测验用例运转在你平台上,会不会有安全隐患)。
Cypress10.x的升级后,在你运转测验时,你能够感觉出整个用户界面都被从头design了,用户体会也很不同。另外,Cypress还把自己的Logo都换掉了,这也能够看出Cypress对10.x版别的希望,未来Cypress将在商业化道路上越走越远。

Cypress
主要改动细节
1.cypress.json被移除
cypress.json文件被彻底移除了,Cypress10.x版别不支持cypress.json文件,转而支持cypress.config.js,cypress.config.ts。这两个文件能够根据你运转的项目而主动生成。
2.baseUrlandexperimentalSessionAndOrigin从大局装备变为部分装备。
E2E和Componment装备彻底分开了,所以每个测验类型都需要各自独立的装备,baseUrlandexperimentalSessionAndOrigin,以往放在cypress.json里,现在放在cypress.config.js/cypress.config.ts下的e2e或许Componment模块下。
const{defineConfig}=require(‘cypress’)
module.exports=defineConfig({
e2e:{
baseUrl:’http://localhost:1234′},
component:{
devServer:{
framework:’react’,//orvue
bundler:’webpack’,
webpackConfig,
}
})
3.supportFile也从大局装备退为部分装备。
曾经,cypress/support/index.js,现在不用了,改为cypress/support/e2e.js(格式为cypress/support/e2e.{js,jsx,ts,tsx})。
4.彻底去除Pluginsfile。转而被setupNodeEvents()代替。
曾经,cypress/plugins/index.js非常重要,我们许多于node交互的内容都写在这个文件下。Cypress10.x彻底把它去掉了,你需要把以往写在这个文件里的内容,移到cypress.config.js/cypress.config.ts下的e2e或许component模块下。
const{defineConfig}=require(‘cypress’)
module.exports=defineConfig({
e2e:{
setupNodeEvents(on,config){
//e2etestingnodeeventssetupcode
},
},
component:{
setupNodeEvents(on,config){
//componenttestingnodeeventssetupcode
},
},
}
简而言之,你需要把cypress/plugins整个文件夹删去去,然后把里面的内容,放到e2e或许component下的setupNodeEvents(on,config)里。(特别注意其实便是(on,config)下面的内容同步移过来就行)
5.defineConfig能够完结Cypress代码主动提示和补全功用了。
cypress.config.js/cypress.config.ts下面第一句写上这个,后边你在写cypress代码时,就会有主动提示和补全功用了。
const{defineConfig}=require(‘cypress’)
6.integrationFolder被彻底去掉了。
integrationFolder曾经放我们一切测验的文件,现在这个文件现已被彻底去掉,改叫e2e或许componment。
相应的,一切的测验用例,不再以文件夹方法来区分,转而变成testFiles→specPattern。举个例子来说,
//曾经
{
“componentFolder”:”src”,
“integrationFolder”:”cypress/integration”,
“testFiles”:”**/*.cy.js”}
//Cypress10.x今后
{
component:{
specPattern:’src/**/*.cy.js’},
e2e:{
specPattern:’cypress/integration/**/*.cy.js’}
一句话,你e2e的测验用例,就在cypress.config.js/cypress.config.ts下的e2e模块里,你component用例,就放在component模块下。
已然有specPattern,那么就有excludeSpecPattern。这个用法相同,只不是是把某些用例从测验用例里扫除出去。
7.今后你的测验用例要以*.cy.js结尾。
为了跟世界同步,最好你的测验用例后缀名使用Cypress最新的后缀*.cy.js,不要用*.spec.js了,要不你出去找工作面试要脱轨了。
8.ExperimentalCypressStudio被去掉了。
理由是要从头design,现在社区闹的厉害,我们都不乐意失去这个功用,究竟录制回放香啊。
9.CypressAPI的一些改动。
这些就不说了,用到再说了。
搬迁过程
改动太大了,我们接受的意愿就低,假如你彻底用Cypress默认的那一套还好,假如你跟我相同,做了许多定制,更改了许多默认文件夹,你肯定有点烦的。不过不要紧。Cypress给我们预备了一个搬迁东西。
老版别Cypress搬迁到Cypress10.x过程如下:
1.装置最新版别。在项目根目录下履行
npminstall-Dcypress@latest
这一步会装置最新的Cypress10.x
2.发动Cypress。在项目根目录下履行
npxcypressopen
这个时候,Migrate东西会主动呈现,而且告知你那些当地要改。
注意,这个当地只是在你用原始的默认装备才有用,假如你定制了Cypress的一些功用(假如你看了我的书,必定跟我相同,更改了Cypress的一些默认装备,那么这个就不起作用了)。
这个有点鸡肋的,当你发现Migrate东西不给力后,不要慌,看看上个部分Cypress的主要改动,然后一点点改就行,或许直接选择一个测验用例履行,它会报错,你一个个把报错的过错解决掉就完结搬迁啦。
搬迁要点
大概率仍是讲下要点:
1.cypress.json文件改成cypress.config.js/cypress.config.ts。
2.cypress.config.js/cypress.config.ts文件下的baseUrl,experimentalSessionAndOrigin等属性不能放在大局变量,要放e2e或许componment下。(不知道有哪些不要紧,直接运转测验,会有明确过错提示。这儿表扬下,前端开发的确要讲究一点)。
3.删去plugins整个文件夹,转而把plugins/index.js里面的内容都移动到cypress.config.js/cypress.config.ts下的e2e模块的setupNodeEvents里去。
4.support文件夹下的index.js改为e2e.js。
5.假如你跟我相同改了默认装备,在cypress.config.js/cypress.config.ts下的e2e模块下,设置好如下内容:
“specPattern”:”src/tests/**/*.cy.js”,
“excludeSpecPattern”:[
“**/__snapshots__/*”,
“**/__image_snapshots__/*”],
“fixturesFolder”:”src/configs”,
“supportFile”:”src/support/e2e.js”
6.再次提示下,cypress.config.js/cypress.config.ts下的e2e或许componment下的setupNodeEvents非常重要,你的plugins/index.js里的内容能不能用,就要看你移动不移动到这儿了。
7.更改一切测验文件后缀名为*.cy.js。
当然你也能够不改,在第5步里,specPattern里把后缀名改了(比如改成*.spec.js)就行。可是我主张你更改掉,究竟今后你出去面试,难免会碰见不懂装懂的面试官,到时候说你不懂新特性:),递归改名写个脚本吧,不要傻傻的手工去一个个改。
8.更改其他或许被影响的当地。
比如我有一些功用,交互式指令根据用户输入生成测验用例等,我就需要改下这部分。你或许也有自己的功用,自己改下吧。改好别着急merge代码,先跑几天。
假如搬迁还有问题,能够直接Cypress我国群里问,或许官网看看细节。
最终寄语

Prometheus时序数据库

totozhan阅读(52)

笔者最近担起了公司监控的重担,而当前监控最流行的数据库即是Prometheus。依照笔者打破砂锅问到底的精神,天然要把这个开源组件源码搞明白才行。在经过一系列源码/资料的阅览以及各种Debug之后,对其内部机制有了一定的认识。今日,笔者就来介绍下Prometheus的存储结构。
因为篇幅较长,所以笔者分为两篇,本篇首要是描绘Prometheus监控数据在内存中的存储结构。下一篇,首要描绘的是监控数据在磁盘中的存储结构。
Gorilla
Prometheus的存储结构-TSDB是参阅了Facebook的Gorilla之后,自行实现的。所以阅览
这篇文章《Gorilla:AFast,Scalable,In-MemoryTimeSeriesDatabase》
,可以对Prometheus为何选用这样的存储结构有着清晰的理解。
监控数据点
下面是一个十分典型的监控曲线。
可以调查到,监控数据都是由一个一个数据点组成,所以可以用下面的结构来保存最基本的存储单元
typesamplestruct{
tint64
vfloat64
}
同时咱们还需求注意到的信息是,咱们需求知道这些点归于什么机器的哪种监控。这种信息在Promtheus中就用Label(标签来表明)。一个监控项一般会有多个Label(例如图中),所以一般用labels[]Label。
因为在咱们的习气中,并不关心单独的点,而是要关心这段时刻内的曲线状况。所以天然而然的,咱们存储结构肯定逻辑上是这个姿态:
这样,咱们就可以很容易的经过一个Labels(标签们)找到对应的数据了。
监控数据在内存中的表明方式

数据库
最近的数据保存在内存中
Prometheus将最近的数据保存在内存中,这样查询最近的数据会变得十分快,然后经过一个compactor定时将数据打包到磁盘。数据在内存中最少保存2个小时(storage.tsdb.min-block-duration。至于为什么设置2小时这个值,应该是Gorilla那篇论文中调查得出的定论
即紧缩率在2小时时分达到最高,假如保存的时刻更短,就无法最大化的紧缩。
内存序列(memSeries)
接下来,咱们看下具体的数据结构
typememSeriesstuct{
……
refuint64//其id
lstlabels.Labels//对应的标签调集
chunks[]*memChunk//数据调集
headChunk*memChunk//正在被写入的chunk
……
}
其间memChunk是真实保存数据的内存块,将在后面讲到。咱们先来调查下memSeries在内存中的安排。
由此咱们可以看到,针对一个终究端的监控项(包含抓取的一切标签,以及新增加的标签,例如ip),咱们都在内存有一个memSeries结构。
寻址memSeries
假如经过一堆标签快速找到对应的memSeries。天然的,Prometheus就选用了hash。首要结构体为:
typestripeSeriesstruct{
series[stripeSize]map[uint64]*memSeries//记载refId到memSeries的映射
hashes[stripeSize]seriesHashmap//记载hash值到memSeries,hash冲突选用拉链法
locks[stripeSize]stripeLock//分段锁
}
typeseriesHashmapmap[uint64][]*memSeries
因为在Prometheus中会频频的对map[hash/refId]memSeries进行操作,例如查看这个labelSet对应的memSeries是否存在,不存在则创立等。因为golang的map非线程安全,所以其选用了分段锁去拆分锁。
而hash值是依据labelSets的值而算出来。
数据点的存储
为了让Prometheus在内存和磁盘中保存更大的数据量,必然需求进行紧缩。而memChunk在内存中保存的正是选用XOR算法紧缩过的数据。在这里,笔者只给出Gorilla论文中的XOR描绘
更具体的算法在论文中有详细描绘。总之,使用了XOR算法后,均匀每个数据点能从16bytes紧缩到1.37bytes,也就是说所用空间直接降为本来的1/12!
内存中的倒排索引
上面讨论的是标签悉数给出的查询状况。那么咱们怎样快速找到某个或某几个标签(非悉数标签)的数据呢。这就需求引进以Label为key的倒排索引。咱们先给出一组标签调集
{__name__:http_requests}{group:canary}{instance:0}{job:api-server}
{__name__:http_requests}{group:canary}{instance:1}{job:api-server}
{__name__:http_requests}{group:production}{instance:1}{job,api-server}
{__name__:http_requests}{group:production}{instance:0}{job,api-server}
可以看到,因为标签取值不同,咱们会有四种不同的memSeries。假如一次性给定4个标签,应该是很容易从map中直接获取出对应的memSeries(虽然Prometheus并没有这么做)。但大部分咱们的promql只是给定了部分标签,怎么快速的查找符合标签的数据呢?
这就引进倒排索引。
先看一下,上面比如中的memSeries在内存中会有4种,同时内存中还夹杂着其它监控项的series
假如咱们想知道job:api-server,group为production在一段时刻内一切的http恳求数量,那么有必要获取标签带着
({__name__:http_requests}{job:api-server}{group:production})的一切监控数据。
假如没有倒排索引,那么咱们有必要遍历内存中一切的memSeries(数万乃至数十万),逐个依照Labels去比对,这显然在性能上是不行接受的。而有了倒排索引,咱们就可以经过求交集的手段迅速的获取需求哪些memSeries。
注意,这边倒排索引存储的refId有必要是有序的。这样,咱们就可以在O(n)复杂度下顺利的算出交集,另外,针对其它恳求方式,还有并集/差集的操作,对应实现结构体为:
typeintersectPostingsstruct{…}//交集
typemergedPostingsstruct{…}//并集
typeremovedPostingsstruct{…}//差集
倒排索引的插入安排即为Prometheus下面的代码
Add(labels,t,v)
|->getOrCreateWithID
|->memPostings.Add
//Addalabelsettothepostingsindex.
func(p*MemPostings)Add(iduint64,lsetlabels.Labels){
p.mtx.Lock()
//将新创立的memSeriesrefId都加到对应的Label倒排里去
for_,l:=rangelset{
p.addFor(id,l)
}
p.addFor(id,allPostingsKey)//allPostingKey””,””everyone都加进去
p.mtx.Unlock()
}
正则支持
事实上,给定特定的Label:Value还是无法满足咱们的需求。咱们还需求对标签正则化,例如取出一切ip为1.1.*前缀的http_requests监控数据。为了这种正则,Prometheus还保护了一个标签一切可能的取值。对应代码为:
Add(labels,t,v)
|->getOrCreateWithID
|->memPostings.Add
func(h*Head)getOrCreateWithID(id,hashuint64,lsetlabels.Labels){

for_,l:=rangelset{
valset,ok:=h.values[l.Name]
if!ok{
valset=stringset{}
h.values[l.Name]=valset
}
//将可能取值塞入stringset中
valset.set(l.Value)
//符号表的保护
h.symbols[l.Name]=struct{}{}
h.symbols[l.Value]=struct{}{}
}

}
那么,在内存中,咱们就有了如下的表
图中所示,有了label和对应一切value调集的表,一个正则恳求就可以很容的分解为若干个非正则恳求并最后求交/并/查集,即可得到终究的结果。
总结
Prometheus作为当今最流行的时序数据库,其间有十分多的值得咱们借鉴的设计和机制。这一篇笔者首要描绘了监控数据在内存中的存储结构。

CSS 中几种最常用的水平垂直居中的办法

totozhan阅读(54)

CSS是前端里面的根底之一,也是非常重要的一部分,它往往决定了你所做出来的网页页面是否美观。在设计网页页面的过程中,总会有将元素或许文字进行水平笔直居中的要求。下面就为我们介绍CSS中几种常用到的水平笔直居中的办法。
01PART运用margin:auto
当元素有给定的高度以及宽度的时候,运用margin:auto;元素仅会水平居中,并不会进行笔直居中。此刻就需要设置元素的position为absolute,父级元素的position为relative,一起元素的上下左右都需要设置为0。
HTML代码
CSS代码
.box{width:200px;height:200px;background-color:#eee;position:relative;margin-top:20px;}.center1{width:50px;height:50px;background-color:#00ACED;margin:auto;position:absolute;top:0;left:0;right:0;bottom:0;}
作用展现:
02PART运用position:absolute
当现已知道了要进行水平笔直居中的元素的宽高时,就能够经过设置position:absolute来完成。但是,运用的一起还需要结合其他属性才完整完成。因为,单是设置absolute,上左间隔均为一半,就会出现下面这种状况。很显然能够看到,元素并不是彻底居中,仅只有左上角的位置在中心点
概念图:
因而想要完成元素彻底水平笔直居中,在设置了absolute定位后,能够设置margin值为负,或许运用calc来核算,上左间隔在50%的根底上还要减去元素本身一半的宽高。
margin值为负或许calc核算均是在已知元素宽高的状况下,假定不知道元素的宽高,那么怎样完成水平笔直居中呢?这儿就能够运用transform属性,经过坐标位移来完成居中。
CSS代码
/*结合margin*/.center2{width:50px;height:50px;background-color:#7FFFD4;position:absolute;left:50%;top:50%;margin-left:-25px;margin-top:-25px;}/*结合calc核算*/.center2{width:50px;height:50px;background-color:#7FFFD4;position:absolute;left:calc(50%-25px)top:calc(50%-25px);}/*结合transform*/.center2{width:50px;height:50px;background-color:#7FFFD4;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);}
作用展现

CSS
03PART运用弹性布局
能够经过弹性布局来设置水平笔直居中,这儿需要设置父级元素display:flex;还需要设置两个属性,水平布局justify-content以及笔直布局align-items。
HTML代码
class=”box2″><divclass=”center4″>div></div>
CSS代码:
.box2{background-color:#eee;width:200px;height:200px;position:relative;margin-top:20px;display:flex;justify-content:center;align-items:center;}.center4{width:50px;height:50px;background-color:#B39873;}
作用展现:
04PART文本水平对齐和行高
前面介绍的是元素怎么完成水平笔直居中,下面介绍的是怎么将文字进行水平笔直居中。这第一个办法也是最经常用的,运用文本水平对齐text-align和行高line-height来完成的。
HTML代码
class=”box3″><divclass=”center5″>文字居中div></div>
CSS代码
.box3{background-color:#eee;width:200px;height:200px;margin-top:20px;}.center5{text-align:center;line-height:200px;}
作用展现
05PART运用网格布局
第二个办法能够经过网格布局grid来完成。而这儿经过grid有两种方式完成,一种对元素本身属性进行设置,另一种在元素的父级元素中设置。两者看上去内容好像差不多,不同的是在元素中设置的是align-self还要多了一个margin,父级元素中是align-items。
相关代码:
/*grid元素中设置*/.box4{background-color:#eee;width:200px;height:200px;margin-top:20px;display:grid;}.center6{align-self:center;justify-content:center;margin:auto;}/*grid父级元素中设置*/.box5{background-color:#eee;width:200px;height:200px;margin-top:20px;display:grid;align-items:center;justify-content:center;}
作用展现:
06PART总结
以上便是关于CSS怎么将元素或许文字进行水平笔直居中的几种常用办法,我们还其他关于CSS完成水平笔直居中的办法吗?请在评论区留下你的想法。

Dubbo数据包

totozhan阅读(72)

今日给咱们带来一篇关于DubboIO交互的文章,本文是一位搭档所写,用风趣的文字把枯燥的知识点写出来,通俗易懂,十分有意思,所以刻不容缓找作者授权然后分享给咱们:
一些风趣的问题
Dubbo是一个优秀的RPC结构,其中有错综复杂的线程模型,本篇文章笔者从自己浅陋的认知中,来剖析Dubbo的整个IO进程。在开端之前,咱们先来看如下几个问题:
事务办法履行之后,数据包就发出去了吗?
netty3和netty4在线程模型上有什么区别?
数据包到了操作系统socketbuffer,阅历了什么?
Provider打出的log耗时很小,而Consumer端却超时了,怎样能够排查到问题?
数据包在物理层是一根管道就直接发过去吗?
Consumer事务线程await在Condition上,在哪个时机被唤醒?
……
接下来笔者将用Dubbo2.5.3作为Consumer,2.7.3作为Provider来叙述整个交互进程,笔者站在数据包视角,用第一人称来叙述,系好安全带,咱们动身咯。

Dubbo
有意思的游览
1、Dubbo2.5.3Consumer端建议请求
我是一个数据包,出生在一个叫Dubbo2.5.3Consumer的小镇,我的任务是是传递信息,一起也喜爱出门游览。
某一天,我行将被发送出去,据说是要去一个叫Dubbo2.7.3Provider的当地。
这一天,事务线程建议建议办法调用,在FailoverClusterInvoker#doInvoke我挑选了一个Provider,然后通过各种ConsumerFilter,再通过Netty3的pipeline,终究通过NioWorker#scheduleWriteIfNecessary办法,我来到了NioWorker的writeTaskQueue行列中。
当我回头看主线程时,发现他在DefaultFuture中的Condition等待,我不知道他在等什么,也不知道他要等多久。
我在writeTaskQueue行列排了一会队,看到netty3IOworker线程在永不停歇的履行run办法,咱们都称这个为死循环。
终究,我很走运,NioWorker#processWriteTaskQueue挑选了我,我被写到操作系统的Socket缓冲区,我在缓冲区等待,横竖时刻充足,我回味一下今日的游览,期间我辗转了两个游览团,分别叫主线程和netty3IOworker线程,嗯,两个游览团服务都不错,功率很高。
干脆我把今日的见闻记载下来,绘制成一张图,当然不重要的当地我就忽略了。
2、操作系统发送数据包
我在操作系统socket缓冲区,通过了许多神奇的工作。
在一个叫传输层的当地给我追加上了目标端口号、源端口号
在一个叫网络层的当地给我追加上了目标IP、源IP,一起通过目标IP与掩码做与运算,找到“下一跳”的IP
在一个叫数据链路层的当地通过ARP协议给我追加上了“下一跳”的目标MAC地址、源MAC地址
最有意思的是,咱们坐的都是一段一段缆车,每换一个缆车,就要修改目标MAC地址、源MAC地址,后来问了同行的数据包小伙伴,这个形式叫“下一跳”,一跳一跳的跳过去。这里有许多数据包,体型大的单独一个缆车,体型小的几个挤一个缆车,还有一个可怕的工作,体型再大一点,要分拆做多个缆车(尽管这对咱们数据包没啥问题),这个叫拆包和粘包。期间咱们通过交换机、路由器,这些当地玩起来很Happy。
当然也有不愉快的工作,就是拥堵,目的地缆车满了,来不及被拉走,只能等待咯。
3、在Provider端的阅历
好不容易,我来到了目的地,我坐上了一个叫“零拷贝”号的快艇,迅速到了netty4,netty4果然富丽堂皇,通过NioEventLoop#processSelectedKeys,再通过pipeline中的各种入站handler,我来到了AllChannelHandler的线程池,当然我有许多挑选,可是我随意选了一个目的地,这里会阅历解码、一系列的Filter,才会来的目的地“事务办法”,NettyCodecAdapter#InternalDecoder解码器很厉害,他能够处理拆包和粘包。
在AllChannelHandler的线程池中我会停留一会,所以我也画了一张图,记载旅程。
自此,我的游览完毕,新的故事将由新的数据包续写。
4、Provider端产生了新的数据包
我是一个数据包,出生在一个叫Dubbo2.7.3Provider的小镇,我的任务是去唤醒命中注定的线程,接下来我会开端一段游览,去一个叫Dubbo2.5.3Consumer的当地。
在Provider事务办法履行之后
由事务线程通过io.netty.channel.AbstractChannelHandlerContext#writeAndFlush
再通过io.netty.util.concurrent.SingleThreadEventExecutor#execute履行addTask
将任务放入行列io.netty.util.concurrent.SingleThreadEventExecutor#taskQueue
我便跟随着io.netty.channel.AbstractChannelHandlerContext$WriteTask等待NioEventLoop发车,等待的进程中,我记载了走过的脚步。
在这里,我看到NioEventLoop是一个死循环,不停地从任务行列取任务,履行任务AbstractChannelHandlerContext.WriteAndFlushTask,然后指引咱们到socket缓冲区等候,永不知疲倦,我似乎领会到他身上有一种倔强的、寻求极致的匠人精力。
通过io.netty.channel.AbstractChannel.AbstractUnsafe#write,我抵达了操作系统socket缓冲区。在操作系统层面和大多数数据包相同,也是做缆车抵达目的地。
5、抵达dubbo2.5.3Consumer端
抵达dubbo2.5.3Consumer端,我在操作系统socket缓冲区等了一会,同样是坐了“零拷贝”号快艇,抵达了真正的目的地dubbo2.5.3Consumer,在这里我发现,NioWorker#run是一个死循环,然后履行NioWorker#processSelectedKeys,通过NioWorker#read方式读出来,我就抵达了AllChannelHandler的线程池,这是一个事务线程池。
我在这里等待一会,等任务被调度,我看见com.alibaba.dubbo.remoting.exchange.support.DefaultFuture#doReceived被履行了,一起Condition的signal被履行了。我在远处看到了一个被堵塞线程被唤醒,我似乎明白,因为我的到来,唤醒了一个沉睡的线程,我想这应该是我生命的意义。
至此,我的任务也完成了,本次旅程完毕。
总结netty3和netty4的线程模型
咱们根据两个数据包的自述,来总结一下netty3和netty4的线程模型。
1、netty3写进程
2、Netty4的读写进程
阐明:这里没有netty3的读进程,netty3读进程和netty4相同,pipeline是由IO线程履行。
总结:netty3与netty4线程模型的区别在于写进程,netty3中pipeline由事务线程履行,而netty4无论读写,pipeline一致由IO线程履行。
netty4中ChannelPipeline中的Handler链一致由I/O线程串行调度,无论是读还是写操作,netty3中的write操作时由事务线程处理Handler链。netty4中能够下降线程之间的上下文切换带来的时刻耗费,可是netty3中事务线程能够并发履行Handler链。如果有一些耗时的Handler操作会导致netty4的功率低下,可是能够考虑将这些耗时操作放在事务线程最早履行,不放在Handler里处理。因为事务线程能够并发履行,同样也能够提高功率。
一些疑难问题排查
有遇到一些比较典型的疑难问题,例如当Provider容许的didi.log耗时正常,而Consumer端超时了,此刻有如下排查方向,didi.log的Filter其实处于十分里层,往往不能反映实在的事务办法履行情况。
Provider除了事务方向履行外,序列化也有或许是耗时的,所以能够用arthas监控最外侧办法org.apache.dubbo.remoting.transport.DecodeHandler#received,扫除事务办法耗时高的问题
Provider中数据包写入是否耗时,监控io.netty.channel.AbstractChannelHandlerContext#invokeWrite办法
通过netstat也能查看当前tcpsocket的一些信息,比方Recv-Q,Send-Q,Recv-Q是现已到了接受缓冲区,可是还没被应用代码读走的数据。Send-Q是现已到了发送缓冲区,可是对方还没有回复Ack的数据。这两种数据正常一般不会堆积,如果堆积了,或许就有问题了。
看ConsumerNioWorker#processSelectedKeys(dubbo2.5.3)办法是否耗时高。
直到终究整个链路的所有细节……问题肯定是能够解决的。
尾声
在整个交互进程中,笔者省略线程栈调用的一些细节和源代码的细节,例如序列化与反序列化,dubbo怎样读出完好的数据包的,事务办法履行前那些Filter是怎样排序和散布的,netty的Reactor形式是怎么完成的。这些都是十分风趣的问题……

全球直播下载-让更多人看到你

登录/注册返回首页