年度归档: 2021 年

  • Rust工程的分发

    Rust项目直接用Cargo build就可以产出构建物,但是这个构建物不一定真能在部署端运行起来,常见问题有以下几个。

    Glibc版本

    一般我们的构建都是放linux平台的,Glibc是GUN发布的c库,真正的底层依赖。Rust在编译的时候绝大部分都是静态链接,但是对于C标准库,它使用的还是动态链接。Glibc广泛存在,本来也不是啥大问题,但是如果构建的时候使用了相对新的版本,而运行环境是在其他使用低版本Glibc的系统,那么就会有 version `GLIBC_2.18′ not found 这种问题。

    解决方案有很多种,最简单的就是换一个libc的实现,musl是一个相对合理的选择。只要在构建的时候选择x86_64-unknown-linux-musl就行了。

    cargo build --target x86_64-unknown-linux-musl

    构建环境还需要musl-tools环境。

    如果由于一些特殊原因没法用musl,还可以考虑降级Glibc。比如使用低版本的Ubuntu进行构建,也可以使用cross工具。

    外部文件

    如果追求单文件,那么各种配置文件和其他文件依赖就是一个问题。最直接的方法是使用include_str直接把内容放在构建物中,sqlx::migrate就是用的这种方法。如果是其他文件,也可以自己实现,或者使用第三方的库,比如rust-embed等。

    Docker镜像

    Docker镜像更多的问题是在大小上,一般来说采用多步构建就行了。构建镜像可以用rust镜像,运行环境用debian:buster-slim。如果有其他依赖,比如openssl、sqlite也可以自行安装。…

  • 部署Rust工程到阿里云函数计算FC

    本文首发于阿里云开发者社区:https://developer.aliyun.com/article/797279

    阿里云函数计算目前支持C#、Java、Python、Go等大部分语言,对于一些定时任务是非常适合的。最近有一些工程使用Rust重写了也想部署到阿里云函数计算上,这里来看可以使用Custom Runtime/Container。

    Custom Runtime/Container模式

    这个模式本质上是自定义脚本启动一个http服务,然后Serverless平台转发请求到你的http服务,这个请求header中有一些特殊信息,极端的将不考虑启动速度和性能等等,其实是可以无障碍迁移大部分服务的(存储和数据库可能需要改造)。

    这个运行环境默认包含了Python3,Java 8等常见依赖,对于Rust这种编译成二进制文件的就更简单了。最终产物是一个zip包,包含启动文件bootstrap和其他依赖即可。

    Custom Container模式可以理解成增强模式,如果Custom Runtime不可用,一般是由于特殊的本地依赖导致,Custom Container模式的产出是一个镜像,不过由于镜像的大小比代码包大,所以计费上要多一些,包含拉取镜像的费用。所以这两者需要根据情况来决策,尽可能使用Runtime模式。这样费用和速度上都好一些。

    代码改造

    这里使用的是funcraft工具专门用于部署,template.yml文件包含描述信息,代码放在code目录。

    在Cargo.toml中新增两个依赖

    tokio = { version = "1.12.0", features = ["full"] }
    warp = "0.3.0"

    修改main.rs用warp启动一个http服务

    #[tokio::main]
    async fn main() {
        pretty_env_logger::init();
        // POST /invoke
        let 
  • 移除Rust标准库依赖

    现代通用操作系统对于应用程序的支持很多,在硬件平台上操作系统做了管理,操作系统之上还有标准库对应用程序提供系统调用。然后如果只从跑起来的角度来说,只要有最上面和最下面的就行了。

    如下图:

    中间两层提供的都是抽象。而有些时候我们的应用程序需要运行在一个相对底层的情况下,我们就需要移除标准库的依赖,更进一步可能要减少对于部分操作系统的依赖。

    nothing程序

    如果编译一个空的rust程序,比如nothing.rs

    fn main(){}

    在Ubuntu下查看系统调用如下图

    我这里的芯片是riscv的,所以第一步是新增.cargo/config文件

    [build]
    target = "riscv64gc-unknown-none-elf"

    在代码头部取消标准库

    这里编译会失败,因为println!也是std提供的,而core中没有。

    移除后编译也是失败

    panic_handler是致命错误处理函数,默认也是std提供,这里我们加一个空实现

    由于我们的main函数在被调用前,其实有很多初始化工作被做了,现在移除了std也没有了。直接删除main方法,然后加上no_main配置就行了。现在编译可以通过。

    查看产出物的信息,可以看到入口是0,这个产出物本质上是没有用处的。还需要补充上后面需要的内容。

    这里需要加上_start函数

    #[no_mangle]
    extern "C" fn _start() {
        loop{};
    }
  • Flutter和Rust混合编程

    Rust语言本身就是跨平台的,加上很多性能上的优势,很多代码可以在一定程度上复用。

    Flutter的FFI支持可以让我们调用本地代码,也就是可以做到Flutter和Rust混合编程。

    Rust改造

    为了减少改动,我一般会引入一个新的项目,直接在原项目名基础上加上ffi。

    这个项目的主要用途在于定义对外暴露的接口,并在构建时输出so等文件。

    在Cargo.toml中新增两个依赖

    [dependencies]
    rust-project = { path = "../rust-project" }
    
    [build-dependencies]
    cbindgen = "0.14.3"
    dart-bindgen = "0.1.7"

    其中cbindgen帮助我们从Rust代码生成C/C++的头文件,dart-bindgen(现在用ffigen了)帮助我们从头文件生成dart绑定。

    Flutter插件

    有了上一步的so和dart文件后我们就可以调用了,但是出于隔离和复用的考虑,这里不直接在Flutter项目中使用,而是先包装成Plugin。

    按照设计,Flutter插件可以用于封装与平台专用代码进行的通信,由于上一步已经生成了绑定,所以这里只做最基础的封装和注册。

    import 'ffi.dart' as ffi;
    
    class Plugin {
      int functionName(int a, int b) {
        
  • 自定义Jellyfin插件

    最近把多媒体管理软件从Plex切换到Jellyfin了,之前用的ttm搜刮器做的整理,最近由于Nas没有放在住的房屋,远程管理比较麻烦,所以又把目光放回Jellyfin的插件上。

    由于动漫都是走Sonarr下载的,把rename打开以后识别上就没啥大问题了。官方自带了themoviedb的插件,但是一是不支持代理,二是包含了很多YouTube的信息,这个确实不必要。所以自己参考写了一个插件,主要是支持Proxy方便访问themoviedb,二是移除了一些不需要的信息。

    插件编写

    插件的编写使用C#,主要就是实现对应的接口,主要是IRemoteMetadataProvider和IRemoteImageProvider。一个负责源数据,一个负责图片。

    我一般是用TV和Movie两种,其中TV的集数识别可以依赖Jellyfin,当然如果有需要也可以自己实现从文件名分析。

    插件测试

    插件的测试自然可以用单元测试,但是由于一般来说插件主要做的是把信息转为Jellfyin的对象,没有太多复杂逻辑。直接打包放到Jellfyin中使用就行了。

    在本地为了方便,我一般用docker-compose来启动。

    version: "3"
    
    services:
      jellyfin:
        image: jellyfin/jellyfin:latest
        volumes:
          - config:/config:z
          - ./videos:/media/videos
          - ./Jellyfin.Plugin.HappyMovie/bin/Debug/net5.0/Jellyfin.Plugin.HappyMovie.dll:/config/plugins/HappyMovie/Jellyfin.Plugin.HappyMovie.dll:ro
          - ~/.nuget/packages/yove.proxy/1.1.1/lib/netstandard2.0/Yove.Proxy.dll:/config/plugins/HappyMovie/Yove.Proxy.dll:ro
        ports:
          - 127.0.0.1:8896:8096
    
    volumes:
      config:

    dll文件路径根据自己的项目实际情况修改即可。这里也要包括外部依赖。比如我这里使用了代理配置,所以依赖了YoveProxy库。

    插件发布安装

    插件直接分发DLL即可完成安装。为了更好的方便普通用户使用,也可以提供一个manifest.json文件。

    这个文件的具体格式可以参考:https://raw.githubusercontent.com/htynkn/HappyMovie/master/manifest.json

    也有现成的python脚本可以生成。最关键是把DLL文件打包到zip中。…

  • 交叉编译给铁威马Nas添加wget

    铁威马Nas自带的系统不知道魔改的啥,很多基本工具都没有,比如wget。有时候需要从外边安装点啥,特别是下载脚本特别难。

    铁威马Nas就分两个架构的,x86和arm v8。我手上的都是x86的,官方提供了编译工具链,但是我自己的经验来看,目前还没有遇到不兼容的地方,直接用公开工具就行了。比如rust的x86工具链,或者cross的docker image也行。

    这里以wget为例,使用docker image来。

    首先下载源代码https://ftp.gnu.org/gnu/wget/wget-1.21.1.tar.gz,解压后执行docker命令进入容器。

    docker run -it -v $(pwd):/data rustembedded/cross:x86_64-unknown-linux-gnu-0.2.1 bash

    wget的编译方法看文档就行了,先configure,再make,然后我们也不用install,直接拷贝到Nas的/bin目录即可。

    ./configure --prefix=/usr      \
                --sysconfdir=/etc  \
                --with-ssl=openssl
    make
  • 学术共同体应该做什么

    共同体这个词最早追溯到15世纪,普遍来看是指在某些方面具有共同利益者组成的群体。最多见的是经济共同体,比如欧洲经济共同体、东南亚经济共同体等。当然,一般意义的帮派、黑社会也属于共同体的一种,只不过一般称为“帮“。

    共同体的关键是利益,当然学术共同体也是一样的。只不过这里的利益更多是学术上的,而不是经济利益。学术共同体中较为知名的(规模较大的)有英国皇家学会、美国计算机学会等,当然中国计算机学会(CCF)在脱离挂靠以后也渐渐展露出学术共同体的面貌。

    学术共同体有很多活动,比较常见的有四类:

    • 告知行业自身的发展发向和需要攻克的难题
    • 维护学术规范,对于抄袭、作假等恶劣行为做出监督和谴责
    • 对政府的学术/科技决策提出建议和意见
    • 对公众的科普,特别是针对青少年的,提供公众的科学素养,培养潜在人才

    那么从这个角度看CCF各方面都是做的不错的,当然其中也有一些不足,我个人体会在于第二点上缺乏对于学术不端的监督和谴责不足,目前学会的发声主要在于国际合作和国际制裁上。其次是科普上,学会的CSP认证、全国青少年信息学奥林匹克竞赛、校企合作等相对不错,但是毕竟辐射面不多,对于青少年启蒙方面怎么加强也许是未来工作的方向。

  • 云原生与Apache Dubbo 3.0

    如果需要下载,可以访问:https://089u.com/f/631225-496536778-45eb62(访问密码:7269)…

  • Switch Lan Play Openwrt版本常见问题排查

    如果需要在自己的Openwrt上安装lanplay插件,可以直接从:https://htynkn.github.io/openwrt-switch-lan-play/openwrt/ 下载对应的包。总共有两个ipk文件。

    常见问题排查

    • 确认自己下载的插件是否和自己硬件架构一致,不同的包是没法使用的。
    • 确认自己是否为标准Openwrt,版本是否为19.07.7?
    • 右上角是否有未提交提醒,如果有请先提交
  • 零信任PPT

    需要下载,可以访问

    零信任-让安全超越边界.pdf: https://089u.com/f/631225-496523607-bafd55 (访问密码:7269)…