产品整理
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
4. Known Issues
- windows 上无法执行cmd 的指令
2. task-trigger
可视化配置定时任务,在指定的时间执行任务请求,对已有系统无任何倾入,可快速集成使用。
- 源码地址: https://github.com/yfsoftcom/task_trigger
- 基于node环境,使用schedule模块
- 通过配置cron表达式和request执行web请求
- 需要配合 api-server 进行使用
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的数据操作,灵活扩展自定义业务逻辑
- 源码地址: https://github.com/yfsoftcom/yf-api-server
- 基于restify框架
- 支持key+secret双端验证
- 支持接口权限验证
- 支持hook钩子操作
- 支持接口多版本同时在线
设计概要
背景
团队的产品从单平台,慢慢扩展到多个客户端,且有多个异构系统的数据交互,所以需要一个统一的数据输入输出口。
- 用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¶m=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范式,但是能满足我们团队现有的需求,提高了业务实现的开发效率;
- 效果预览
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
postman测试
postman测试
5.Other
到此,一个能满足基本业务的api服务端就搭建好了
目前我的项目在使用它做生产环境了
pm2 logs
pm2 logs欢迎拍砖~~
测试的