首页 文章 精选 留言 我的

精选列表

搜索[gateway],共2550篇文章
优秀的个人博客,低调大师

Fizz Gateway网关脚本功能的高级用法

创建服务 #创建聚合接口 #配置输入 配置输入的定义包括3部分:请求头、请求体和Query参数 基于JSON Schema规范 自带校验规则 支持自定义脚本实现复杂的逻辑校验 JSON Schema规范,详见: http://json-schema.org/specification.html(opens new window) http://json-schema.org/understanding-json-schema/(opens new window) #配置校验结果 校验不通过时,Fizz会把校验失败的原因(如:订单ID不能为空)放到上下文的validateMsg字段里 可以自定义返回给调用方的报文格式,如 msgCode, message 支持自定义响应头 支持自定义脚本处理校验结果 #配置步骤 #配置步骤的基础信息 #配置步骤的接口入出参 #步骤说明 一个聚合接口可包含多个步骤 一个步骤可包含多个请求(即调用多个接口) 步骤间是串联顺序执行 一个步骤内的多个请求并行执行 #数据转换 支持配置固定值,引用值和脚本 #固定值 #引用值 #脚本 #星号 * 星号通配符可以接收一个返回对象类型的引用值,返回对象里的字段会合并到目标对象里 样例:userInfo = {"userName": "Fizz", "userID": 1234} #优先级与覆盖顺序 固定值 < 引用值 < 脚本 < 星号* 当一个字段配置了多种类型的值时按以上顺序覆盖,星号优先级最高 #引用值规范 # 获取入参请求头aaa的值 input.request.headers.aaa # 获取入参请求体bbb字段的值 input.request.body.bbb # 获取入参URL Query参数fff字段的值 input.request.params.fff # 获取步骤1里request1的请求头ccc的值 step1.request1.request.headers.ccc # 获取步骤1里request1的响应体ddd的值 step1.request1.response.body.ddd # 获取步骤1结果里eee的值 step1.result.eee 支持单值引用,如:string,int等 支持对象类型的引用 input: 表示调用方的输入数据,如H5页面提交上来的参数 stepN.requestN: 表示步骤N里调用接口N的相关参数 stepN.result: 表示步骤N的转换结果 #Fallback与预处理条件 Fallback: 当调用接口发生异常(如超时、网络或系统异常)可配置fallback方案: Stop: 终止请求并立即返回 Continue: 继续后续的操作,且要设置默认的fallback json 预处理: 根据条件判断是否要调用接口,脚本返回true时才调用接口 #配置步骤结果处理 支持对步骤里调用的每一个接口的返回结果做数据转换,如果配置数据转换规则原样返回并存储到上下文里供后续使用 支持对步骤里调用的一个或多个接口的返回结果做处理,并把处理完的结果存储到上下文里供后续使用,不配置则不处理 #配置输出 配置返回给调用方的结果 支持配置响应头 支持配置响应体 支持自定脚本处理复杂的业务逻辑 #脚本 #简介 Fizz支持通过自定义脚本进行服务编排: 在配置输入中 通过 脚本校验 输入内容; 在配置输出中 通过 脚本 定义 输出内容,也可以细化到 某个输出字段的 脚本处理; 在配置步骤中 通过 脚本 定义 配置入参、配置响应 的返回内容; 在结果校验中 通过 脚本 完全自定义校验逻辑,校验输出内容。 Fizz支持javascript和groovy两种脚本语言,方便开发人员灵活的选择自己熟悉的语言进行服务编排。 其中, 如果使用javascript,可以 通过common对象获取一系列工具函数,方便进行逻辑处理; 而在groovy中,所有的工具函数都挂载在context下,你可以很方便的使用它们。 #脚本编写格式 #javascript 编写JavaScript脚本时,需要按照以下固定格式进行编写。 function namedyFunc不可修改。 返回值只能是基本类型,如string/number/boolean,object/array类型的必须通过JSON.stringify序列化后返回。 Fizz 是通过调用 js引擎执行javascript脚本,然后捕获执行结果,只能获取基本的数据类型。 object/array类型捕获前,会调用原型上的toString方法,得到的结果为[object type]的字符串,并非预期的数据,所以必须通过JSON.stringify()序列化为jsonString后再返回。 请勿在js 中使用document等api function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; // do something... // return string/number/boolean/jsonString return JSON.stringify({}); } #groovy 编写groovy脚本时,支持返回groovy支持的任何数据类型。 import com.alibaba.fastjson.JSON import com.alibaba.fastjson.JSONArray import com.alibaba.fastjson.JSONObject // do something... // return any result return result #配置输入——脚本校验 在编辑服务编排接口时,允许在配置输入中,对输入的数据进行自定义的脚本校验,校验 请求头、请求体、query参数是否通过验证。 返回的验证结果,必须是一个 序列化后的 数组,且: 如果校验通过,则返回一个空数组; 如果校验不通过,将校验不通过的错误信息,push到数组中后返回。 参考示例: javascript function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; // 获取聚合接口用户输入的数据 // 获取请求头 var token = common.getInputReqHeader(ctx, 'token'); // 获取请求参数 var account = common.getInputReqParam(ctx, 'account'); var validate = []; // 校验请求参数 if (!token) { // 将校验不通过的错误信息push到validate中 validate.push('缺少 token'); } if (!account) { validate.push('缺少 account'); } // 将 数组 validate 序列化后返回 // 空数组表示校验通过,非空表示校验不通过 return JSON.stringify(validate); } groovy // 获取聚合接口用户输入的数据 // 获取请求头 String token = context.getInputReqHeader('token') // 获取请求参数 String account = context.getInputReqAttr('params').get('account') List<String> validate = new LinkedList<>() // 校验请求参数 if (token == null || token.trim().isEmpty()) { // 将校验不通过的错误信息add到validate中 validate.add('缺少 token') } if (account == null || account.trim().isEmpty()) { validate.add('缺少 account') } // 空数组表示校验通过,非空表示校验不通过 return validate #配置输出 #输出 完整response 在编辑服务编排接口时,允许在配置输出中,自定义输出结果。 对于返回结果,建议以{ 状态码, 请求信息,请求结果 }的数据结构进行返回,示例如下: { "msgCode": 0, // 状态码 "message": "success", // 请求信息 "data": { // 请求结果 "count": 1 } } 当脚本内部执行时,检查到发生异常,需要终止请求,可在 响应的结果中, 添加_stopAndResponse: true用于中断,直接将当前结果返回到用户端。 { "msgCode": 1, // 状态码 "message": "request error", "_stopAndResponse": true // 终止请求并返回响应结果 } 配置输出脚本示例: // javascript脚本函数名不能修改 function dyFunc(paramsJsonStr) { var context = JSON.parse(paramsJsonStr)['context']; var data = common.getStepRespBody(context, 'step2', 'request1', 'data'); // do something // 自定义 返回结果,如果返回的Object里含有_stopAndResponse=true字段时将会终止请求并把脚本结果响应给客户端(主要用于有异常情况要终止请求的场景) var result = { // 对于result 内的数据结构无其他特殊要求,msgCode/message/data字段仅做示例 // _stopAndResponse: true, msgCode: '0', message: '', data: data }; // 返回结果为Array或Object时要先转为json字符串 return JSON.stringify(result); } #单个字段 输出脚本处理 在编辑服务编排接口时,允许在配置输出中,通过脚本处理,自定义单个字段的值。 在字段配置中,选择 脚本后,即可通过脚本 配置 单个字段的值。 这里的脚本执行的结果只赋值给单个字段。 // javascript脚本函数名不能修改 function dyFunc(paramsJsonStr) { var context = JSON.parse(paramsJsonStr)['context']; var token = common.getStepRespBody(context, 'step2', 'request1', 'token'); // do something var memberId = parseToken(token); return memberId; } #配置步骤 与 上面的配置输入——脚本校验和__配置输出__ 相同。 #结果校验 结果校验指为最终返回给用户端的数据进行校验。 返回的验证结果,必须是一个 序列化后的 数组,且: 如果校验通过,则返回一个空数组; 如果校验不通过,将校验不通过的错误信息,push到数组中后返回。 参考示例: javascript function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; // 获取聚合接口用户输入的数据 // 获取请求头 var token = common.getInputReqHeader(ctx, 'token'); // 获取请求参数 var account = common.getInputReqParam(ctx, 'account'); var validate = []; // 校验请求参数 if (!token) { // 将校验不通过的错误信息push到validate中 validate.push('缺少 token'); } if (!account) { validate.push('缺少 account'); } // 将 数组 validate 序列化后返回 // 空数组表示校验通过,非空表示校验不通过 return JSON.stringify(validate); } groovy // 获取聚合接口用户输入的数据 // 获取请求头 String token = context.getInputReqHeader('token') // 获取请求参数 String account = context.getInputReqAttr('params').get('account') List<String> validate = new LinkedList<>() // 校验请求参数 if (token == null || token.trim().isEmpty()) { // 将校验不通过的错误信息add到validate中 validate.add('缺少 token') } if (account == null || account.trim().isEmpty()) { validate.add('缺少 account') } // 空数组表示校验通过,非空表示校验不通过 return validate #javascript 脚本中的context javascript脚本中的context是仅作用域函数作用域中的,作为function dyFunc(paramsJsonStr){}的第一个入参传入。 function dyFunc(paramsJsonStr) { // 传入的 paramsJsonStr 仅是一个字符串,需要通过JSON.parse进行序列化后获取`context` var ctx = JSON.parse(paramsJsonStr)['context']; // do something... } context数据结构描述: interface context { debug: boolean; // 是否DEBUG模式 elapsedTimes: elapsedTime[]; // 各个操作的耗时 input: { // 客户输入和接口的返回结果 request: { // 请求 path: string; // 请求路径 method: string; // 请求方法 POST/GET/PUT/DELETE/... headers: { [head: string]: any; }; // 请求头 body: { [field: string]: any; }; // 请求体 params: { [param: string]: any; }; // 响应体 }; response: { // 响应 headers: { [head: string]: any; }; // 响应头 body: { [field: string]: any; }; // 响应体 聚合接口的响应 }; }; [stepName: string]: { // 步骤 [requestName: string]: { // 接口 request: { // // 请求相关参数 url: string; // 请求路径 method: string; // 请求方法 POST/GET/PUT/DELETE/... headers: { [head: string]: any; }; // 请求头 body: { [body: string]: any; }; // 请求体 params: { [param: string]: any; }; // 响应体 }; response: { // 响应 根据转换规则转换后的接口响应 headers: { [head: string]: any; }; // 响应头 body: { [field: string]: any; }; // 响应体 }; } }; result: string | number | boolean; // object/array 需要使用 JSON.stirngify 序列化 } interface elapsedTime { [acticeName: string]: number; // 操作名称:耗时 } 为了方便在脚本中使用context,我们提供了javascript和groovy两种脚本的工具函数。 #工具函数——javascript common.getInputReq(ctx): 获取上下文客户端中请求对象 ctx: 上下文 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var req = common.getInputReq(ctx); var path = req.path; // 请求路径 var method = req.method; // 请求方法 var headers = req.headers; // 请求头 var body = req.body; // 请求体 var params = req.params; // 请求参数 // do something... // return anything string return ''; } common.getStepReq(ctx, stepName, requestName): 获取上下文步骤中请求接口的请求对象 ctx: 上下文 stepName: 配置步骤中的 step name requestName:配置步骤中的 stepName 对应的 request name function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var req = common.getStepReq(ctx, 'step1', 'request1'); var url = req.url; // 请求路径 var method = req.method; // 请求方法 var headers = req.headers; // 请求头 var body = req.body; // 请求体 var params = req.params; // 请求参数 // do something... // return anything string return ''; } common.getStepResp(ctx, stepName, requestName) 获取上下文步骤中请求接口的响应对象 ctx: 上下文 stepName: 配置步骤中的 step name requestName:配置步骤中的 stepName 对应的 request name function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var stepResp = common.getStepResp(ctx, 'step1', 'request1'); // do something... // return anything string return ''; } common.getInputReqHeader(ctx, headerName) 获取客户端请求头 ctx: 上下文 headerName: 请求头字段名 【选填】,不传时返回所有请求头 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getInputReqHeader(ctx, 'content-type'); // do something... // return anything string return ''; } common.getInputReqParam(ctx, paramName) 获取客户端URL请求参数(query string) ctx: 上下文 paramName URL参数名 【选填】,不传时返回所有请求参数 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqParam(ctx, 'page'); // do something... // return anything string return ''; } common.getInputReqBody(ctx, field) 获取客户端请求体 ctx: 上下文 field字段名 【选填】,不传时返回整个请求体 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqBody(ctx, 'page'); // do something... // return anything string return ''; } common.getInputRespHeader(ctx, headerName) 获取返回给客户端的响应头 ctx: 上下文 headerName响应头字段名 【选填】,不传时返回所有响应头 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputRespHeader(ctx, 'content-type'); // do something... // return anything string return ''; } common.getInputRespBody(ctx, field) 获取返回给客户端的响应体 ctx: 上下文 field字段名 【选填】,不传时返回整个响应体 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqBody(ctx, 'page'); // do something... // return anything string return ''; } common.getStepReqHeader(ctx, stepName, requestName, headerName) 获取步骤中调用的接口的请求头 ctx上下文 【必填】 stepName步骤名【必填】 requestName请求的接口名 【必填】 headerName请求头字段名 【选填】,不传时返回所有请求头 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getStepReqHeader(ctx, 'step1', 'request1', 'content-type'); // do something... // return anything string return ''; } common.getStepReqParam(ctx, stepName, requestName, paramName) 获取步骤中调用的接口的URL参数 ctx上下文 【必填】 stepName步骤名【必填】 requestName请求的接口名 【必填】 paramNameURL参数名 【选填】,不传时返回所有URL参数 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepReqParam(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; } common.getStepReqBody(ctx, stepName, requestName, field) 获取步骤中调用的接口的请求体 ctx上下文 【必填】 stepName步骤名【必填】 requestName请求的接口名 【必填】 field字段名 【选填】,不传时返回整个请求体 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepReqBody(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; } common.getStepRespHeader(ctx, stepName, requestName, headerName) 获取步骤中调用的接口的响应头 ctx上下文 【必填】 stepName步骤名【必填】 requestName请求的接口名 【必填】 headerName响应头字段名 【选填】,不传时返回所有响应头 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getStepRespHeader(ctx, 'step1', 'request1', 'content-type'); // do something... // return anything string return ''; } common.getStepRespBody(ctx, stepName, requestName, field) 获取步骤中调用的接口的响应头 ctx上下文 【必填】 stepName步骤名【必填】 requestName请求的接口名 【必填】 field字段名 【选填】,不传时返回整个响应头 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepRespBody(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; } common.getStepResult(ctx, stepName, field) 获取步骤结果 ctx上下文 【必填】 stepName步骤名【必填】 field字段名 【选填】,不传时返回整个步骤结果对象 function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var list = common.getStepResult(ctx, 'step1', 'list'); // do something... // return anything string return ''; } #工具函数——groovy context.getInputReq() 获取上下文客户端中请求对象 Map<String, Object> req = context.getInputReq() context.getStepReq(stepName, requestName): 获取上下文步骤中请求接口的请求对象 stepName: 配置步骤中的 step name requestName:配置步骤中的 stepName 对应的 request name Map<String, Object> req = context.getStepReq('step1', 'request1') context.getStepResp(stepName, requestName) 获取上下文步骤中请求接口的响应对象 stepName: 配置步骤中的 step name requestName:配置步骤中的 stepName 对应的 request name context.getInputReqHeader(headerName) 获取客户端请求头 headerName: 请求头字段名 【选填】,不传时返回所有请求头 context.getInputReqParam(paramName) 获取客户端URL请求参数(query string) paramName URL参数名 【选填】,不传时返回所有请求参数 context.getInputReqBody(field) 获取客户端请求体 field字段名 【选填】,不传时返回整个请求体 context.getInputRespHeader(headerName) 获取返回给客户端的响应头 headerName响应头字段名 【选填】,不传时返回所有响应头 context.getInputRespBody(field) 获取返回给客户端的响应体 field字段名 【选填】,不传时返回整个响应体 context.getStepReqHeader(ctx, stepName, requestName, headerName) 获取步骤中调用的接口的请求头 stepName步骤名【必填】 requestName请求的接口名 【必填】 headerName请求头字段名 【选填】,不传时返回所有请求头 context.getStepReqParam(stepName, requestName, paramName) 获取步骤中调用的接口的URL参数 stepName步骤名【必填】 requestName请求的接口名 【必填】 paramNameURL参数名 【选填】,不传时返回所有URL参数 context.getStepReqBody(stepName, requestName, field) 获取步骤中调用的接口的请求体 stepName步骤名【必填】 requestName请求的接口名 【必填】 field字段名 【选填】,不传时返回整个请求体 context.getStepRespHeader(stepName, requestName, headerName) 获取步骤中调用的接口的响应头 stepName步骤名【必填】 requestName请求的接口名 【必填】 headerName响应头字段名 【选填】,不传时返回所有响应头 context.getStepRespBody(stepName, requestName, field) 获取步骤中调用的接口的响应头 stepName步骤名【必填】 requestName请求的接口名 【必填】 field字段名 【选填】,不传时返回整个响应头 context.getStepResult(stepName, field) 获取步骤结果 stepName步骤名【必填】 field字段名 【选填】,不传时返回整个步骤结果对象 #抛出异常 当要在脚本里中止请求时可以通过以下方式来实现 返回一个对象且这个对象包含一个_stopAndResponse等于true的属性,Fizz会终止后续的操作并把这个对象返回给调用方。 #重定向 通过脚本可以实现重定向,脚本返回一个对象且这个对象同时包含_stopAndResponse=true和_redirectUrl属性,_redirectUrl的值为重定向的目标URL,Fizz会终止后续的操作并进行重定向。JavaScript脚本样例如下: #配置路由 至此服务编排的接口配置完成,但此时还不能通过网关访问接口,需要到网关管理-路由管理里配置路由 #在线测试 支持在线实时测试 支持测试接口和正式接口隔离 支持返回上下文,可以查看整个执行过程中各个步骤及请求的输入与输出 支持保存历史测试记录 支持调试模式,在测试接口和正式接口均可使用,修改后重新发布可实时生效,在调试模式下会打印请求日志及报文,主要用于排查线上问题 #脚本执行异常 当脚本执行异常时context里会记录异常信息 exceptionMessage 异常信息 exceptionStacks 异常堆栈信息 exceptionData 引起异常的脚本数据 // 上下文数据结构设计 // 上下文,用于保存客户输入输出和每个步骤的输入与输出结果 var context = { // 是否DEBUG模式 debug:false, // exception info exceptionMessage: "", exceptionStacks: "", exceptionData: "", // such as script source code that cause exception // ... other fields } 在请求里加上returnContext=true可以返回context上下文,异常信息样例: #导入导出 导入导出主要用于在各个环境间同步接口配置,在开发环境配置好后导到测试环境中测试,测试完后导到生产环境进行发布 #发布|下线和审核 目前发布|下线申请有以上两个入口。 批量发布:对发布单里的接口进行批量发布 批量回滚:对发布单里的接口进行批量回滚 发布:实时发布到网关 回滚:支持回滚到历史任何一个版本,可在发布历史里指定一个版本进行回滚 下线:从网关删除接口,在后台可以通过发布功能再次上线 #发布流程说明 申请发布、审核、发布和下线功能的权限可根据需要灵活分配给不同角色,如:开发人员只能申请发布,上级领导审核,运维或测试人员执行发布、回滚或下线。在开发、测试和预生产环境为了方便开发人员调试也可把申请发布、审核、发布和下线功能都分配给开发人员。

