灯小笼 发布的文章

老婆在mac最新的MacOS Mojave系统里边安装了photoshop cc 2016以后,发现在使用触控板的时候,没有触感了,尝试了各种重装,重装ps,重装wacom驱动,都没有凑效。

在百度搜了一下,发现有一篇通过修改系统隐私的方案比较靠谱,于是照着操作了一番,果然ok了。不过,老婆在我操作成功之后说,实际上她也找到了那篇文章,但是在设置隐私的时候,发现都是置灰的状态,不能操作,就没有继续下去了。因此,这篇文章将通过图文并茂的形式,帮助大家快速解决这个问题。

- 阅读剩余部分 -

虹软的人脸识别sdk提供了免费的离线人像识别功能,识别速度也很快,可以很便捷地集成在各种不同的开发语言里边,使用到广泛的应用场景。不过,在集成到我们的门禁系统(基于java)的时候,还是遇到了一些坑,这里记录一下,希望对其他使用虹软(arcsoft)的朋友有所帮助。

- 阅读剩余部分 -

题目:有金额M元,给N个人发红包,最低0.01元,完全随机,不设上限,全部金额都需发放出去。

思路:可以借鉴发牌的算法,将金额以最小发放单位0.01元换算,等价于M*100张牌。那么我们要做的是,从M*100张牌里边随机抽出N-1张牌,计算这N-1张牌中间隔出来的N个区间的差值即可。

- 阅读剩余部分 -

将Lombok注解应用到一个项目中可以大大减少在IDE中生成或手工编写的样板代码行数。这样可以减少维护开销,减少bug,提高类的可读性。

在idea中要使用lombok是很简单的事情,只需要安装一个lombok plugin,然后在pom.xml加入对lombok的依赖即可。

与任何技术选择一样,使用Lombok既有积极的作用,也会有消极的影响。而最典型的不好的一面就是,将源代码生成javadoc的时候,因为源码里边使用了lombok,只声明了private的属性,而未编写setter/setter方法等,最后生成的文档当然就不会包含这些属性的getter和setter方法。先通过一个简单的例子复现一下这个场景。

- 阅读剩余部分 -

最近redis很“忙”,一到上午10点左右,redis就频繁出现各种报错,大部分的场景还好,我们对cache的异常进行了捕获,只是在日志里边记录一下,而不会抛出异常,所以顶多就慢一些而已。不过,还是有让我们也不得不忙的场景出来:

1、有的场景使用redis缓存校验码,比如用户通过手机验证码登录时,明明发送验证码成功,明明输入正确的验证码,但是就是提示验证失败。

2、随着每个依赖redis的服务不断变慢,网站不断出现502,最后,基本上不能访问了。

于是,运维人员不得不一声令下,重启redis。终于,作为cache的redis内存占用量急剧下降,连接数也迅速降低,网站也很快恢复稳定,一切似乎完美地回归了。

这样的事情重复了几天,大家找到规律了,于是索性定了个定时任务,每天凌晨5点的时候,重启一下redis,为即将躁动的10点偃旗息鼓,杀杀他的威风。

不过,作为有技术素养有技术追求的团队,怎么能这样就认怂了呢?

- 阅读剩余部分 -

一般我们说优化mysql,总是会将着眼点放在mysql的慢查询的优化上,或者字段的数据类型,mysql的分库/分表,读写分离,异或事务这些看上去高大上的东东上。但是,对于一些更加基础或者更加常识的地方,往往会加以忽视。就比如,本文将要提到的:mysql的查询本身的优化。

这次接到的优化任务出现的背景是:
我们有一个内部电话呼叫的系统,在下午使用客服相对较多的时候,在很随机的情况下,会出现突然的卡顿,这种现象维持的时间很短,检查的时候,往往发现cpu、内存、负载、网络,都很正常,查询错误日志也看不到异常。

系统用的是阿里云,2C4G,看负载的曲线也维持得很小很平稳,内存消耗也没有达到瓶颈。中间一度怀疑过对缓存的使用有问题,因为有很多临时数据都是通过cache在传输和保存的,调用频率也很高。于是,负责此项目的同学也做过很多方面的优化,想过很多招数。比如:
1、临时数据的保存从全量改为增量,大大降低了数据传输的量。
2、将数据库改成长连接,减少连接使用量。
原来我们使用的数据库是由阿里云提供的,后来降配了,长连接经常出现连接数不够的时候,又改为普通连接了。最后,我们又把mysql改成了自建,连接数2000,还是够用的。不过,即使使用长连接的时候,依然会出现卡顿,索性,就一直维持着使用普通连接了。

