這篇文章主要講解了“Fizz Gateway網(wǎng)關(guān)腳本功能的高級用法教程”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Fizz Gateway網(wǎng)關(guān)腳本功能的高級用法教程”吧!
創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比銅山網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式銅山網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋銅山地區(qū)。費用合理售后完善,十余年實體公司更值得信賴。
校驗不通過時,F(xiàn)izz會把校驗失敗的原因(如:訂單ID不能為空)放到上下文的validateMsg字段里
可以自定義返回給調(diào)用方的報文格式,如 msgCode, message
支持自定義響應(yīng)頭
支持自定義腳本處理校驗結(jié)果
一個聚合接口可包含多個步驟
一個步驟可包含多個請求(即調(diào)用多個接口)
步驟間是串聯(lián)順序執(zhí)行
一個步驟內(nèi)的多個請求并行執(zhí)行
支持配置固定值,引用值和腳本
#固定值
#腳本
#星號 *
星號通配符可以接收一個返回對象類型的引用值,返回對象里的字段會合并到目標(biāo)對象里
樣例:userInfo = {"userName": "Fizz", "userID": 1234}
#優(yōu)先級與覆蓋順序
固定值 < 引用值 < 腳本 < 星號*
當(dāng)一個字段配置了多種類型的值時按以上順序覆蓋,星號優(yōu)先級最高
#引用值規(guī)范
# 獲取入?yún)⒄埱箢^aaa的值 input.request.headers.aaa # 獲取入?yún)⒄埱篌wbbb字段的值 input.request.body.bbb # 獲取入?yún)RL Query參數(shù)fff字段的值 input.request.params.fff # 獲取步驟1里request1的請求頭ccc的值 step1.request1.request.headers.ccc # 獲取步驟1里request1的響應(yīng)體ddd的值 step1.request1.response.body.ddd # 獲取步驟1結(jié)果里eee的值 step1.result.eee
支持單值引用,如:string,int等
支持對象類型的引用
input: 表示調(diào)用方的輸入數(shù)據(jù),如H5頁面提交上來的參數(shù)
stepN.requestN: 表示步驟N里調(diào)用接口N的相關(guān)參數(shù)
stepN.result: 表示步驟N的轉(zhuǎn)換結(jié)果
#Fallback與預(yù)處理條件
Fallback:
當(dāng)調(diào)用接口發(fā)生異常(如超時、網(wǎng)絡(luò)或系統(tǒng)異常)可配置fallback方案:
Stop: 終止請求并立即返回
Continue: 繼續(xù)后續(xù)的操作,且要設(shè)置默認(rèn)的fallback json
預(yù)處理: 根據(jù)條件判斷是否要調(diào)用接口,腳本返回true時才調(diào)用接口
#配置步驟結(jié)果處理
配置返回給調(diào)用方的結(jié)果
支持配置響應(yīng)頭
支持配置響應(yīng)體
支持自定腳本處理復(fù)雜的業(yè)務(wù)邏輯
Fizz
支持通過自定義腳本進(jìn)行服務(wù)編排:
在 配置輸入 中 通過 腳本校驗 輸入內(nèi)容;
在 配置輸出 中 通過 腳本 定義 輸出內(nèi)容,也可以細(xì)化到 某個輸出字段的 腳本處理;
在 配置步驟 中 通過 腳本 定義 配置入?yún)?、配置響?yīng) 的返回內(nèi)容;
在 結(jié)果校驗 中 通過 腳本 完全自定義校驗邏輯,校驗輸出內(nèi)容。
Fizz
支持 javascript
和 groovy
兩種腳本語言,方便開發(fā)人員靈活的選擇自己熟悉的語言進(jìn)行服務(wù)編排。
其中,
如果使用javascript
,可以 通過 common
對象獲取一系列工具函數(shù),方便進(jìn)行邏輯處理;
而在 groovy
中,所有的工具函數(shù)都掛載在 context
下,你可以很方便的使用它們。
#javascript
編寫JavaScript腳本時,需要按照以下固定格式進(jìn)行編寫。 function name dyFunc
不可修改。
返回值只能是基本類型,如 string/number/boolean
,object/array
類型的必須通過JSON.stringify
序列化后返回。
Fizz 是通過調(diào)用 js引擎執(zhí)行javascript腳本,然后捕獲執(zhí)行結(jié)果,只能獲取基本的數(shù)據(jù)類型。
object/array類型捕獲前,會調(diào)用原型上的
toString
方法,得到的結(jié)果為[object type]
的字符串,并非預(yù)期的數(shù)據(jù),所以必須通過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支持的任何數(shù)據(jù)類型。
import com.alibaba.fastjson.JSON import com.alibaba.fastjson.JSONArray import com.alibaba.fastjson.JSONObject // do something... // return any result return result
在 編輯服務(wù)編排接口時,允許在 配置輸入 中,對輸入的數(shù)據(jù)進(jìn)行自定義的腳本校驗,校驗 請求頭、請求體、query參數(shù)是否通過驗證。
返回的驗證結(jié)果,必須是一個 序列化后的 數(shù)組,且:
如果校驗通過,則返回一個空數(shù)組;
如果校驗不通過,將校驗不通過的錯誤信息,push到數(shù)組中后返回。
參考示例:
javascript
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; // 獲取聚合接口用戶輸入的數(shù)據(jù) // 獲取請求頭 var token = common.getInputReqHeader(ctx, 'token'); // 獲取請求參數(shù) var account = common.getInputReqParam(ctx, 'account'); var validate = []; // 校驗請求參數(shù) if (!token) { // 將校驗不通過的錯誤信息push到validate中 validate.push('缺少 token'); } if (!account) { validate.push('缺少 account'); } // 將 數(shù)組 validate 序列化后返回 // 空數(shù)組表示校驗通過,非空表示校驗不通過 return JSON.stringify(validate); }
groovy
// 獲取聚合接口用戶輸入的數(shù)據(jù) // 獲取請求頭 String token = context.getInputReqHeader('token') // 獲取請求參數(shù) String account = context.getInputReqAttr('params').get('account') Listvalidate = new LinkedList<>() // 校驗請求參數(shù) if (token == null || token.trim().isEmpty()) { // 將校驗不通過的錯誤信息add到validate中 validate.add('缺少 token') } if (account == null || account.trim().isEmpty()) { validate.add('缺少 account') } // 空數(shù)組表示校驗通過,非空表示校驗不通過 return validate
#輸出 完整response
在 編輯服務(wù)編排接口時,允許在 配置輸出 中,自定義輸出結(jié)果。
對于返回結(jié)果,建議以 { 狀態(tài)碼, 請求信息,請求結(jié)果 }
的數(shù)據(jù)結(jié)構(gòu)進(jìn)行返回,示例如下:
{ "msgCode": 0, // 狀態(tài)碼 "message": "success", // 請求信息 "data": { // 請求結(jié)果 "count": 1 } }
當(dāng)腳本內(nèi)部執(zhí)行時,檢查到發(fā)生異常,需要終止請求,可在 響應(yīng)的結(jié)果中, 添加_stopAndResponse: true
用于中斷,直接將當(dāng)前結(jié)果返回到用戶端。
{ "msgCode": 1, // 狀態(tài)碼 "message": "request error", "_stopAndResponse": true // 終止請求并返回響應(yīng)結(jié)果 }
配置輸出腳本示例:
// javascript腳本函數(shù)名不能修改 function dyFunc(paramsJsonStr) { var context = JSON.parse(paramsJsonStr)['context']; var data = common.getStepRespBody(context, 'step2', 'request1', 'data'); // do something // 自定義 返回結(jié)果,如果返回的Object里含有_stopAndResponse=true字段時將會終止請求并把腳本結(jié)果響應(yīng)給客戶端(主要用于有異常情況要終止請求的場景) var result = { // 對于result 內(nèi)的數(shù)據(jù)結(jié)構(gòu)無其他特殊要求,msgCode/message/data字段僅做示例 // _stopAndResponse: true, msgCode: '0', message: '', data: data }; // 返回結(jié)果為Array或Object時要先轉(zhuǎn)為json字符串 return JSON.stringify(result); }
#單個字段 輸出腳本處理
在 編輯服務(wù)編排接口時,允許在 配置輸出 中,通過腳本處理,自定義單個字段的值。
在字段配置中,選擇 腳本后,即可通過腳本 配置 單個字段的值。
這里的腳本執(zhí)行的結(jié)果只賦值給單個字段。
// javascript腳本函數(shù)名不能修改 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; }
與 上面的 配置輸入——腳本校驗 和__配置輸出__ 相同。
結(jié)果校驗指為最終返回給用戶端的數(shù)據(jù)進(jìn)行校驗。
返回的驗證結(jié)果,必須是一個 序列化后的 數(shù)組,且:
如果校驗通過,則返回一個空數(shù)組;
如果校驗不通過,將校驗不通過的錯誤信息,push到數(shù)組中后返回。
參考示例:
javascript
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; // 獲取聚合接口用戶輸入的數(shù)據(jù) // 獲取請求頭 var token = common.getInputReqHeader(ctx, 'token'); // 獲取請求參數(shù) var account = common.getInputReqParam(ctx, 'account'); var validate = []; // 校驗請求參數(shù) if (!token) { // 將校驗不通過的錯誤信息push到validate中 validate.push('缺少 token'); } if (!account) { validate.push('缺少 account'); } // 將 數(shù)組 validate 序列化后返回 // 空數(shù)組表示校驗通過,非空表示校驗不通過 return JSON.stringify(validate); }
groovy
// 獲取聚合接口用戶輸入的數(shù)據(jù) // 獲取請求頭 String token = context.getInputReqHeader('token') // 獲取請求參數(shù) String account = context.getInputReqAttr('params').get('account') Listvalidate = new LinkedList<>() // 校驗請求參數(shù) if (token == null || token.trim().isEmpty()) { // 將校驗不通過的錯誤信息add到validate中 validate.add('缺少 token') } if (account == null || account.trim().isEmpty()) { validate.add('缺少 account') } // 空數(shù)組表示校驗通過,非空表示校驗不通過 return validate
context
javascript
腳本中的context
是僅作用域函數(shù)作用域中的,作為 function dyFunc(paramsJsonStr){}
的第一個入?yún)魅搿?/p>
function dyFunc(paramsJsonStr) { // 傳入的 paramsJsonStr 僅是一個字符串,需要通過JSON.parse進(jìn)行序列化后獲取`context` var ctx = JSON.parse(paramsJsonStr)['context']; // do something... }
context
數(shù)據(jù)結(jié)構(gòu)描述:
interface context { debug: boolean; // 是否DEBUG模式 elapsedTimes: elapsedTime[]; // 各個操作的耗時 input: { // 客戶輸入和接口的返回結(jié)果 request: { // 請求 path: string; // 請求路徑 method: string; // 請求方法 POST/GET/PUT/DELETE/... headers: { [head: string]: any; }; // 請求頭 body: { [field: string]: any; }; // 請求體 params: { [param: string]: any; }; // 響應(yīng)體 }; response: { // 響應(yīng) headers: { [head: string]: any; }; // 響應(yīng)頭 body: { [field: string]: any; }; // 響應(yīng)體 聚合接口的響應(yīng) }; }; [stepName: string]: { // 步驟 [requestName: string]: { // 接口 request: { // // 請求相關(guān)參數(shù) url: string; // 請求路徑 method: string; // 請求方法 POST/GET/PUT/DELETE/... headers: { [head: string]: any; }; // 請求頭 body: { [body: string]: any; }; // 請求體 params: { [param: string]: any; }; // 響應(yīng)體 }; response: { // 響應(yīng) 根據(jù)轉(zhuǎn)換規(guī)則轉(zhuǎn)換后的接口響應(yīng) headers: { [head: string]: any; }; // 響應(yīng)頭 body: { [field: string]: any; }; // 響應(yīng)體 }; } }; result: string | number | boolean; // object/array 需要使用 JSON.stirngify 序列化 } interface elapsedTime { [acticeName: string]: number; // 操作名稱:耗時 }
為了方便在腳本中使用context
,我們提供了 javascript
和 groovy
兩種腳本的工具函數(shù)。
common.getInputReq(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; // 請求參數(shù) // do something... // return anything string return ''; }
ctx
: 上下文
common.getStepReq(ctx, stepName, requestName)
:
獲取上下文步驟中請求接口的請求對象
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; // 請求參數(shù) // do something... // return anything string return ''; }
ctx
: 上下文
stepName
: 配置步驟中的 step name
requestName
:配置步驟中的 stepName 對應(yīng)的 request name
common.getStepResp(ctx, stepName, requestName)
獲取上下文步驟中請求接口的響應(yīng)對象
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var stepResp = common.getStepResp(ctx, 'step1', 'request1'); // do something... // return anything string return ''; }
ctx
: 上下文
stepName
: 配置步驟中的 step name
requestName
:配置步驟中的 stepName 對應(yīng)的 request name
common.getInputReqHeader(ctx, headerName)
獲取客戶端請求頭
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getInputReqHeader(ctx, 'content-type'); // do something... // return anything string return ''; }
ctx
: 上下文
headerName
: 請求頭字段名 【選填】,不傳時返回所有請求頭
common.getInputReqParam(ctx, paramName)
獲取客戶端URL請求參數(shù)(query string)
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqParam(ctx, 'page'); // do something... // return anything string return ''; }
ctx
: 上下文
paramName URL參數(shù)名 【選填】,不傳時返回所有請求參數(shù)
common.getInputReqBody(ctx, field)
獲取客戶端請求體
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqBody(ctx, 'page'); // do something... // return anything string return ''; }
ctx
: 上下文
field
字段名 【選填】,不傳時返回整個請求體
common.getInputRespHeader(ctx, headerName)
獲取返回給客戶端的響應(yīng)頭
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputRespHeader(ctx, 'content-type'); // do something... // return anything string return ''; }
ctx
: 上下文
headerName
響應(yīng)頭字段名 【選填】,不傳時返回所有響應(yīng)頭
common.getInputRespBody(ctx, field)
獲取返回給客戶端的響應(yīng)體
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getInputReqBody(ctx, 'page'); // do something... // return anything string return ''; }
ctx
: 上下文
field
字段名 【選填】,不傳時返回整個響應(yīng)體
common.getStepReqHeader(ctx, stepName, requestName, headerName)
獲取步驟中調(diào)用的接口的請求頭
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getStepReqHeader(ctx, 'step1', 'request1', 'content-type'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
headerName
請求頭字段名 【選填】,不傳時返回所有請求頭
common.getStepReqParam(ctx, stepName, requestName, paramName)
獲取步驟中調(diào)用的接口的URL參數(shù)
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepReqParam(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
paramName
URL參數(shù)名 【選填】,不傳時返回所有URL參數(shù)
common.getStepReqBody(ctx, stepName, requestName, field)
獲取步驟中調(diào)用的接口的請求體
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepReqBody(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
field
字段名 【選填】,不傳時返回整個請求體
common.getStepRespHeader(ctx, stepName, requestName, headerName)
獲取步驟中調(diào)用的接口的響應(yīng)頭
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var contentType = common.getStepRespHeader(ctx, 'step1', 'request1', 'content-type'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
headerName
響應(yīng)頭字段名 【選填】,不傳時返回所有響應(yīng)頭
common.getStepRespBody(ctx, stepName, requestName, field)
獲取步驟中調(diào)用的接口的響應(yīng)頭
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var page = common.getStepRespBody(ctx, 'step1', 'request1', 'page'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
field
字段名 【選填】,不傳時返回整個響應(yīng)頭
common.getStepResult(ctx, stepName, field)
獲取步驟結(jié)果
function dyFunc(paramsJsonStr) { var ctx = JSON.parse(paramsJsonStr)['context']; var list = common.getStepResult(ctx, 'step1', 'list'); // do something... // return anything string return ''; }
ctx
上下文 【必填】
stepName
步驟名【必填】
field
字段名 【選填】,不傳時返回整個步驟結(jié)果對象
context.getInputReq()
獲取上下文客戶端中請求對象
Mapreq = context.getInputReq()
context.getStepReq(stepName, requestName)
:
獲取上下文步驟中請求接口的請求對象
Mapreq = context.getStepReq('step1', 'request1')
stepName
: 配置步驟中的 step name
requestName
:配置步驟中的 stepName 對應(yīng)的 request name
context.getStepResp(stepName, requestName)
獲取上下文步驟中請求接口的響應(yīng)對象
stepName
: 配置步驟中的 step name
requestName
:配置步驟中的 stepName 對應(yīng)的 request name
context.getInputReqHeader(headerName)
獲取客戶端請求頭
headerName
: 請求頭字段名 【選填】,不傳時返回所有請求頭
context.getInputReqParam(paramName)
獲取客戶端URL請求參數(shù)(query string)
paramName URL參數(shù)名 【選填】,不傳時返回所有請求參數(shù)
context.getInputReqBody(field)
獲取客戶端請求體
field
字段名 【選填】,不傳時返回整個請求體
context.getInputRespHeader(headerName)
獲取返回給客戶端的響應(yīng)頭
headerName
響應(yīng)頭字段名 【選填】,不傳時返回所有響應(yīng)頭
context.getInputRespBody(field)
獲取返回給客戶端的響應(yīng)體
field
字段名 【選填】,不傳時返回整個響應(yīng)體
context.getStepReqHeader(ctx, stepName, requestName, headerName)
獲取步驟中調(diào)用的接口的請求頭
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
headerName
請求頭字段名 【選填】,不傳時返回所有請求頭
context.getStepReqParam(stepName, requestName, paramName)
獲取步驟中調(diào)用的接口的URL參數(shù)
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
paramName
URL參數(shù)名 【選填】,不傳時返回所有URL參數(shù)
context.getStepReqBody(stepName, requestName, field)
獲取步驟中調(diào)用的接口的請求體
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
field
字段名 【選填】,不傳時返回整個請求體
context.getStepRespHeader(stepName, requestName, headerName)
獲取步驟中調(diào)用的接口的響應(yīng)頭
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
headerName
響應(yīng)頭字段名 【選填】,不傳時返回所有響應(yīng)頭
context.getStepRespBody(stepName, requestName, field)
獲取步驟中調(diào)用的接口的響應(yīng)頭
stepName
步驟名【必填】
requestName
請求的接口名 【必填】
field
字段名 【選填】,不傳時返回整個響應(yīng)頭
context.getStepResult(stepName, field)
獲取步驟結(jié)果
stepName
步驟名【必填】
field
字段名 【選填】,不傳時返回整個步驟結(jié)果對象
當(dāng)要在腳本里中止請求時可以通過以下方式來實現(xiàn)
返回一個對象且這個對象包含一個_stopAndResponse等于true的屬性,F(xiàn)izz會終止后續(xù)的操作并把這個對象返回給調(diào)用方。
通過腳本可以實現(xiàn)重定向,腳本返回一個對象且這個對象同時包含_stopAndResponse=true和_redirectUrl屬性,_redirectUrl的值為重定向的目標(biāo)URL,F(xiàn)izz會終止后續(xù)的操作并進(jìn)行重定向。JavaScript腳本樣例如下:
支持調(diào)試模式,在測試接口和正式接口均可使用,修改后重新發(fā)布可實時生效,在調(diào)試模式下會打印請求日志及報文,主要用于排查線上問題
當(dāng)腳本執(zhí)行異常時context里會記錄異常信息
exceptionMessage 異常信息
exceptionStacks 異常堆棧信息
exceptionData 引起異常的腳本數(shù)據(jù)
// 上下文數(shù)據(jù)結(jié)構(gòu)設(shè)計 // 上下文,用于保存客戶輸入輸出和每個步驟的輸入與輸出結(jié)果 var context = { // 是否DEBUG模式 debug:false, // exception info exceptionMessage: "", exceptionStacks: "", exceptionData: "", // such as script source code that cause exception // ... other fields }
在請求里加上returnContext=true可以返回context上下文,異常信息樣例:
導(dǎo)入導(dǎo)出主要用于在各個環(huán)境間同步接口配置,在開發(fā)環(huán)境配置好后導(dǎo)到測試環(huán)境中測試,測試完后導(dǎo)到生產(chǎn)環(huán)境進(jìn)行發(fā)布
目前發(fā)布|下線申請有以上兩個入口。
批量發(fā)布:對發(fā)布單里的接口進(jìn)行批量發(fā)布
批量回滾:對發(fā)布單里的接口進(jìn)行批量回滾
發(fā)布:實時發(fā)布到網(wǎng)關(guān)
回滾:支持回滾到歷史任何一個版本,可在發(fā)布?xì)v史里指定一個版本進(jìn)行回滾
下線:從網(wǎng)關(guān)刪除接口,在后臺可以通過發(fā)布功能再次上線
申請發(fā)布、審核、發(fā)布和下線功能的權(quán)限可根據(jù)需要靈活分配給不同角色,如:開發(fā)人員只能申請發(fā)布,上級領(lǐng)導(dǎo)審核,運維或測試人員執(zhí)行發(fā)布、回滾或下線。在開發(fā)、測試和預(yù)生產(chǎn)環(huán)境為了方便開發(fā)人員調(diào)試也可把申請發(fā)布、審核、發(fā)布和下線功能都分配給開發(fā)人員。
感謝各位的閱讀,以上就是“Fizz Gateway網(wǎng)關(guān)腳本功能的高級用法教程”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Fizz Gateway網(wǎng)關(guān)腳本功能的高級用法教程這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!