优秀的个人博客,低调大师

API Gateway Kong在Rainbond上的部署

什么是Kong Kong是一个可扩展的开源API平台(也称为API网关,API中间件或微服务服务网格)。Kong最初是由Kong Inc.(以前称为Mashape)实现的,用于为其API Marketplace维护、管理和扩展超过15,000个微服务,这些微服务每月产生数十亿个请求。 技术上讲,Kong是在Nginx中运行的Lua应用程序,并且通过lua-nginx-module实现。Kong是与OpenResty一起分发的,而不是使用此模块来编译Nginx,OpenResty已经包括lua-nginx-module。 了解更多有关Kong的事情,你需要点击了解一下。 从应用市场安装 快速安装 目前我们已经将最新版本(v1.4.X)的Kong发布到了应用市场,如果你想要快速的搭建以及使用Kong,你只需要做一件事情,那就是点击一下安装: 等待一小段时间后,Kong就已经部署在了你的Rainbond集群中了。在这个应用中,我们已经集成了Konga作为UI管理工具,接下来的步骤,需要你访问Konga,做几步简单的设置,就可以愉快的探索Kong了。 注册Konga 配置Kong的连接地址,写入 http://127.0.0.1:8001即可 连接成功,就可以使用Konga来管理你的Kong了 注意事项 如果你所使用的Rainbond平台,是在2019年12月25日以前安装的,并且没有进行过任何升级操作,那么你可能遇到Konga连接不到Kong的问题,解决的方案如下: 如果你使用了v5.1.9以前的版本,请升级到最新版本。 如果你现在已经在使用v5.1.9版本,那么请点击链接,打个补丁。 Kong的启动很消耗内存 配置Kong 环境变量 Kong支持以KONG_开头的环境变量进行配置。举例说明: 对于部署在Rainbond上的Kong来说,直接添加环境变量 KONG_LOG_LEVEL = error 即可在Kong的配置文件中生成 log_level = error 添加完成后,点击更新,即可使之生效。 注入Nginx配置 通过调整Kong实例的Nginx配置,可以优化其基础架构的性能。 Kong启动时,将构建一个Nginx配置文件。你可以通过Kong配置直接将自定义Nginx配置注入此文件。 注入单个Nginx配置 Kong的配置文件中的任何前缀为的条目nginx_http_, nginx_proxy_或nginx_admin_通过删除前缀将其转换为等效的Nginx指令,并将其添加到Nginx配置的相应部分: 前缀为的条目nginx_http_将注入到整体http 块指令中。 前缀为的条目nginx_proxy_将注入到server处理Kong代理端口的block指令中。 前缀为的条目nginx_admin_将注入到server处理Kong的Admin API端口的block指令中。 例如,如果将以下行添加到kong.conf文件中: nginx_proxy_large_client_header_buffers=16 128k 它将以下指令添加到serverKong的Nginx配置的代理块中: large_client_header_buffers 16 128k; 为了达到这个目的,你需要参考环境变量,为Kong添加以下环境变量: KONG_NGINX_HTTP_OUTPUT_BUFFERS = "4 64k" 通过注入的Nginx指令包含文件 对于更复杂的配置方案,例如添加整个新 server块,可以使用上述方法include向Nginx配置注入 指令,指向包含其他Nginx设置的文件。 可以通过在kong.conf文件中添加以下条目来包含目标文件: nginx_http_include = /path/to/your/my-server.kong.conf 在Rainbond上,可以通过环境变量进行配置: KONG_NGINX_HTTP_INCLUDE="/path/to/your/my-server.kong.conf" Kong应用怎么制作 即点即用的Kong,使用起来非常方便。那么这个应用是怎么制作的呢? 我们只需要做到以下几点,就可以发布出可以即点即用的云市场应用: 目标应用的所有组件都已经部署在Rainbond并正常运行 各服务组件使用的数据库具备自动初始化数据的功能 各服务组件间的依赖关系已经处理妥当,从业务层面已经正常运行 接下来,只需要参考应用分享与发布,将你的应用发布出去即可。 数据库自动初始化 Kong可以使用的数据库包括 Postgres与Cassandra,我们这里使用了前者。 首先利用docker run 命令快速部署一个Postgresql: docker run -d --name kong-database \ -p 5432:5432 \ -e "POSTGRES_USER=kong" \ -e "POSTGRES_DB=kong" \ postgres:9.6 使用Kong的镜像,即可初始化数据库表结构,在部署初始化组件时,要记得建立从 kong-init 指向 kong-database的依赖关系: docker run --rm \ --name kong-init \ --link kong-database:kong-database \ -e "KONG_DATABASE=postgres" \ -e "KONG_PG_HOST=127.0.0.1" \ -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ kong kong migrations bootstrap kong-init 运行完成后会自动退出,在Rainbond上显示运行异常,不用担心,它已经完成了使命,验证下 kong-database 中已存在数据表结构,就可以删除kong-init 了。 进入 kong-database 的容器实例,通过命令行工具备份出数据库。 pg_dump -U kong -d kong > /var/lib/postgresql/data/data.sql 找到 kong-database 的数据持久化目录,得到 data.sql,kong-database 的使命也就达成了,可以被关闭删除。 自定义一个代码仓库,参考 https://github.com/dazuimao1990/pri-postgresql/tree/kong 将 data.sql 放到 sql 目录下,即可用这份代码创建一个可以自动初始化表结构的Postgresql了。创建之,命名为 kong-postgres 备用。 部署Kong 直接使用docker run 命令创建Kong,要记得建立从 Kong 指向 kong-postgres 的依赖关系: docker run -d --name kong \ --link kong-database:kong-database \ -e "KONG_DATABASE=postgres" \ -e "KONG_PG_HOST=127.0.0.1" \ -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ -p 8000:8000 \ -p 8443:8443 \ -p 8001:8001 \ -p 8444:8444 \ kong 内存至少提高至4G。 部署Konga 直接使用docker run 命令创建Konga,要记得建立从 Konga 指向 Kong 的依赖关系: docker run -p 1337:1337 \ --name konga \ pantsel/konga 完成后,最终拓扑将会是这个样子的: 发布应用 点击 发布到市场,编辑它的信息,即可发布了。

优秀的个人博客,低调大师

微服务与网关技术(SIA-GateWay

一、背景 软件架构,总是在不断的演进中... 把时间退回到二十年之前,当时企业级领域研发主要推崇的还是C/S模式,PB、Delphi这样的开发软件是企业应用开发的主流。随着时间的推移,基于浏览器的B/S架构开始渐渐流行了起来。初期,Web开发ASP还占据了不少优势,但JSP的预编译模式让性能有了很大提升,随后基于JAVA语言的J2EE架构变得越来越流行。 早期软件架构基本都是单体架构,系统之间往往不需要进行交互,这也导致数据孤岛和ETL工具的发展。随着企业应用越来越多,相互的关系也越来密切,应用之间也迫切需要进行实时交互访问,随后基于XML的异构系统集成和数据交互技术开始被很多公司采用,SOA的概念被提了出来,web service逐渐流行。 互联网时代,很多公司为了适应更加灵活的业务需求,基于HTTP协议和Restful的架构风格及简洁

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册