All posts by 龙生
照片规格 尺寸
1寸 2.5*3.5cm 大1寸 3.3*4.8cm 小1寸 2.6*3.6cm 2寸 3.5*5.3cm 小2寸(护照) 4.8*3.3cm 5 寸 12.7*8.9cm 6 寸 15.2*10.2cm 7 寸 17.8*12.7cm 8 寸 20.3*15.2cm 10寸 25.4*20.3cm 12寸 30.5*20.3cm 15寸 38.1*25.4cm
View Details2018年 DevOps 学习路径图
DevOps 目前非常热门,我认识的大多数朋友,同事和高级开发者都在努力成为 DevOps 工程师,并将自己作为组织中的 DevOps 拥护者。 虽然我承认 DevOps 的好处,它与改进的软件开发和部署直接相关,但从我有限的经验来看,我可以说这不是一件容易的事。在如此多的工具和实践中选择正确的路径是非常困难的。 作为一个 Java 博主,我的读者经常会问到一些问题,例如:如何成为 DevOps 工程师,我应该学些什么?我应该进行什么样的训练?学习 Maven 和 Jenkins 一定是为了成为 DevOps 工程师吗?Dcoker 和 Kubernetes 怎么样?DevOps 如何建设基础的自动化流程?我是否应该学习 Chef、Puppet 或者 Ansible?读者们不断向我提出各种各样的问题,这些只是其中的一部分。 我在自己有限的经验中搜索答案,尽已所能回答那些问题。我不能使用一种简单、有效、可复用的方式把回答记录下来,不过没关系。 今天我将与大家分享一个很棒的资源,它将帮助你成为你一直想成为的 DevOps 工程师,2018年 DevOps 路线图。 昨天我在网上闲逛的时候,偶然发现了 Kamranahmedse 的 GitHub 页面,上面有一些有用的路线图,可以帮助我成为前端开发人员、后端开发人员、全栈 web 开发人员,最后也是最重要的,DevOps 工程师。 这个路线图在任何意义上都是非常棒的,因为它不仅强调了 DevOps 工程师的角色,而且还告诉了你需要学习哪些工具和技术来涵盖这个领域。 最重要的是,它在视觉上很吸引人(你喜欢黄色和奶油色的蓝色线条吗?),所以你可以打印出来并粘在桌子上以便于参考。 虽然路线图很好,但它告诉你要学什么,但它没有告诉你如何学习和在哪里学习。 为了完成路线图,我分享了一些有用的在线课程,包括免费和付费,以便你可以学习和改进你想要的工具或领域。 开发人员 2018 年的 DevOps 路线图 我谈到 2018 DevOps 路线图是这个: Kamran Ahmed (kamranahmedse) 制图 (https://github.com/kamranahmedse/developer-roadmap) 现在,我们按照路线图逐步了解在 2018 年该如何掌握 DevOps 的基本技能: 1. 学习一门编程语言 Java、Python 和 JavaScript 是三种主要的编程语言,我相信你们至少知道一种。 如果你一种都不知道,也没关系。你可以通过下面的介绍的教程来选择一种语言。但我仍然强烈建议你至少学会上述三种通用的主流编程语言中的一种。 Java 如果你想学习 Java,Java 大师养成是门不错的教程,最近它刚针对 Java 10 时行了更新。 Python 如果你想学习 Python,我推荐一门自己最喜欢的课程:完全 Python 训练营。它能教会你 Python 3 这个最流行的 Python 版本。 JavaScript 如果你想学 JavaScript,那千万不要错过 Mosh Hamdani 在 Udemy 上的 JavaScript 基础入门。 如果你需要更多选择,而且愿意通过免费的资源来学习,那么你可以在我列出的清单中找到免费的 Java、Python 和 JavaScript 教程。 2. 了解不同的操作系统概念 这是 Ops 部分开始的地方,早些时候它只是由知道操作系统和硬件的系统管理员支持,但是对于 DevOps,现在开发人员也需要了解它们了。 您至少需要了解路线图中建议的流程管理、线程和并发、套接字、I/O管理、虚拟化、内存存储和文件系统。 由于我们大多数人都在 Linux 工作,我建议你通过 Udemy 上的 Linux Administration BootCamp 课程来更好地学习和理解 Linux 操作系统。 如果您需要更多选择并且不介意从可用资源中学习,那么您还可以查看此 免费的 Linux 课程。 3. 掌握终端生存大法 作为 DevOps 人,能在命令行终端中熟练的使用命令那必须要掌握的,尤其是在 Linux 环境中。必须要了解,Linux 的 shell,如 Bash、或者 Ksh;一些小工具比如 find、grep、awk、sed、lsof;还有网络命令像 nslookup […]
View Details15个最佳的代码评审(Code Review)工具
代码评审可以被看作是计算机源代码的测试,它的目的是查找和修复引入到开发阶段的应用程序的错误,提高软件的整体素质和开发者的技能。代码审查程序以各种形式,如结对编程,代码抽查等。在这个列表中,我们编制了15个最好的代码审查工具,这将有助于开发者节省代码审查时间。 您可能感兴趣的相关文章 Web 前端开发人员和设计师必读精华文章推荐 精心挑选的优秀jQuery Ajax分页插件和教程 12个让人惊叹的的创意的 404 错误页面设计 让网站动起来!12款优秀的 jQuery 动画插件 8个前沿 HTML5 & CSS3 效果【附源码下载】 1. Gerrit Gerrit is a web based code review system, facilitating online code reviews for projects using the Git version control system. Gerrit makes reviews easier by showing changes in a side-by-side display, and allowing inline comments to be added by any reviewer. Gerrit simplifies Git based project maintainership by permitting any authorized user to submit changes to the master Git repository, rather than requiring all approved changes to be […]
View DetailsJavaScript数字精度丢失问题总结
本文分为三个部分 JS 数字精度丢失的一些典型问题 JS 数字精度丢失的原因 解决方案(一个对象+一个函数) 一、JS数字精度丢失的一些典型问题 1. 两个简单的浮点数相加 1 0.1 + 0.2 != 0.3 // true Firebug 这真不是 Firebug 的问题,可以用alert试试 (哈哈开玩笑)。 看看Java的运算结果 再看看Python 2. 大整数运算 1 9999999999999999 == 10000000000000001 // ? Firebug 16位和17位数竟然相等,没天理啊。 又如 1 2 var x = 9007199254740992 x + 1 == x // ? 看结果 三观又被颠覆了。 3. toFixed 不会四舍五入(Chrome) 1 1.335.toFixed(2) // 1.33 Firebug 线上曾经发生过 Chrome 中价格和其它浏览器不一致,正是因为 toFixed 兼容性问题导致 二、JS 数字丢失精度的原因 计算机的二进制实现和位数限制有些数无法有限表示。就像一些无理数不能有限表示,如 圆周率 3.1415926…,1.3333… 等。JS 遵循 IEEE 754 规范,采用双精度存储(double precision),占用 64 bit。如图 意义 1位用来表示符号位 11位用来表示指数 52位表示尾数 浮点数,比如 1 2 0.1 […]
View Details学习ES6零基础-彩票项目中,解决项目代码中运行错误的问题
最近在学习ES6,在B站上看了一些视频再结合阮一峰老师的《ES6标准入门》基本上对ES6的各特性过了一遍,那就开始动手练项目咯,在找到视频对应的代码后,下载并运行出现了几个问题,通过百度又没查到相关的解决思路,这不还得科学上网,毕竟你询问的人群是全世界,总有适合的哪一个。话不说,开始叙述问题,并一步步的解决问题。项目的源代码在我的github上:https://github.com/sun2013126370/es6-lottery-master,视频的话去B站找咯。 先说一下我的相关配置吧
1 2 3 4 |
nodejs版本: v10.13.0 npm版本:6.4.1 gulp版本:CLI version 3.9.1(全局安装-npm install -g gulp) |
1 2 3 第一个问题: Failed to load external module @babel/register 网上说gulp的版本变成3.9.0(命令:npm install -g gulp@3.9.0)就可以,可以解决这个问题,但是至今还没找到出现这个问题的原因。还好,这个问题并不影响项目的运行,因此选择忽略这个错误或者将gulp的版本换成3.9.0都可以。 第二个问题:TypeError: require.extensions.hasOwnProperty is not a function 这个问题是由版本造成的,打开项目中的package.json,将0.3.1版本改成0.3.2即可,并执行npm install 命令。 重新执行gulp --watch命令,又发现了如下错误,go on! 第三个问题:gulp[13772]: src\node_contextify.cc:628: Assertion `args[1]->IsString()’ failed. 具体什么原因,还没有搞明白,后续再补充。解决这个问题的办法就是npm install natives,再次运行 gulp --watch,OK啦,项目起来了。在浏览器输入localhost:3000,就看到效果了。那接下来就是敲敲项目代码,把出现问题的原因找出来。 from:https://blog.csdn.net/a2013126370/article/details/84102343
View DetailsNodejs Sass安装报错一招解决
背景: 这个问题不是一天两天了,有时候是网速不行,有时候是被墙了,有时候是github把node-sass的包转移目录导致下载失败。 Cannot download "https://github.com/sass/node-sass/releases/download/xxx/binding.node的问题 另附node-sass的binding.node各个版本的安装包,哪里少,就单独下载哪个,下载完了之后,跟着我,一起把文件放在指定位置即可解决这个问题 https://github.com/sass/node-sass/releases/tag/v4.7.2 1.本机位置 C:\Users\Administrator\AppData\Roaming\npm-cache\node-sass\ 这个里面是各种版本,报错提示你哪个版本下载失败,你就塞到哪个版本的文件夹里,如图所示 2.删除项目的node_moduls目录 3.重新npm install 4.另附全局安装命令
1 2 3 |
npm i sass-loader node-sass webpack <span class="hljs-comment">--g</span> npm i style-loader css-loader <span class="hljs-comment">--g</span> |
qq 43163707 落雨 本文地址:http://www.cnblogs.com/ae6623/p/8711853.html
View Detailsgulp自定义标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
var gulp = require('gulp'); var connect = require('gulp-connect'); var replace = require('gulp-replace'); function defaultTask(cb) { // place code for your default task here cb(); replaceTask(); connect.server({ root: "build", port:8888 }); connect.serverClose(); } function replaceTask(){ /*index*/ gulp.src(['./index.html']) .pipe(replace("@@{user_domain_url}", "http://user.domain.com")) .pipe(replace('@@{nickname}', 'gz')) .pipe(gulp.dest('build/')); /*js*/ gulp.src(['js/*.js']) .pipe(replace("@@{user_domain_url}", "http://user.domain.com")) .pipe(replace('@@{nickname}', 'gz')) .pipe(gulp.dest('build/js')); } exports.default = defaultTask; |
View Details
前端构建工具gulp超详细配置, 使用教程(图文)
流程 1. 输入命令(可以使用git bash或者命令控制台cmd) npm install -g gulp 安装全局gulp命令 2. 创建一个项目文件夹, 当前项目文件夹下输入命令npm init 配置package.json文件, 这一部分看情况自己决定是否填, 不想填也可以, 直接按回车 当前项目文件夹下输入命令npm install gulp --save-dev 全局安装gulp后,还需要在每个要使用gulp的项目中都单独安装一次 开始使用gulp 其实, gulp的使用比webpack要简单很多. 配置gulpflie.js文件 在当前项目文件下创建文件名为gulpfile.js文件, 作为该项目配置文件.
1 2 3 4 5 6 |
//gulpfile.js var gulp = require('gulp'); gulp.task('default',function(){ console.log('hello world'); }); |
其实在项目文件夹下输入命令gulp时, 就是触发这个default任务, 因此, 我们定义多个自定义事件, 这样在输入gulp时, 就可以直接将我们写的命令也一起触发. gulp API gulp.src(globs[, options]) globs参数是文件匹配模式(类似正则表达式),用来匹配文件路径(包括文件名),当然这里也可以直接指定某个具体的文件路径。当有多个匹配模式时,该参数可以为一个数组。 options为可选参数。通常情况下我们不需要用到。 下面我们重点说说Gulp用到的glob的匹配规则以及一些文件匹配技巧。 名称 说明 * 匹配文件路径中的0个或多个字符,但不会匹配路径分隔符,除非路径分隔符出现在末尾 ** 匹配路径中的0个或多个目录及其子目录,需要单独出现,即它左右不能有其他东西了。如果出现在末尾,也能匹配文件。 ? 匹配文件路径中的一个字符(不会匹配路径分隔符) […] 匹配方括号中出现的字符中的任意一个,当方括号中第一个字符为^或!时,则表示不匹配方括号中出现的其他字符中的任意一个,类似js正则表达式中的用法 !(pattern|pattern|pattern) 匹配任何与括号中给定的任一模式都不匹配的 ?(pattern|pattern|pattern) 匹配括号中给定的任一模式0次或1次,类似于js正则中的(pattern|pattern|pattern)? +(pattern|pattern|pattern) 匹配括号中给定的任一模式至少1次,类似于js正则中的(pattern|pattern|pattern)+ *(pattern|pattern|pattern) 匹配括号中给定的任一模式0次或多次,类似于js正则中的(pattern|pattern|pattern)* @(pattern|pattern|pattern) 匹配括号中给定的任一模式1次,类似于js正则中的(pattern|pattern|pattern) 例子:
1 2 3 4 5 6 7 8 |
//转换html文件 gulp.task('html', function(){ gulp.src('./src/index.html') .pipe(connect.reload()) .pipe(gulp.dest('./dist'));//写入命令 }); 当有多种匹配模式时可以使用数组 |
1 2 3 4 |
//使用数组的方式来匹配多种文件 gulp.src(['js/*.js','css/*.css','*.html']) 使用数组的方式还有一个好处就是可以很方便的使用排除模式,在数组中的单个匹配模式前加上!即是排除模式,它会在匹配的结果中排除这个匹配,要注意一点的是不能在数组中的第一个元素中使用排除模式 |
1 2 |
gulp.src([*.js,'!b*.js']) //匹配所有js文件,但排除掉以b开头的js文件 gulp.src(['!b*.js',*.js]) //不会排除任何文件,因为排除模式不能出现在 |
数组的第一个元素中 此外,还可以使用展开模式。展开模式以花括号作为定界符,根据它里面的内容,会展开为多个模式,最后匹配的结果为所有展开的模式相加起来得到的结果。展开的例子如下: a{b,c}d 会展开为 abd,acd a{b,}c 会展开为 abc,ac a{0..3}d 会展开为 a0d,a1d,a2d,a3d a{b,c{d,e}f}g 会展开为 abg,acdfg,acefg a{b,c}d{e,f}g 会展开为 abdeg,acdeg,abdeg,abdfg gulp.dest(path[,options]) gulp.dest()方法是用来写文件的 path为写入文件的路径 options为一个可选的参数对象,通常我们不需要用到 要想使用好gulp.dest()这个方法,就要理解给它传入的路径参数与最终生成的文件的关系。 gulp的使用流程一般是这样子的:首先通过gulp.src()方法获取到我们想要处理的文件流,然后把文件流通过pipe方法导入到gulp的插件中,最后把经过插件处理后的流再通过pipe方法导入到gulp.dest()中,gulp.dest()方法则把流中的内容写入到文件中,这里首先需要弄清楚的一点是,我们给gulp.dest()传入的路径参数,只能用来指定要生成的文件的目录,而不能指定生成文件的文件名,它生成文件的文件名使用的是导入到它的文件流自身的文件名,所以生成的文件名是由导入到它的文件流决定的,即使我们给它传入一个带有文件名的路径参数,然后它也会把这个文件名当做是目录名,例如:
1 2 3 4 5 6 7 8 |
var gulp = require('gulp'); gulp.src('script/jquery.js') .pipe(gulp.dest('dist/foo.js')); //最终生成的文件路径为 dist/foo.js/jquery.js,而不是dist/foo.js 要想改变文件名,可以使用插件gulp-rename 下面说说生成的文件路径与我们给gulp.dest()方法传入的路径参数之间的关系。 gulp.dest(path)生成的文件路径是我们传入的path参数后面再加上gulp.src()中有通配符开始出现的那部分路径。例如: |
1 2 3 4 5 6 7 |
var gulp = reruire('gulp'); //有通配符开始出现的那部分路径为 **/*.js gulp.src('script/**/*.js') .pipe(gulp.dest('dist')); //最后生成的文件路径为 dist/**/*.js //如果 **/*.js 匹配到的文件为 jquery/jquery.js ,则生成的文件路径为 dist/jquery/jquery.js 再举更多一点的例子 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
gulp.src('script/avalon/avalon.js') //没有通配符出现的情况 .pipe(gulp.dest('dist')); //最后生成的文件路径为 dist/avalon.js //有通配符开始出现的那部分路径为 **/underscore.js gulp.src('script/**/underscore.js') //假设匹配到的文件为script/util/underscore.js .pipe(gulp.dest('dist')); //则最后生成的文件路径为 dist/util/underscore.js gulp.src('script/*') //有通配符出现的那部分路径为 * //假设匹配到的文件为script/zepto.js .pipe(gulp.dest('dist')); //则最后生成的文件路径为 dist/zepto.js 通过指定gulp.src()方法配置参数中的base属性,我们可以更灵活的来改变gulp.dest()生成的文件路径。 当我们没有在gulp.src()方法中配置base属性时,base的默认值为通配符开始出现之前那部分路径,例如: |
[…]
View DetailsJava Platform Standard Edition 8 Documentation
Oracle has two products that implement Java Platform Standard Edition (Java SE) 8: Java SE Development Kit (JDK) 8 and Java SE Runtime Environment (JRE) 8. JDK 8 is a superset of JRE 8, and contains everything that is in JRE 8, plus tools such as the compilers and debuggers necessary for developing applets and applications. JRE 8 provides the libraries, the Java Virtual Machine (JVM), and other components to run applets and applications written in the Java programming language. Note that the JRE includes components not required […]
View Details高并发接口设计思路
并发队列的选择 Java的并发包提供了三个常用的并发队列实现,分别是:ArrayBlockingQueue、ConcurrentLinkedQueue 和 LinkedBlockingQueue 。 ArrayBlockingQueue是**初始容量固定**的阻塞队列,我们可以用来作为数据库模块成功竞拍的队列,比如有10个商品,那么我们就设定一个10大小的数组队列。 ConcurrentLinkedQueue使用的是CAS原语无锁队列实现,是一个异步队列,入队的速度很快,出队进行了加锁,性能稍慢。 LinkedBlockingQueue也是阻塞的队列,入队和出队都用了加锁,当队空的时候线程会暂时阻塞。 在请求预处理阶段,由于我们的系统入队需求要远大于出队需求,一般不会出现队空的情况,所以我们可以选择ConcurrentLinkedQueue来作为我们的请求队列实现 1. 请求接口的合理设计 一个秒杀或者抢购页面,通常分为2个部分,一个是静态的HTML等内容,另一个就是参与秒杀的Web后台请求接口。 通常静态HTML等内容,是通过CDN的部署,一般压力不大,核心瓶颈实际上在后台请求接口上。这个后端接口,必须能够支持高并发请求,同时,非常重要的一点,必须尽可能“快”,在最短的时间里返回用户的请求结果。为了实现尽可能快这一点,接口的后端存储使用内存级别的操作会更好一点。仍然直接面向MySQL之类的存储是不合适的,如果有这种复杂业务的需求,都建议采用异步写入。 当然,也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果,一段时间后才可以从页面中看到用户是否秒杀成功。但是,这种属于“偷懒”行为,同时给用户的体验也不好,容易被用户认为是“暗箱操作”。 高并发下的数据安全 我们知道在多线程写入同一个文件的时候,会存现“线程安全”的问题(多个线程同时运行同一段代码,如果每次运行结果和单线程运行的结果是一样的,结果和预期相同,就是线程安全的)。如果是MySQL数据库,可以使用它自带的锁机制很好的解决问题,但是,在大规模并发的场景中,是不推荐使用MySQL的。秒杀和抢购的场景中,还有另外一个问题,就是“超发”,如果在这方面控制不慎,会产生发送过多的情况。我们也曾经听说过,某些电商搞抢购活动,买家成功拍下后,商家却不承认订单有效,拒绝发货。这里的问题,也许并不一定是商家奸诈,而是系统技术层面存在超发风险导致的。 1. 超发的原因 假设某个抢购场景中,我们一共只有100个商品,在最后一刻,我们已经消耗了99个商品,仅剩最后一个。这个时候,系统发来多个并发请求,这批请求读取到的商品余量都是99个,然后都通过了这一个余量判断,最终导致超发。(同文章前面说的场景) 在上面的这个图中,就导致了并发用户B也“抢购成功”,多让一个人获得了商品。这种场景,在高并发的情况下非常容易出现。 2. 悲观锁思路 解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。 悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。 虽然上述的方案的确解决了线程安全的问题,但是,别忘记,我们的场景是“高并发”。也就是说,会很多这样的修改请求,每个请求都需要等待“锁”,某些线程可能永远都没有机会抢到这个“锁”,这种请求就会死在那里。同时,这种请求会很多,瞬间增大系统的平均响应时间,结果是可用连接数被耗尽,系统陷入异常。 3. FIFO队列思路 那好,那么我们稍微修改一下上面的场景,我们直接将请求放入队列中的,采用FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。看到这里,是不是有点强行将多线程变成单线程的感觉哈。 然后,我们现在解决了锁的问题,全部请求采用“先进先出”的队列方式来处理。那么新的问题来了,高并发的场景下,因为请求很多,很可能一瞬间将队列内存“撑爆”,然后系统又陷入到了异常状态。或者设计一个极大的内存队列,也是一种方案,但是,系统处理完一个队列内请求的速度根本无法和疯狂涌入队列中的数目相比。也就是说,队列内的请求会越积累越多,最终Web系统平均响应时候还是会大幅下降,系统还是陷入异常。 4. 乐观锁思路 这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号(Version)更新。实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。 有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。 from:https://my.oschina.net/momisabuilder/blog/2992962
View Details