golang的mutex的误用(defer)

前两天,我的一个golang程序突然出现异常,因为从ramq中读取数据并且自动ack, 然后另外一个线程再读取出来。 中间使用了mutex来防止冲突,结果发现突然不知道什么原因,这个数据竟然没有读到了。

后来分析应该是mutex的原因,然后做了个小测试,就简单的在使用mutex.Lock的后面直接defer mutex.Unlock, 本意很简单,在变量的生命周期结束后直接Unlock,结果发现竟然只会lock,不会unlock。将mutex.Unlock替换为 一个输出函数,结果发现也不会。仔细看了下defer的用法,结果发现defer是在函数结束之前调用的。最后把lock和 unlock以及中间的代码封装为一个内部函数,再次调用就正常了。

R910 风扇控制

上周公司这边弄了台2手的R910服务器,一启动那个噪音实在受不了。即使到最后,默认的噪音也还是受不了。

最后只能尝试将其风扇改为手动模式。

需要注意的是:

  1. iDRAC的网口是第一个网口,我习惯哪个近用哪个,所以用了第4个网口作为网络连接,最后又接了根网线到第一个网口上
  2. iDARC如果设置为DHCP自动获取的话,在网口1上会被分配两个IP地址,一个是iDRAC的地址,一个是系统的地址,控制的时候,需要使用iDARC的地址,不过,这两个地址在同一个网段下,可以互相通讯的。
  3. iDARC通了后,可以通过IP访问web页面,还有一堆内容可以配置或者查看的。
  4. 上面的是自动控制的前提条件,我是通过判断CPU内核的平均温度来调节风扇的。如果高于50度,则恢复成自动的,如果低于50度,则变为手动的。通过cron 5分钟检测一次。

脚本内容:

#!/bin/bash
set -x
CUR_CPU_TEMP=`sensors | grep "Core" | awk -F '+' '{print $2}' | awk -F '°C' '{sum +=$1} END {print sum/NR}'`

CMD="ipmitool -I lanplus -H 192.168.2.166 -U root -P calvin raw "

echo `date` "CUR_CPU_TEMP="$CUR_CPU_TEMP

if [ ${CUR_CPU_TEMP%.*} -gt 50 ]
  then
    echo "--> enable dynamic fan control"
    $CMD 0x30 0x30 0x01 0x01
  else
    echo "--> disable dynamic fan control"
    $CMD 0x30 0x30 0x01 0x00
    echo "--> set static fan speed 30%"
    $CMD 0x30 0x30 0x02 0xff 0x1e
fi

javascript的Function函数

我在使用element-ui的table的控件的时候,对其中的template很好奇,使用slot-scope字段可以透传 当前row的相关信息,在react.js做列表控件的时候,就想着也实现一个类似的。

我没有仔细研究element-ui的代码是如何实现的,不过 javascript有一个Function函数,正好也在 做这个相关的功能,所以就用这个函数弄了一个类似的。

function rend_scope(t, key, slot) {
    if(!t.props['slot-scope']) {
        return (<Fragment key={key}>{React.createElement(
            t.type,
            t.props,
        )}</Fragment>);
    }
    let scope = t.props['slot-scope'];
    if(!scope.startsWith('{')) {
        let newprops = {...t.props};
        newprops[scope] = slot;
        return (<Fragment key={index2}>{React.createElement(
            t.type,
            newprops,
        )}</Fragment>);
    } else {
        let result = null;
        let looseJsonParse = (obj)=>{
            return Function('"use strict";return (' + obj + ')')()(slot);
        };
        let s = `function(${scope}=slot){return ${scope};}`;
        result = looseJsonParse(s);
        return (<Fragment key={index2}>{React.createElement(
            t.type,
            {...t.props, ...result},
        )}</Fragment>);
    }
};

上面的代码首先判断是否存在slot-scope, 不存在的话,则动态创建。

如果存在的话,则判断是否是'{‘开头的,如果不是,则是将slot的作为props指定字段的值插入,然后动态创建。

如果是'{‘开头的话,表示要提取slot中的某部分字段的内容,这些字段作为props中指定的字段和值插入,然后动态创建。 这里使用了Function的功能,首先将slot-scope中的字符串拼接为一个简单的字段提取的函数, 上面变量s中字符串 函数的功能就是提取object中指定字段的功能,虽然通过分割slot-scope中的字符串,然后对object通过 数组方式读取也可以,我还是喜欢通过Function的功能,这样如果某个字段填写有问题的话,执行到会直接报错的,报错后 位置也好找。looseJsonParse里面的功能就是生成新的js的函数并且执行,因为动态生成函数后,执行的参数是slot, 而之前s的函数就变成了是返回slot中某些字段的内容并组成新的object了,最后将这部分和老的props合并并动态生成。

