产品整理

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

欢迎拍砖~~

测试的
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容