博客

  • 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)…

  • 为Katacoda课程添加自动化测试

    Katacoda是一个很方便做课程的平台,提供免费的机器资源,丰富的环境和UI界面支持。

    Katacoda的课程是由配置+markdown+其他资源组成的,课程写好以后提交到Github就可以自动刷新。一般来说课程内容比较直接,一般写好以后试用一下就可以了,但是结合cypress工具我们也可以做一些简单的自动化测试。

    首先在目录创建文件夹.cypress,然后创建一个以_spec.js结尾的文件,在文件中编写测试接口。另外为了方便起见Katacoda额外提供了一些辅助功能,比如cy.startScenario()可以直接启动课程。

    这里是dubbo-admin的测试例子

    describe("Valid env and layout", () ={
      before(() ={
        cy.startScenario();
      });
    
      it('finds launch command"', () ={
        cy.contains(" launch.sh");
      });
    
      it("start k8s", () ={
        cy.terminalType("launch.sh");
    
        cy.terminalShouldContain("Kubernetes started");
      });
    });

  • Spring Native的使用

    Spring Native的使用

    Spring Native本质上其实是依赖于GraalVM的native image功能,所以要先安装相关依赖。

    安装graalvm

    MacOS的安装依赖brew,官方有一个tap。

    brew install --cask graalvm/tap/graalvm-ce-lts-java11

    安装以后使用gu工具安装native-image工具

    gu install native-image

    SpringNative构建

    首先进行的是AOT插件,插件会根据上下文进行一些优化,主要是为了增强native image的兼容性。

    其次会进行jar包构建,构建后的jar包也是可以在JVM环境下正常运行。

    最后就是build-image这一步,其实启用native与否的关键主要在buildpacks上。首先会自动探测需要应用的buildpacks。如果系统变量BP_NATIVE_IMAGE是true的话就会激活paketo-buildpacks/native-image

    这个插件的native目录包含了对应的GO文件,会调用native-image进行生成操作。生成后会放入image中。

    构建本身还是比较快的。

    出错情况

    最常见的出错就是native-image没有安装或者没有使用graalvm,一般提示native-image找不到。

    目前spring-native要求GraalVM 21.0.0,版本如果低了可能有部分参数不支持,比InlineBeforeAnalysis等。

    可以通过BP_NATIVE_IMAGE_BUILD_ARGUMENTS指定一些特殊参数,常见的如下:

    • –verbose
    • -H:+PrintAnalysisCallTree
    • -H:+TraceClassInitialization
    • -H:+ReportExceptionStackTraces
    • –enable-all-security-services
  • 通过Spring Native构建本地镜像

    Spring Native目前已经在start.spring.io开放使用了。GraalVM在之前已经支持了本地镜像的构建,即不要求JVM安装(不是简单的集成JVM,还有AOT等特性),只生成单一分发文件。现在Spring也可以使用快速使用这个特性了,命令行使用

    mvn spring-boot:build-image

    这个特性比较适合以下场景:

    • Serverless
    • 微服务
    • 分发更高性能和容量的镜像

    参考

    https://www.graalvm.org/reference-manual/native-image/

    https://spring.io/blog/2021/03/11/announcing-spring-native-beta