第2部分的判断如果用第3部分来做的话,则是将slot的整体与老的props合并,与我想要的结果并不同。

ubuntu 20.04 添加桥接网络

之前的版本添加桥接比较麻烦,网络还经常会被断开。20.04的版本有一种简单的方法添加网络。 在/etc/netplan目录中添加配置文件,重启后就自动添加好了。 比如

# This is the network config written by 'subiquity'
network:
  renderer: networkd
  ethernets:
    enp2s0:  #物理网卡的接口
      dhcp4: no  #桥接网络自动获取ip地址了,所以这个可以为NO,这样桥接的br0可以使用原来的物理网卡的接口的ip地址
  version: 2
  bridges:
    br0: #虚拟桥接网络的接口
      dhcp4: yes
      interfaces:
        - enp2s0 #桥接到的物理网卡的接口

上面的配置是动态IP的,我喜欢在路由上绑定mac地址的方式配置ip

golang vs rust vs javascript

最近研究了几天rust,并不是特别的深入,主要用来做wasm。 之前的部分关键程序使用golang写的,但不是wasm,也简单封装了接口, 试了下wasm。

就体验而言,rust的学习曲线实在太抖,相比之前的golang学习,golang用个个把小时看下语法,结构,项目组织方式,然后就可以做 项目了。rust看了几天,貌似还在门外徘徊,不过没关系,经过几天的摸索,我终于学会了使用rust来编写wasm,并且和elementui的 框架的配合调整为我想要的了。而这个只是灾难的开始。

我想试着用rust,一个主要原因是golang生成的wasm实在太大,什么都不做的2MB+了。另外一个最重要的原因是golang生成的wasm, 在解析一个很大的json字符串的时候,竟然需要13+秒的时间,如果使用第三方的json解析的话,需要1+秒的时间,虽然可以使用tinygo 来减少wasm的容量,但tinygo无法使用第三方的json解析。而在查看wasm相关信息的时候,rust据说不错。所以就决定写个试试了。

下面的坑都是根据回忆记录的。不一定是对的,所有执行的目标都是wasm

  1. rust的json解析,如果不使用js_sys的json解析的话,需要很长的时间,没记错的话,需要很久,至少10s+是有的。这个json数据大约在几十MB之间。 如果使用js_sys的话,需要0.8秒左右的时间。之所以提出来是因为太明显了。最后逼迫我必须使用js_sys的解析。缺点就是描写的各种累心
  2. 因为1解析出来的json数据会被各个不同的部分使用,因此这个变量要被全局存储。全局存储大概搞了我好多天,因为没有最理想的。 刚开始准备一个最简单的Option的方案,不支持指针类的; 升级为lazy_static方案, 不支持js_sys::JsValue,JsonValue太慢 放弃; thread_local方案,这个需要使用with,这个是我目前可以找到的可以支持js_sys::JsValue的了,也只能这样用了,使用with, 丑就丑吧
  3. 因为2使用了with方案,而代码中的数据在处理的时候,会从其他地方得到的数据进行整合,比如我又从其他的公共变量获取数据,而 with的处理结果,除非使用clone的方式,否则由于变量生命期的关系,各种编译报错,我真的恨死rust的这种反人类的设计了。 明明我只是为了读取内部的一段内存的数据,结果非的逼我clone出一段内存来,感情现在内存真的都是白菜价啊
  4. 很无奈,其他部分(我只测试了一个,以后的以后想办法对付吧),我使用了lazy_static方案,我试了下Mutex,结果在浏览器里 一跑,发现浏览器cpu 100%卡住了,等好久才有反映,这下好了,整个数据不用处理了。既然Mutex不行,就试试RwLock,反正我 数据仍到HashMap中,更新少,查询多,但要返回相应的数据,还得clone,于是又回到3了。
  5. 我无数次准备掐死自己的心都有了,让你犯贱选rust,你看使用golang多少,一周的rust研究成功,golang两个小时就达到相同效果了。 但golang真的慢啊
  6. rust的设计初衷或许非常完美,但智能指针的设计模式或者所有权的设计,真的是非人类。即使是学院的erlang,也没有rust这么变态, 我感觉我好久都没关注过erlang了,真有点怀念熟悉了之后处理代码的那种感觉。