月度归档: 2018 年 4 月

  • 根据Commit ID自动触发Docker Hub的构建

    根据Commit ID自动触发Docker Hub的构建

    有时候自己的Docker镜像需要上传到Docker Hub上,为了保证镜像的更新,我们需要出发Docker Hub的构建。具体操作有以下几种:

    1. 从Travis CI(或者其他CI)来触发,每次提交自动构建新的镜像到Docker Hub
    2. 从其他镜像触发,比如你的镜像依赖了tomcat,那么就可以在Docker Hub中配置tomcat镜像一更新,你自己就更新
    3. 通过Docker Hub手动触发

    这三个方法看起来第一个最好,但是有个先决条件,项目库或者说CI权限在自己手动。如果你的镜像编译了第三方的repo,那其实你没有办法配置webhook这一类的通知来触发构建。

    因为最近在用阿里云函数计算,所以想到一个取巧的方法,通过commit id来判断是否为最新构建,大致思路如下:

    1. 在Dockerfile中输出commit id
    2. 通过Github API获取目标项目的最新commit id
    3. 通过Docker Hub API获取最新构建的日志
    4. 对比日志,如果commit id一样,就说明构建是最新的
    5. 如果不一样,就调用Docker Hub API触发新的构建

    在Dockerfile中添加:

    RUN git rev-parse HEAD

    然后构建日志中就有commit id信息了

    触发构建用的Docker Hub API地址可以在Build Settings中找到

  • 使用阿里云函数计算自动同步fork repo

    使用阿里云函数计算自动同步fork repo

    在参与一些开源项目的时候,因为工作流的原因,经常需要从upstream的repo同步改动到自己fork的repo中。一般来说可以使用git命令来完成,大致步骤如下:

    1. git remote add upstream …
    2. git fetch upstream
    3. git pull master
    4. git rebase upstream/master
    5. git push

    操作到算不上繁琐,我是本地写了一个shell,自己手动运行。

    但是有时候工作在多个repo上,可能会忘记更新,特别是有一些项目活跃度很高,要是一两天没有同步,开工的pull request可能就要花大量时间去解决冲突。对于团队项目,那还需要大家轮流负责同步的事情,虽然网上有很多服务可以做到自动同步,但是一般都要求上游项目仓库接入,如果自己只是项目的贡献者,还是比较难去操作的。

    最近发现Github的API支持Patch方法,可以做到一个api调用就完成上面的几个git命令,同时流量消耗很小(发送一个json body就行了),这样就可以放到阿里云函数计算上,通过定时触发来自动化这个问题。

    为了简单起见,还是使用nodejs 8的环境,依赖库使用async和request。

    我们以dubbo为例,首先需要获取上游项目的最新commit sha。调用地址:https://api.github.com/repos/apache/incubator-dubbo/branches/master

    然后下一步发送一个PATCH请求到自己fork的库中,以我自己的repo为例,请求地址:

    https://api.github.com/repos/htynkn/dubbo/git/refs/heads/master

    发送的body中包含两个字段,一个是上一步获得的sha,一个是是否强制更新的标识符。

    {
     "sha": sha,
     "force": false
    }

    步骤就这两步,其次就是需要一个token,可以自己在Github配置汇总生成,只需要repo权限就行了。

    完整代码如下:

    var request = 
  • Docker多步构建生成dubbo-admin镜像

    Docker多步构建生成dubbo-admin镜像

    Docker是支持多步构建的,对于需要编译源代码的那种构建,多步构建一方面可以获得更小的镜像,另外一方面也不需要手动清理源代码和别的文件了。

    有时候本地调试的时候需要起一个dubbo-admin看一下,但是每次都是启动一个tomcat,然后拷贝war,久了也有点麻烦。想从Docker镜像启动一个,但是官方没有提供。网上有不少个人构建的镜像,但是版本有些旧了。索性自己搞一下放在Docker hub。

    手动操作比较直接,克隆代码库,然后maven打包出war包,放tomcat运行即可。多步构建的Dockerfile如下:

    FROM maven:3-jdk-8
    RUN git clone --depth 1 https://github.com/apache/incubator-dubbo-ops.git /source
    WORKDIR /source
    RUN mvn package -f dubbo-admin
    
    
    FROM tomcat:8.0-jre8
    RUN rm -rf /usr/local/tomcat/webapps/
    COPY --from=0 /source/dubbo-admin/target/*.war /usr/local/tomcat/webapps/ROOT.war
    EXPOSE 8080

    运行的时候提供一下注册中心的环境变量(dubbo.registry.address)即可。

    如果是docker-compose,简单的例子写法如下:

    version: '3'
    
    services:
      zookeeper:
        image: zookeeper
      
  • 关于Dubbo

    最近在做Dubbo,发现之前对Dubbo的理解有点误区。之前一直觉得Dubbo只是一套RPC框架,并没有一些云上微服务的那套(Netflix开源的那套)。最近仔细看了一下,发现其实每个方面都有涉及。

    1.集群容错

    Dubbo的集群容错是在dubbo-cluster模块中(https://github.com/apache/incubator-dubbo/tree/master/dubbo-cluster)。实现是在RPC层,当调用完成后会根据配置做出处理。有以下几种:
    1)失败自动切换,当出现失败,重试其它服务器。这个是默认策略
    2)快速失败,只发起一次调用,失败立即报错
    3)失败安全,出现异常时,直接忽略
    4)失败自动恢复,后台记录失败请求,定时重发
    5)并行调用多个服务器,只要一个成功即返回
    6)广播调用所有提供者,逐个调用,任意一台报错则报错
    这个和Hystrix是不一样的,Dubbo只是提供了容错,但是没有熔断。如果需要熔断,需要自己在消费者一端实现对应逻辑,和Dubbo框架无关。

    2.负载均衡

    Dubbo是支持负载均衡的,实现同样在 dubbo-cluster模块中(https://github.com/apache/incubator-dubbo/tree/master/dubbo-cluster)。也是在RPC层,具体的调用发生前完成。负载均衡的策略有以下几种:
    1)随机。这个是默认策略
    2)轮循
    3)最少活跃调用数
    这个和ribbon有点像,但是只提供了本地负载均衡,策略比ribbon少,不包含ribbon的缓存和拦截器特性。

    3.版本兼容

    如果出现不兼容升级时,可以用版本号特性过渡,
  • 阿里云的函数计算

    阿里云的函数计算

    之前用过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