- 阅读剩余部分 -

一直以为,抓取网站整站,要么需要一个非常牛的工具,要么自己用curl之类写一个。这次想把caddy的英文文档的站点做个镜像的时候,竟然发现可以直接利用wget来实现,还真是小瞧了这个常见的工具了。

wget的参数的详解,网上已经很多了,就不再copy了,有兴趣详细了解的朋友可以参考下面的链接:

首先,我想做caddy的doc的镜像的原因是因为经常访问不了,也就是说,不想通过代理才能访问,所以,我需要使用代理的相关命令。因为caddy是https协议,所以我export一个变量https_proxy来作为代理。

- 阅读剩余部分 -

网站讲究高可用,讲究不间断服务。而对于刚接触caddy的我们而言,修改配置文件是加家常便饭,比如:增加日志监控,增加一个301重定向什么的。那么修改了配置文件,配置文件是否配置正确呢?配置后又该怎么重启呢?如何确保重启过程的不间断服务呢?如果出现服务挂掉该怎么确保服务的自动启动呢?这一系列的疑问,我们今天来一一释怀吧。但是,需要相信的是,caddy作为一个新生代的web服务器软件,这些方面肯定会考虑到的。本文将参考官方的命令行模式文档,为这些问题一一解答。

ps.关于Caddy的命令行参数,也可以参考我翻译的中文文档:Caddy命令行参数

如何检查配置文件正确性

caddy指定配置文件的参数是-conf,那么怎么验证配置文件是否正确呢?就像nginx的-t参数一样,caddy有-validate参数可供使用。看一下官方文档:

-validate
Parse the Caddyfile and exit. If syntactically valid, a message will be printed to stdout and the process log (if any) and will exit with status 0. If not, an error will be returned with a non-zero exit status.

解析Caddyfile并退出,如果句法结构正确,将会通过标准输出打印一条信息,记录日志(如果配置了),最后会退出,退出码为0。否则,会报出相应的错误信息,状态码为非0。

- 阅读剩余部分 -

网站改版后,很难确保新的网址和旧的网址保持一致,因此总需要写一些重定向规则,确保原来被搜索引擎抓取的页面能重定向到新的URL。对于一个基于typeocho的php类型的网站,重写也总是必要的。在使用nginx服务器的时候,重写和重定向是在一起的,并没有什么歧义产生,但是,到caddy里边,这两个概念是区分开的。更为不好的地方在于,两者并存的时候,会出现意想不到的结果。

比如,最早本站发现有一些老页面的流量过来,但是会进到404页面。

5 203.208.60.50 - - [26/Aug/2018:20:53:44 +0800] "GET /article/223672015323021312 HTTP/1.1" 404 2057 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"

按照官方说明,在Caddyfile中使用__redir__命令予以重定向。

    redir 301 {
    /article/223672015323021312 /article/2017/06/php-git-http-server.html
    /article/2017/06/5.html     /article/2017/06/php-git-http-server.html
}

rewrite {
    to {path} {path}/ /    
}</code></pre><p>重启caddy,但是发现并没有生效,还是和之前效果一样。</p><!--more--><p>检查配置文件,发现应该是因为里边存在__<a href="https://dengxiaolong.com/caddy/cn-doc/http.rewrite.html" title="rewrite">rewrite</a>__指令,而caddy并没有处理两者之间的优先级导致的。<a href="https://www.bing.com/" title="bing">bing</a>搜索一下,发现果然有这方面的讨论。</p><p><a href="https://github.com/mholt/caddy/issues/1107">https://github.com/mholt/caddy/issues/1107</a></p><p>其中,hlidotbe提到:</p><blockquote>Looking a bit further, I see why it happens. in caddyhttp/httpserver/plugin.go "redir" is after "header", way after "rewrite".</blockquote><p>主要说的是<code>redir</code>是在在<code>rewrite</code>后面执行的,也就是说,先执行了rewrite逻辑,然后再执行redir逻辑。</p><p>查看<a href="https://github.com/mholt/caddy/blob/master/caddyhttp/httpserver/plugin.go">源代码</a>,果然如此:</p><pre><code class="lang-go">// directives is the list of all directives known to exist for the

