nginx多进程间的负载均衡

nginx是如何把任务分配到每个worker的呢?这种分配平均吗?合理吗?

通过strace  一个worker进程,部分逻辑如下:

我们发现,accept4是放在epoll_wait后面的,不难推测:

  1. nginx的epoll_wait 是在看那个文件描述符有事件发生了(就是需要处理了),当然,这里不包含listen的那个文件描述符(不是不能,是不应该);如果有事件发生,则处理,这些都是已经接收了的连接,有可能是(已建立的连接上的)新的请求。如果没有事件发生,则调用accept4看看有没有新的连接进来。这个逻辑就保证了,如果我比较闲,那么我就接活儿,如果我没闲着,我就不接活儿了

golang的chan阻塞与deadlock

示例:

如上程序:

如果没有第二个go协程,那么第一个协程是消费者,main协程是生产者,消费者死去后,就会出现deadlock错误; 原以为是runtime检测到我们在写一个没人消费的chan感到奇怪而报错,实际上不是的,甚至也不是写不进去而报错,而是,没有一个协程是能被执行的了(就好比陈佩斯的小偷中说的那样,这大半夜的也每个车让我指挥指挥),所以,runtime才感觉很迷茫,就报了个deadlock; 如果有第二个协程在的话,runtime会很高兴地去执行第二个协程的,真的不在意那个chan是否有人消费的。

hive transform

总是需要写一些transform放在hive上也挺麻烦,尤其这个transform还需要复杂的配置文件或者是访问IP首先等情况,还不见得能跑通,于是,我就发明了一个万能的transform:

只需要在自己喜欢的机器上执行命令行程序就行,使用nc来做这个万能的transform,然而,自己的程序总是需要listen一个端口是不是也很麻烦,其实不难:

办法1:

使用 nc -l 10.210.227.25 1234 -e “your-command”

办法2: 如果你的nc版本太低,还不支持-e

把这个编译一下,类似于nc的作用

 

注意:

使用transform时要注意:

虽然这了有limit 10 ,你的transform干的可能不是10个的活儿,哪怕这个table只有一个file,可能和执行这个任务用到的机器数量有关;从这个角度来看,hive还不够聪明;

可能需要自己优化一下:

 

transform 只能靠进程数量提高效率,没法在进程内并发?这个不担心乱序?

可以设置reducer的数量来限制并发。

transform的输出格式:

If there is no AS clause after USING my_script, Hive assumes that the output of the script contains 2 parts: key which is before the first tab, and value which is the rest after the first tab. Note that this is different from specifying AS key, value because in that case, value will only contain the portion between the first tab and the second tab if there are multiple tabs.

如果transform子句的using 后面没有as子句:

则输出被视为以第一个tab为分隔的两列,第一列是key,第二列是value;如果输出中没有tab,则整行都是第一列,第二列就是NULL;如果输出中有tab,则第一个tab之前的是第一列,第一个tab以后的都视为第二列

如果transform子句的using 后面有as子句:

则按照tab分隔视为多列

 

参考:

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Transform

 

关于规则引擎

github上有不少关于规则引擎的项目,其中.net java 的比较多,go的就非常少。

 

https://github.com/topics/rules-engine

 

json的:

https://github.com/CacheControl/json-rules-engine

这个只是key   op  value 是否超过定义的规则

 

https://github.com/mithunsatheesh/node-rules

 

c#:

https://github.com/microsoft/RulesEngine

这个是编排工作流的

 

java:

https://github.com/selwynshen/nics-easy-rules

这里的思想可以看看

 

关于json规则引擎

 

这个的特点是,可以直接在规则中定义函数; 这个适用于外包软件中的定制开发

 

bash 中文汉字乱码问题

篇首语

汉字乱码分很多种情况,自从计算机进入中国就从来没有间断过,本次只讨论其中一种情况。

现象:

  1. 终端上可以显示汉字,vim中编辑汉字也没问题
  2. bash中的汉字在移动光标的时候就乱了

分析与解答:

  1. 终端上能显示汉字,说明终端的编码和程序认为的你的终端的编码是一致的;就是说,你的终端设置为utf-8编码时,通常ssh都会把该信息告诉给服务器端的程序(如:bash),通常是不会错的,但是,bash中如果手动export LANG环境变量,且和终端实际设置不一致时,该bash启动的程序(如:vim)得到的LANG信息就是手动export 的LANG,可能和实际终端设置的不一致,这时候,bash启动的那些程序就不能正确处理(输入、输出)汉字了;注意: bash中手动设置的LANG环境变量不管export与否,都不影响bash本身,要想影响到bash也容易,只需要在export之后,再在该bash中执行一个新的bash,这个新的bash就会按照export的LANG来工作了,所以,bash本身处理(输入、输出)汉字并不受当前进程中设置的LANG的影响,只受bash启动时传递给bash的LANG的影响。
  2. 曾经,build容器镜像的时候,直接设置了LANG=zh_CN.UTF-8,于是每次docker exec -it $container-name bash 的时候,bash都是工作在LANG=zh_CN.UTF-8的配置下的,所以,总是不会出现上面讨论的这种问题的。
  3. 偶尔,有一次,使用了一个没有设置LANG=zh_CN.UTF-8 的容器镜像,创建了一个没有明确设置LANG=zh_CN.UTF-8的容器,于是,每次docker exec -it $container-name bash 的时候,bash环境中就只会存在创建容器(镜像)时指定的很少的几个环境变量,docker命令上下文中的LANG 是不会影响 docker exec -it $container-name bash 的。 这种情况可以在docker exec 时指定环境变量,如:
    docker exec -e LANG=zh_CN.UTF-8 -it $container-name bash
  4. 如何查看bash中影响到当前bash进程的那个LANG 呢?
    1. 不是 set
    2. 不是echo $LANG
    3. 而是: cat /proc/$$/environ
  5. 对于bash进程来讲,正确的LANG 和不正确的LANG 在程序逻辑上差别是什么呢?
    1. 这里不直接看代码,让我们通过strace看一下
    2. 比较方法:
      1. strace 一个LANG为空的bash和一个LANG=zh_CN.UTF-8的bash,然后输入汉字
        1. 前者: 逐个字节的read,逐个字节的write;虽然是逐个字节的write,到了终端时,终端也能拼成正确的汉字,所以,表面上工作的似乎是正常的
        2. 后者: 逐个字节的read,多字节的汉字时,是多个字节凑齐后一起write的;(注意:这里存在一点儿问题,如果用户就是随便输入的,根本不可能凑齐一个合法的字符呢?会不会就卡死了呢?
      2. 但是,当我们使用方向键移动光标时:
        1. 前者认为我们好移动的是一个字节,而终端就啥了,总不能把光标放到一个汉字的中间(或三分之一处)吧
        2. 后者则能很好的告诉终端移动多少,于是就不会乱码,而且能很好的处理删除汉字的操作
  6. 虽然解决办法很简单,就是设置LANG, 但是什么时候设置LANG 却很关键。 懂了原理之后,以后再也不怕这种乱码了,以后再也不用总是靠“猜”了