美文网首页
产品整理

产品整理

作者: MR__Fan | 来源:发表于2016-08-22 11:31 被阅读31次

    gr-api系列产品整理

    server api

    • yf-api-server
    • yf-fast-dbm
    • gr-api
    • biz-api ( java )

    sdk

    • js angularjs
    • nodejs
    • java
    • .Net
    • php

    task_trigger

    scheduled task trigger for api

    ci-web

    http web console 4 execute shell command

    总结一些自己完成的提高效率的工具

    1. yfci.sh

    用于在linux系统上快速安装java和node环境的自动化脚本

    • 源码地址: https://github.com/yfsoftcom/mytools
    • 基于centos 6.x的系统环境
    • 自动安装如下软件:git , lsof , node 4.5 , pm2 , cnpm , java1.8 , maven 3.2.x , tomcat 8.x
    • 自动集成ci-web , 通过浏览器访问:http://[yourdomain]:3000 , 可执行系统shell命令,如:
    $ free -m
    
    $ yfci build
    

    YF-CI-WEB

    这是一个可以通过web界面来执行linux shell 的工具

    0.Overview

    自己平时喜欢捣腾玩意儿,弄了个centos主机,学习shell,做了一些脚本,但是执行都要xshell进,好麻烦!
    于是就有了这个小工具,安装在linux上,可以通过web来执行shell指令了。在家也可以编译发布产品代码,开森~
    实际上就是一个nodejs的小应用,通过child_process来执行shell指令。
    凑活着用呗,嘿嘿~
    配合上自己写的一些shell脚本蛮实用的

    奉上源码地址:https://github.com/yfsoftcom/yf-ci-web
    欢迎拍砖

    • PC上界面如下:


      执行 free -m 命令
    • 兼容适配手机哦,不过手机上能显示的空间小,费眼~


      iphone 6 打开 执行 free -m 命令

    1. Install

    $ git clone https://github.com/yfsoftcom/yf-ci-web.git
    
    $ cd yf-ci-web
    
    $ npm install
    

    2. Run

    $ npm start
    //或者使用pm2来启动
    $ pm2 start index.js -i 1 --name yf-ci-web
    

    3. Useage

    打开 http://[yourdomain]:3000

    4. Known Issues

    • windows 上无法执行cmd 的指令

    2. task-trigger

    可视化配置定时任务,在指定的时间执行任务请求,对已有系统无任何倾入,可快速集成使用。

    任务列表 创建任务

    3. yf-fast-dbm

    快速极简的orm框架

    • 源码地址: https://github.com/yfsoftcom/yf-fast-dbm
    • 目前支持mysql,使用 jugglingdb
    • 通过delflag实现逻辑删除
    • 默认带有四个字段:id,createAt,updateAt,delflag
    • 支持批量插入
    • TODO:事务,存储过程,mongodb语法

    1.Installation

    $ npm install yf-fast-dbm

    2.API List

    • adapter

    获取原生的数据库适配器,可执行自定义的sql来满足一些复杂的业务操作

    • find

    通过一组查询、排序、分页的条件筛选一组数据结果。

    • first

    通过一组查询、排序、分页的条件筛选一行数据结果。

    • count

    通过筛选条件进行统计计数

    • findAndCount

    通过一组查询、排序、分页的条件筛选一组数据结果,并返回符合条件的所有数据行数

    • get

    通过数据的ID获取到唯一的数据

    • update

    修改一些数据

    • remove

    删除一条已知的数据

    • clear

    通过筛选条件删除一组数据

    • create

    添加一条或者多条数据

    3.Configuration

    模块自带的一些配置信息:

    • Code List 1:
    {
        host:'localhost',           //mysql host
        port:3306,                  //mysql port
        database:'test',            //mysql dbname
        username:'root',            //mysql username
        password:'',                //mysql password
        debug:false,                //true:输出jugglingdb生成的sql语句
        showSql:false,              //true:输出本模块生成的sql语句
        pool:{
            connectionLimit:10,     //链接池的配置
            queueLimit:0,
            waitForConnections:true
        }
    }
    

    在初始化的时候,可以通过传入的参数覆盖这些默认值

    • Code List 2:
    var C = {
        host:'192.168.1.1',
        database:'test',
        username:'root',
        password:'root',
    };
    var M = require('yf-fast-dbm')(C);
    

    4.Useage

    find
    • Code List 3:
    // M 的初始化代码请参看 Code List:2
    var arg = {
     table: "test",
     condition: "delflag=0",
     fields: "id,article,ptags,product"
    };
    M.find(arg).then(function (data) {
     // do success here
    }).catch(function (err) {
     // do error here
    });
    
    first
    • Code List 4:
    // M 的初始化代码请参看 Code List:2
    var arg = {
     table: "test",
     condition: "delflag=0",
     fields: "id,article,ptags,product"
    };
    M.first(arg).then(function (data) {
     // do success here
    }).catch(function (err) {
     // do error here
    });
    
    count
    • Code List 5:
    // M 的初始化代码请参看 Code List:2
    var arg = {
     table: "test",
     condition: "delflag=0"
    };
    M.count(arg).then(function (c) {
     // do success here
    }).catch(function (err) {
     // do error here
    });
    
    findAndCount
    • Code List 6:
    // M 的初始化代码请参看 Code List:2
    var arg = {
     table: "test",
     condition: "delflag=0",
     fields: "id,article,ptags,product"
    };
    M.first(arg).then(function (data) {
     // do success here
    }).catch(function (err) {
     // do error here
    });
    
    get
    • Code List 7:
    // M 的初始化代码请参看 Code List:2
    var arg = {
     table: "test",
     id: 1
    };
    M.get(arg).then(function (data) {
     // do success here
    }).catch(function (err) {
     // do error here
    });
    
    update
    • Code List 8:
      修改所有key为test的val为123
    // M 的初始化代码请参看 Code List:2
    var arg = {
     table: "test",
     condition: "key = 'test'",
        row:{val:"123"}
    };
    M.update(arg).then(function (data) {
     // do success here
    }).catch(function (err) {
     // do error here
    });
    
    remove
    • Code List 9:
    // M 的初始化代码请参看 Code List:2
    var arg = {
     table: "test",
     id: 1
    };
    M.remove(arg).then(function (data) {
     // do success here
    }).catch(function (err) {
     // do error here
    });
    
    clear
    • Code List 10:
    // M 的初始化代码请参看 Code List:2
    var arg = {
     table: "test",
     condition: "delflag=0"
    };
    M.clear(arg).then(function (data) {
     // do success here
    }).catch(function (err) {
     // do error here
    });
    
    create
    • Code List 11:
    // M 的初始化代码请参看 Code List:2
    var arg = {
     table: "test",
     row: {key:"test",val:"mmm"}
    };
    M.create(arg).then(function (data) {
     // do success here
    }).catch(function (err) {
     // do error here
    });
    

    or batch insert

    • Code List 12:
    // M 的初始化代码请参看 Code List:2
    var arg = {
     table: "test",
     row:[{key:"test",val:"mmm"},{key:"test2",val:"mmm2"}]
    };
    M.create(arg).then(function (data) {
     // do success here
    }).catch(function (err) {
     // do error here
    });
    

    4. yf-api-server

    0.OVERVIEW

    一款灵活的api服务端,自动集成crud的数据操作,灵活扩展自定义业务逻辑

    设计概要

    背景

    团队的产品从单平台,慢慢扩展到多个客户端,且有多个异构系统的数据交互,所以需要一个统一的数据输入输出口。

    • 用node有个人私心,因为喜欢它,虽然编写java已经有近7年的时间了,但我还是想跳出自己的舒适区。
    • 使用restify作为http框架,因为它够轻,够简洁,几乎没有学习成本,而且体积小,自然坑也少 [偷笑]。
    • 没有使用restful风格,因为业务需要对数据有权限限制,而且业务交集很多,对路由的管理成本就大。
    • 经过一小段时间的纠结,决定采用taobao和jd的开放平台的设计方案,定义统一的入口,通过参数定位业务接口,实现灵活的业务开发。
    定义

    服务只有一个入口 /api ; 只接受post方式的请求,定义如下

    • 传入参数结构
    参数名 类型 是否必须 参数说明 默认值 示例
    method String Y 需要调用的业务函数
    appkey String Y 应用被分配的密钥
    timestamp Number Y 应用端的时间戳,用于验证请求的时效性 13位时间戳
    v String N 调用的服务端接口的版本号
    param Object N 业务函数需要用到的参数,以JsonObject的形式传入
    sign String Y 将接口参数进行升序排列,如 appkey,method,param,timestamp添加一个masterKey=xxx[此处的key来自于注册的key] 组合成appkey=123&masterKey=xxx&param=44444&tmiestamp=140932932932[所有的参数值使用urlencode] 过md5加密,生成一个32位的密钥
    • 输出参数结构
    参数名 类型 是否必须 参数说明
    errno Number Y 业务函数的错误代码,通常为0,表示正常执行,<0 则表示执行错误,可通过应用说明获取到具体的错误原因。
    message String N 通常在执行出错的情况下,会输出错误的信息。
    timestamp Number N 返回服务端处理完信息之后的时间戳。
    data Object/Array Y 一般的查询类的业务函数,会在该字段下携带查询结果信息;具体是Object类型还是Array类型则根据不同的业务函数的说明而定。
    error Object N 错误信息的详细内容

    这样的设计不能满足现在的restful范式,但是能满足我们团队现有的需求,提高了业务实现的开发效率;

    • 效果预览
    启动服务 postman 测试

    1.Install

    • 依赖不少,请耐心等待几分钟。
      $ npm install yf-api-server --save

    • 需要手动创建一下logs记录日志文件的目录
      $ mkdir logs

    • 创建一个数据库和两张表
      api_app:保存了appkey和secretkey的记录


      api_app

      api_record:记录每一次的接口请求


      api_record

    SQL脚本

    --
    -- 表的结构 `api_app`
    --
    
    CREATE TABLE IF NOT EXISTS `api_app` (
      `id` int(12) NOT NULL AUTO_INCREMENT,
      `appid` int(12) NOT NULL,
      `appname` varchar(120) NOT NULL,
      `apptype` varchar(120) NOT NULL,
      `appkey` varchar(120) NOT NULL,
      `secretkey` varchar(120) NOT NULL,
      `appenvironment` varchar(120) NOT NULL,
      `approot` varchar(120) NOT NULL,
      `createAt` int(32) NOT NULL,
      `updateAt` int(32) NOT NULL,
      `delflag` int(12) NOT NULL,
      `status` int(12) NOT NULL DEFAULT '1',
      `about` varchar(250) NOT NULL,
      `appurl` varchar(500) DEFAULT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `appid` (`appid`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
    
    --
    -- 表的结构 `api_record`
    --
    
    CREATE TABLE IF NOT EXISTS `api_record` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `appkey` varchar(100) NOT NULL,
      `createAt` bigint(20) NOT NULL,
      `timestamp` bigint(20) NOT NULL,
      `param` varchar(1000) NOT NULL,
      `sign` varchar(100) NOT NULL,
      `v` varchar(100) NOT NULL,
      `method` varchar(100) NOT NULL,
      `updateAt` bigint(20) NOT NULL,
      `delflag` tinyint(4) NOT NULL DEFAULT '0',
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;
    
    INSERT INTO `api_app` (`id`, `appid`, `appname`, `apptype`, `appkey`, `secretkey`, `appenvironment`, `approot`, `createAt`, `updateAt`, `delflag`, `status`, `about`, `appurl`) VALUES
    (1, 10001, 'YFDemoKey', 'PC', 'a81bc1bb1122323b', '3fc4h39d3ed9b33b67fcbc359131e7ee', 'DEV', '*', 1462610156, 1462773916, 0, 1, 'YF所有,抄袭必究', NULL)
    
    -- 这里的appkey 和 secretkey会在接口调用的时候被使用到
    -- appkey : 'a81bc1bb1122323b'
    

    2.Config

    $ touch config.js
    $ vi config.js
    
    var k = {
      db:{
          host: '192.168.1.1',
          port:3306,
          username:'root',
          password:'',
      },
      database:{'api':'api'},
      server:{port:8080},
      dev:'DEV'
    };
    
    var getDbConfig = function(option){
        var originConfig = {
            host: 'localhost',
            port:3306,
            username:'root',
            password:'',
            debug:false,
            pool:{
                connectionLimit:10,
                queueLimit:0,
                waitForConnections:true
            }
        };
        for(var key in k.db){
            originConfig[key] = k.db[key];
        }
        for(var key in option){
            originConfig[key] = option[key];
        }
        return originConfig;
    };
    module.exports = {
        db:(function(database){
            var _dbs = {};
            for(var d in database){
                _dbs[d] = getDbConfig({database:database[d]});
            }
            return _dbs;
        })(k.database),
        server: k.server||{
            port: k.dev == 'PRODUCT'?9001:8080
        },
        defaultVersion:'0.0.1',
        dev:k.dev,
        log4js: {
            appenders: [
                { type: 'console' },{
                    type: 'file',
                    filename: 'logs/access.log',
                    maxLogSize: 1024 * 1024 * 100, //100Mb一个文件
                    backups:10,
                    category: 'normal'
                }
            ],
            replaceConsole: true,
            levels:{
                dateFileLog: 'debug',
                console: 'errno'
            }
        }
    };
    
    

    3.Code

    编写代码,最终的目录结构预览如下

    项目目录
    $ mkdir V0.0.2 && cd V0.0.2 && touch index.js && vi index.js
    
    'use strict';
    var _ = require('underscore');
    var Q = require('q');
    module.exports = function(C,M,H){
      var q = Q.defer();
    
      M.test = function(){
        var _q = Q.defer();
        _q.resolve({data:"中文和zimu from v0.0.2"})
        return _q.promise;
      }
    
      q.resolve({'foo':M});  //业务名称: foo.test
      return q.promise;
    };
    
    
    $ touch app.js
    $ vi app.js
    
    var async = require('async');
    var config = require('./config.js');
    var M = {};
    var v002 = require('./V0.0.2');
    var yfserver = require('yf-api-server');
    var app = yfserver(config);
    
    async.parallel({
      '0.0.2':function(cb){
        v002(config,M,yfserver.hook).then(function(biz){
          cb(null,biz);
        });
      }
    },function(err,results){
        if(err){
          console.log(err);
          return;
        }
        app.setBizModules(results);
        app.start();
      }
    );
    
    

    4.Run

    $ node app.js

    node app.js

    postman测试


    postman测试

    5.Other

    到此,一个能满足基本业务的api服务端就搭建好了
    目前我的项目在使用它做生产环境了

    代码结构

    pm2 logs

    pm2 logs

    欢迎拍砖~~

    测试的

    相关文章

      网友评论

          本文标题:产品整理

          本文链接:https://www.haomeiwen.com/subject/xsowsttx.html