// http server type, including non-standard (3rd-party) directives.
// The ordering of this list is important.
var directives = []string{

// primitive actions that set up the fundamental vitals of each config
&quot;root&quot;,
&quot;index&quot;,
&quot;bind&quot;,
&quot;limits&quot;,
&quot;timeouts&quot;,
&quot;tls&quot;,

// services/utilities, or other directives that don&#039;t necessarily inject handlers
&quot;startup&quot;,  // TODO: Deprecate this directive
&quot;shutdown&quot;, // TODO: Deprecate this directive
&quot;on&quot;,
&quot;supervisor&quot;, // github.com/lucaslorentz/caddy-supervisor
&quot;request_id&quot;,
&quot;realip&quot;, // github.com/captncraig/caddy-realip
&quot;git&quot;,    // github.com/abiosoft/caddy-git

// directives that add listener middleware to the stack
&quot;proxyprotocol&quot;, // github.com/mastercactapus/caddy-proxyprotocol

// directives that add middleware to the stack
&quot;locale&quot;, // github.com/simia-tech/caddy-locale
&quot;log&quot;,
&quot;cache&quot;, // github.com/nicolasazrak/caddy-cache
&quot;rewrite&quot;,
&quot;ext&quot;,
&quot;minify&quot;, // github.com/hacdias/caddy-minify
&quot;gzip&quot;,
&quot;header&quot;,
&quot;geoip&quot;, // github.com/kodnaplakal/caddy-geoip
&quot;errors&quot;,
&quot;authz&quot;,        // github.com/casbin/caddy-authz
&quot;filter&quot;,       // github.com/echocat/caddy-filter
&quot;ipfilter&quot;,     // github.com/pyed/ipfilter
&quot;ratelimit&quot;,    // github.com/xuqingfeng/caddy-rate-limit
&quot;expires&quot;,      // github.com/epicagency/caddy-expires
&quot;forwardproxy&quot;, // github.com/caddyserver/forwardproxy
&quot;basicauth&quot;,
&quot;redir&quot;,
&quot;status&quot;,</code></pre><p><a href="https://github.com/hlidotbe">hlidotbe</a> 还提到</p><blockquote><p>I think there's really only two (and a half) options:</p><p>1 merge redir and rewrite as most/all web servers do which makes the problem disappear and remove all ambiguity about it;<br>2 order rewrite after redir which may break some use cases but should limit surprises for most;<br>2.5 allow rewrite to redirect too but that would render redir redundant and often unused when rewrites are involved;</p></blockquote><p>简单翻译一下:<br>我认为最后解决方式只有2.5个选项:<br>1 像大多数web服务器软件一样(如nginx),合并<code>redir</code>和<code>rewrite</code>两个指令,让分歧彻底消失;<br>2 使<code>rewrite</code>指令在<code>redir</code>指定后面执行,这虽然会影响部分使用场景(有时候可能想重写后还能重定向),但会解决绝大部分疑惑;<br>2.5 允许<code>rewrite</code>指令支持重定向,不过这样就会让<code>redir</code>显得多余了。</p><p>既然,问题出现了,而且也没有解决方案,我们只能自己绕路而行了。<br>思路就是:</p><ul><li>rewrite命令想办法让需要redir的路径不重写;</li><li>其他一切不变</li></ul><p>最后,来看一下改进的Caddyfile文件:</p><pre><code class="lang-caddy">    # 先让rewrite过滤掉需要redir的路径
rewrite {
    if {path} not /article/223672015323021312
    if {path} not /article/2017/06/5.html
    to {path} {path}/ /    
}

# 先执行rewrite,再执行redir
redir 301 {
    /article/223672015323021312 /article/2017/06/php-git-http-server.html
    /article/2017/06/5.html     /article/2017/06/php-git-http-server.html
}</code></pre><p>经过这样调整,caddy终于能正常相应redir的请求了。虽然这样来看,比nginx的<code>rewrite</code>配置要复杂不少,但其他地方的配置,尤其是https的配置,实在是要高明得多。对于普通的blog来说,caddy还是显得要便捷得多。</p>

- 阅读剩余部分 -