分类: 默认

  • 阿里云的函数计算

    阿里云的函数计算

    之前用过AWS的Lambda,当时感觉确实很新鲜,能够省一些费用,但是管理上又有一些复杂。

    阿里云现在也提供了类似的功能,叫函数计算,目前价格比较优惠,每个月前100万次调用免费。

    触发器包括对象存储,API网关,日志服务,表格存储,定时触发器等。如果是配合API网关使用的话,每G的费用大概0.72-0.8元之间,总的来说是非常适合一些特定适用场景。

    这里分享一个我自己的个人应用场景。

    用了小米路由器之后经常下载一些电影,但是手机上操作有点复杂,一般是百度搜索一下下载地址,可能是磁力链接,也可能是迅雷下载链接;找到链接以后需要到打开小米路由器的APP,添加下载。我期待的场景是输入关键字,然后返回一个链接,点开直接下载。

    这个场景真的适合函数计算,因为要做的事情无非就是发送请求到电影网站,然后抓取一下链接,然后调用小米远程下载的API生成一个链接。(这个链接在微信中打开会自动连接到小米的小程序)

    函数计算

    阿里云的函数计算提供了java,node和python运行环境。从AWS Lambda的经验中了解到Java启动原因可能不太适合serverless的使用。这次直接用node开工了。

    use strict';
    module.exports.handler = function(event, context, callback) {
        callback(null, 'hello world');
     };

    这个是我们需要实现的函数,event包含了调用器的输入,比如API网关的请求头和传参情况,它的类型是Buffer。一定要注意类型。。。不然要跳进坑里。

    context是函数计算自己的一些信息,比如AK和id什么的。

    callback接受两个参数,第一个是error,第二个是要返回的值。callback是必须调用的,不然就是超时。

    API网关和函数计算

    API网关作为触发器输入的event结构如下

    {
        "path":"api request path",
        "httpMethod":"request method name",
        "headers":{all headers,including system headers},
        "queryParameters":{query parameters},
        "pathParameters":{path 
  • 使用swagger-request-validator验证请求合法性

    使用swagger-request-validator验证请求合法性

    Swagger常常用在API设计上,很多应用框架还可以直接通过代码生成Swagger文件。

    有些时候我们自己可能也是一个服务的消费者,即我们需要发送请求给某个API。

    Swagger docs一般会包含请求的格式和要求,对于一般的GET请求还好,但是对于POST请求,有可能body本身挺复杂的,有时候就需要验证请求的本身是否符合Swagger doc的规定。

    swagger-request-validator是atlassian的一套swagger验证工具。支持Spring MVC等应用框架,当然也可以手动时候。

    首先引入依赖

    <dependency>
        <groupId>com.atlassian.oai</groupId>
        <artifactId>swagger-request-validator-core</artifactId>
        <version>${swagger-request-validator.version}</version>
    </dependency>

    其次通过Swagger定义文件生成验证器。

    final SwaggerRequestResponseValidator validator = SwaggerRequestResponseValidator
            .createFor(swaggerJsonUrl / swagger Json content)
            .withBasePathOverride(basePathOverride)
            .build;
    final ValidationReport report = validator.validate(request, response);

    验证器可以从网址或者定义文件内容直接生成。

    如果只需要验证请求,那么就调用validateRequest。

    这里的Request对象可以通过SimpleRequest.Builder直接构建的。

    参考

    https://bitbucket.org/atlassian/swagger-request-validator…

  • 线稿的自动上色

    线稿的自动上色

    有时候自己画了几张线稿,需要上色一下。

    上色的时候就有一些问题了,一是上色的专业知识欠缺,二是想尝试多种上色风格,费时费力。

    在AI上色领域,其实玩家并不是很多,最开始关注的是Style2paints,代码在Github上有,可以自己搭服务,其在线版本已经挂了一些日子了。其次是paintschainer,这是一个在线版本,可以上色,也可以处理线稿,只是上色风格比较上,更多是实验性质。

    以下是一个例子:

  • Github API和gatekeeper

    Github提供了大量API可供使用,但是大部分时候我们需要的可能只是一个简单的网页(client-side only)的应用,通过js直接调用Github API。

    但是由于安全限制,Github并不允许OAuth认证发生在这种应用上。这个时候我们就需要一个帮助我们去获取token的后端,而gatekeeper就可以完成这个任务。

    一般的验证流程是这样的

    1. 调用Github认证,https://github.com/login/oauth/authorize
    2. 在callback页面获取临时code
    3. 调用gatekeeper去换取可用token

    Gatekeeper是一个node应用,配置信息在config.json中。

    Gatekeeper可以很方便的部署到Heroku或者Azure上,对于一般使用,可以做到免费的。…

  • Serverless服务提供商

    今天去更新了一下serverless的代码,突然发现又多了几个Serverless服务商。

    之前场内的玩家有AWS Lamabda和Azure Function。然后IBM有一个类似的,可以自己托管的OpenWhisk。

    今天新看到了几个小一点的

    https://webtask.io/
    
    https://spotinst.com/
    
    http://kubeless.io/

    前两个都是服务商,第三个比较有意思,是基于Kubernetes的,开源可以自己托管。…

  • 再谈多多猫插件开发

    今天找漫画的时候又想到多多猫了,之前用过一下,当时写插件还是用的记事本在xml中直接编写js,那个体验很差,而且代码测试也很复杂。

    今天又需要插件了,自然想换点花样来做,首先考虑的就是使用构建工具来处理大部分问题。这里用的是Gulp。

    模板替换和文件生成

    我们的目标文件只有一个,那就是index.sited.xml。而这个文件又分了两个部分,首先是xml的声明,包含了一些插件信息,其次是我们的js代码。

    首先做的是将这两者分开,分别创建index.xml和index.js文件。

    <?xml version="1.0" encoding="utf-8"?>
    <sited ver="1" debug="1" engine="32" schema="1">
        <meta guid="<%=app.guid%>">
            <title><%= app.title %></title>
            <intro><%= app.intro %></intro>
            <author><%= app.author %></author>
            <url><%= app.url %></url>
            <encode>utf-8</encode>
            <expr><%= app.expr%></expr>
        </meta>
        <main dtype="1" durl="<%= app.url %>">
            <home>
                <hots cache="1d" title="首页" 
  • 单元测试的纯度和脆弱性风险

    客户公司新来了一个CTO,新官上任三把火,他首先盯上了单元测试,他要求只为单个类编写单元测试。所有依赖项都被模拟,简单而言就是单元测试不跨类。

    然后客户展示了一段代码,表示按照这个规范很难操作,因为现在有需求要业务重构B类。

    class A(val b: B) {
    
       fun doSomething() {
           b.doSomethingElse()
           b.doSomethingElse2()
           b.doSomethingElse3()
       }
    }

    我们来简单分析下这个代码和对应的规范:

    按照规范A类和B类都有自己的单元测试,然后根据新的业务需求,类B进行重构并隐藏在接口后面,因此从技术上讲,类A可能会根据场景获得不同的行为。

    现在的问题是,当我们想要遵循项目的指导方针时,我们还应该重构A的单元测试。之前有一个测试,测试对象是B(当然是被mock的)。现在,当对B的引用消失时,测试将被重构,以验证与这个新接口的调用。

    这种情况是在测试重构过程中发生的信息丢失。当在实际系统中存在此类调用时,由于单元测试的纯度,我们不再验证A->B之间的任何通信。

    我认为这种情况是对于单元测试纯度的过度要求,进而增加了单元测试的脆弱性。

    单元测试的纯度

    周围打听下这种纯度要求其实很常见,特别见于新开始建设单元测试的团队,项目领袖对于单元测试对于质量保障有较高的期望,进而导致对于纯度有近乎象牙塔的规范要求,从而导致建设失败。

    这种纯度的建设方式可以用于项目初期开荒,一锤子买卖,快速搞定上级下发的KPI,但是对于项目质量保障毫无价值。

    对于纯度的争议并不少见,我理解其实更多是对于Unit这个外来词的定义问题,机械的将编程语言的类和方法作为一个Unit就是一个高纯度的要求。

    还有一种原因我认为是对于单元测试本质目标的忽略,进而陷入定义的混乱,然而这不是重要的事情。

    不可否认关于Unit的确切含义存在一些分歧。但是,单元测试测试的目的并不是为了符合某些任意的定义。目的是检测错误。或者更一般地说:验证代码的行为是否符合预期。

    重构时,单元测试应该确保变更没有引入错误或更改行为。因此,测试不应该与测试代码中的实现细节耦合。事实上,应该可以完全重写类的实现,并让测试验证行为是否仍然相同。

    因此,从这个角度来看,测试并不关心被测试类是否调用了其他类。这是一个实现细节。事实上,典型的重构是将方法中的一些内部代码提取到一个单独的类中,而这正是测试应该能够验证重构没有改变行为的场景。

    还有一个更简单的例子,一个验证Email地址的Utils类,它是一个static方法,签名如下

    public static bool isValid(string email)

    高纯度的规范要求mock这个方法,你只需要和任何一个最近三个月写过单元测试的研发工程师聊一聊,他就能告诉这个规范是多么愚蠢。

    因此,底线是:避免mock(除了外部服务或非确定性输入的情况),并让测试联动尽可能多的类来验证行为。

    就我个人而言,我喜欢将“单元”视为“行为单元”——规范中可以独立测试的最小部分。但这只是我的定义。

    Mock对脆弱性的影响

    其实公正的讲,这个例子本身是特殊的,因为这个例子正好证明了一个中间问题。让我们来回想一下常见的改动情况。

    当你做出向后不兼容的改变时,依赖于你所改变的东西就会崩溃。所以,如果你的测试现在报错了,那就太好了——一切都在按预期进行。在这一点上,你有几个选择:…

  • WebJars中依赖的来源

    相比起后端,前端工作的工具生态可以说是相当丰富。如果你工作在一个前后端分离的项目,那么大家各司其职,也没啥问题。

    如果项目是一个混合项目,即前后端在一个代码库中,那么使用WebJars就是一个相当有吸引力的选项。WebJars可以帮助我们管理客户端所需的前端依赖,而且使用的是我们熟悉的JVM-base工具,比如Maven,Gradle或者SBT。

    通过访问http://www.webjars.org/就可以搜索现有的依赖,并使用它们。如果遇到需要的依赖,但是WebJars并不包含的时候我们就需要自己做点工作的。

    总的来说WebJars中依赖的来源总共分三种:

    1. NPM
    2. Bower
    3. Classic

    如果依赖来自于NPM或者Bower,那么直接点击Add WebJars,然后输入名字选择版本就可以了。

    如果不是通过NPM或者Bower,那么就需要手动去创建ticket等待响应了。

    也可以参考贡献指南(http://www.webjars.org/contributing)自己去提交相关的内容物。唯一需要注意的就是路径,内容物的路径应该在META-INF/resources/webjars/

    我个人体验来说WebJars其实和Jitpack很像,都是自动系统,都是为了方便管理。…

  • 阿里云幸运券

    阿里云幸运券

    最近一个同事想买阿里云,可能是新用户的原因吧。。。价格便宜的令人发指。2核4G内存的机器一年才825元。

    恍惚间记得阿里云是有推荐码的,可以九折,找了半天还是没有看到。。。

    结果一番搜索原来改成幸运券,还是可以优惠一点的,有需要的随意取用吧。

    https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=f8r7ewjo&utm_source=f8r7ewjo

  • 使用Docker多阶段构建生成更小的镜像

    使用Docker多阶段构建生成更小的镜像

    在将源码直接打为Docker镜像的时候,经常纠结的一个问题就是如何获得更小的镜像。

    以一个java项目为例,因为java编译的时候需要jdk,而运行的时候只需要jre,明显jre的大小更有优势。同时由于各种构建工具的存在(比如gradle,maven),下载的构建用的文件也很多,不光是maven的依赖,还有wrapper和一些临时文件。

    之前的做法一直是使用两个Dockerfile,其中一个使用jdk构建出需要的jar文件,然后第二个使用jre直接将jar文件复制进去。虽然效果不错,但是还是觉得麻烦。

    今天使用Daocloud的时候看到了安全构建这个选项(本质就是两段构建),就突然想到Docker会不会已经有了。结果一搜索还真有,亏我还用多Dockerfile构建了很长时间。

    大概使用如下:

    FROM openjdk:8 AS build-env
    ADD . /java/src/app
    WORKDIR /java/src/app
    RUN gradlew build
    
    FROM openjdk:jre
    RUN apk add -U tzdata
    RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai  /etc/localtime
    COPY --from=build-env /java/src/app/build/libs/target.jar /usr/local/bin/app-server
    EXPOSE 8080
    CMD ["app-server"]

    Docker支持的是多阶段构建,所以如果有需要的话,可以从多个不同的构建中获得生成物。…