forked from docs/doc-exports
Reviewed-by: Eotvos, Oliver <oliver.eotvos@t-systems.com> Co-authored-by: Chen, Junjie <chenjunjie@huawei.com> Co-committed-by: Chen, Junjie <chenjunjie@huawei.com>
123 lines
20 KiB
HTML
123 lines
20 KiB
HTML
<a name="functiongraph_04_0104"></a><a name="functiongraph_04_0104"></a>
|
|
|
|
<h1 class="topictitle1">Developing an Event Function</h1>
|
|
<div id="body0000001422307556"><div class="section" id="functiongraph_04_0104__section6371173123910"><h4 class="sectiontitle">Introduction</h4><p id="functiongraph_04_0104__p2073745323917">When developing an event function using a custom image, implement an HTTP server in the image and listen on port 8000 for requests. By default, the request path <strong id="functiongraph_04_0104__b647213120236">/init</strong> is the function initialization entry. Implement it as required. The request path <strong id="functiongraph_04_0104__b2758175975419">/invoke</strong> is the function execution entry where trigger events are processed. For details about request parameters, see section "Supported Event Sources".</p>
|
|
<p id="functiongraph_04_0104__p144081946111019"></p>
|
|
</div>
|
|
<div class="section" id="functiongraph_04_0104__section0418520193311"><h4 class="sectiontitle">Step 1: Prepare the Environment</h4><p id="functiongraph_04_0104__functiongraph_04_0101_p722313491535">To perform the operations described in this section, ensure that you have the <strong id="functiongraph_04_0104__functiongraph_04_0101_b571115773214">FunctionGraph FullAccess</strong> permissions, that is, all permissions for FunctionGraph. For more information, see section "Permissions Management".</p>
|
|
</div>
|
|
<div class="section" id="functiongraph_04_0104__section992877392"><h4 class="sectiontitle">Step 2: Create an Image</h4><p id="functiongraph_04_0104__p068419143913">Take the Linux x86 64-bit OS as an example.</p>
|
|
</div>
|
|
<ol id="functiongraph_04_0104__ol4774141334018"><li id="functiongraph_04_0104__li977419139409">Create a folder.<pre class="screen" id="functiongraph_04_0104__screen3922727114118">mkdir custom_container_event_example && cd custom_container_event_example</pre>
|
|
</li></ol><ol start="2" id="functiongraph_04_0104__ol1390513210407"><li id="functiongraph_04_0104__li11905021164011">Implement an HTTP server to process <strong id="functiongraph_04_0104__b144811436195311">init</strong> and <strong id="functiongraph_04_0104__b15543183916537">invoke</strong> requests and give a response. Node.js is used as an example.<p id="functiongraph_04_0104__p187921276440">Create the <strong id="functiongraph_04_0104__b377835185420">main.js</strong> file to introduce the Express framework and implement a function handler (method <strong id="functiongraph_04_0104__b850093395512">POST</strong> and path <strong id="functiongraph_04_0104__b10103144195517">/invoke</strong> and an initializer (method <strong id="functiongraph_04_0104__b9765390561">POST</strong> and path <strong id="functiongraph_04_0104__b1797141720561">/init</strong>).</p>
|
|
<pre class="screen" id="functiongraph_04_0104__screen9377151661515">const express = require('express');
|
|
|
|
const PORT = 8000;
|
|
|
|
const app = express();
|
|
app.use(express.json());
|
|
|
|
app.post('/init', (req, res) => {
|
|
console.log('receive', req.body);
|
|
res.send('Hello init\n');
|
|
});
|
|
|
|
app.post('/invoke', (req, res) => {
|
|
console.log('receive', req.body);
|
|
res.send('Hello invoke\n');
|
|
});
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`Listening on http://localhost:${PORT}`);
|
|
});</pre>
|
|
</li></ol><ol start="3" id="functiongraph_04_0104__ol1035701334214"><li id="functiongraph_04_0104__li71011312114818">Create the <strong id="functiongraph_04_0104__b150788866233614">package.json</strong> file for npm so that it can identify the project and process project dependencies.<pre class="screen" id="functiongraph_04_0104__screen28121453164913">{
|
|
"name": "custom-container-event-example",
|
|
"version": "1.0.0",
|
|
"description": "An example of a custom container event function",
|
|
"main": "main.js",
|
|
"scripts": {},
|
|
"keywords": [],
|
|
"author": "",
|
|
"license": "ISC",
|
|
"dependencies": {
|
|
"express": "^4.17.1"
|
|
}
|
|
}</pre>
|
|
<ul id="functiongraph_04_0104__ul9401719516"><li id="functiongraph_04_0104__li144021105119"><strong id="functiongraph_04_0104__b120008991033618">name</strong>: project name</li><li id="functiongraph_04_0104__li1354861819513"><strong id="functiongraph_04_0104__b172019169533620">version</strong>: project version</li><li id="functiongraph_04_0104__li71791629115113"><strong id="functiongraph_04_0104__b49431857152852">main</strong>: application entry file</li><li id="functiongraph_04_0104__li3728104885115"><strong id="functiongraph_04_0104__b7950572633632">dependencies</strong>: all available dependencies of the project in npm</li></ul>
|
|
</li><li id="functiongraph_04_0104__li5357613144220">Create a Dockerfile.<pre class="screen" id="functiongraph_04_0104__screen01586461643">FROM node:12.10.0
|
|
|
|
ENV HOME=/home/custom_container
|
|
ENV GROUP_ID=1003
|
|
ENV GROUP_NAME=custom_container
|
|
ENV USER_ID=1003
|
|
ENV USER_NAME=custom_container
|
|
|
|
RUN mkdir -m 550 ${HOME} && groupadd -g ${GROUP_ID} ${GROUP_NAME} && useradd -u ${USER_ID} -g ${GROUP_ID} ${USER_NAME}
|
|
|
|
COPY --chown=${USER_ID}:${GROUP_ID} main.js ${HOME}
|
|
COPY --chown=${USER_ID}:${GROUP_ID} package.json ${HOME}
|
|
|
|
RUN cd ${HOME} && npm install
|
|
|
|
RUN chown -R ${USER_ID}:${GROUP_ID} ${HOME}
|
|
|
|
RUN find ${HOME} -type d | xargs chmod 500
|
|
RUN find ${HOME} -type f | xargs chmod 500
|
|
|
|
USER ${USER_NAME}
|
|
WORKDIR ${HOME}
|
|
|
|
EXPOSE 8000
|
|
ENTRYPOINT ["node", "main.js"]</pre>
|
|
<ul id="functiongraph_04_0104__ul10963114434217"><li id="functiongraph_04_0104__li29636447427"><strong id="functiongraph_04_0104__b40866829433755">FROM</strong>: Specify base image <strong id="functiongraph_04_0104__b64439147333755">node:12.10.0</strong>. The base image is mandatory and its value can be changed.</li><li id="functiongraph_04_0104__li137654248557"><strong id="functiongraph_04_0104__b57440846433816">ENV</strong>: Set environment variables <strong id="functiongraph_04_0104__b27383288733816">HOME</strong> (<strong id="functiongraph_04_0104__b212089072533816">/home/custom_container</strong>), <strong id="functiongraph_04_0104__b135353342133816">GROUP_NAME</strong> and <strong id="functiongraph_04_0104__b35108011133816">USER_NAME</strong> (<strong id="functiongraph_04_0104__b37541488633816">custom_container</strong>), <strong id="functiongraph_04_0104__b97195286233816">USER_ID</strong> and <strong id="functiongraph_04_0104__b5494582533816">GROUP_ID</strong> (<strong id="functiongraph_04_0104__b214135771233816">1003</strong>). These environment variables are mandatory and their values can be changed.</li><li id="functiongraph_04_0104__li198492020124718"><strong id="functiongraph_04_0104__b109092800833831">RUN</strong>: Use the format <strong id="functiongraph_04_0104__b208547321533831">RUN</strong> <em id="functiongraph_04_0104__i197117224133831"><Command></em>. For example, <strong id="functiongraph_04_0104__b187155336233831">RUN mkdir -m 550 ${HOME}</strong>, which means to create the <strong id="functiongraph_04_0104__b52161570233831">home</strong> directory for user <em id="functiongraph_04_0104__i21948652033831">${USER_NAME}</em> during container building.</li><li id="functiongraph_04_0104__li15560499126"><strong id="functiongraph_04_0104__b110717632633834">USER</strong>: Switch to user <em id="functiongraph_04_0104__i214655775933834">${USER_NAME}</em>.</li><li id="functiongraph_04_0104__li1573427151310"><strong id="functiongraph_04_0104__b44430265933841">WORKDIR</strong>: Switch the working directory to the <strong id="functiongraph_04_0104__b163113450933841">home</strong> directory of user <em id="functiongraph_04_0104__i130471915733841">${USER_NAME}</em>.</li><li id="functiongraph_04_0104__li11176163481315"><strong id="functiongraph_04_0104__b183528929333848">COPY</strong>: Copy <strong id="functiongraph_04_0104__b137164894733848">main.js</strong> and <strong id="functiongraph_04_0104__b209721228533848">package.json</strong> to the <strong id="functiongraph_04_0104__b122061061533848">home</strong> directory of user <em id="functiongraph_04_0104__i12137363233848">${USER_NAME}</em> in the container.</li><li id="functiongraph_04_0104__li19963544104216"><strong id="functiongraph_04_0104__b166557212833858">EXPOSE</strong>: Expose port 8000 of the container. Do not change this parameter.</li><li id="functiongraph_04_0104__li1799418920148"><strong id="functiongraph_04_0104__b1762714115267">ENTRYPOINT</strong>: Run the <strong id="functiongraph_04_0104__b156281511261">node /home/tester/main.js</strong> command to start the container.</li></ul>
|
|
<div class="note" id="functiongraph_04_0104__note17244712135519"><img src="public_sys-resources/note_3.0-en-us.png"><span class="notetitle"> </span><div class="notebody"><ol type="a" id="functiongraph_04_0104__ol16166128155510"><li id="functiongraph_04_0104__li18166162811556">You can use any base image.</li><li id="functiongraph_04_0104__li191661328155510">In the cloud environment, UID 1003 and GID 1003 are used to start the container by default. The two IDs can be modified by choosing <strong id="functiongraph_04_0104__b1353042722612">Configuration</strong> > <strong id="functiongraph_04_0104__b135301127192615">Basic Settings</strong> > <strong id="functiongraph_04_0104__b2530192712266">Container Image Override</strong> on the function details page. They cannot be <strong id="functiongraph_04_0104__b653011271269">root</strong> or a reserved ID.</li></ol>
|
|
</div></div>
|
|
</li></ol><ol start="5" id="functiongraph_04_0104__ol12590173254310"><li id="functiongraph_04_0104__li65901932114317">Build an image.<p id="functiongraph_04_0104__p8688195019499"><a name="functiongraph_04_0104__li65901932114317"></a><a name="li65901932114317"></a>In the following example, the image name is <strong id="functiongraph_04_0104__b051184212266">custom_container_event_example</strong>, the tag is <strong id="functiongraph_04_0104__b165294222611">latest</strong>, and the period (.) indicates the directory where the Dockerfile is located. Run the image build command to pack all files in the directory and send the package to a container engine to build an image.</p>
|
|
<pre class="screen" id="functiongraph_04_0104__screen1356617348547">docker build -t custom_container_event_example:latest .</pre>
|
|
</li></ol>
|
|
<div class="section" id="functiongraph_04_0104__section14706131145612"><h4 class="sectiontitle">Step 3: Perform Local Verification</h4><ol id="functiongraph_04_0104__ol15219131615717"><li id="functiongraph_04_0104__li19219171614578">Start the Docker container.<pre class="screen" id="functiongraph_04_0104__screen32034014570">docker run -u 1003:1003 -p 8000:8000 custom_container_event_example:latest</pre>
|
|
</li></ol><ol start="2" id="functiongraph_04_0104__ol3221850579"><li id="functiongraph_04_0104__li32212511577">Open a new Command Prompt, and send a message through port 8000 to access the <strong id="functiongraph_04_0104__b2828124173020">/init</strong> directory specified in the template code.<pre class="screen" id="functiongraph_04_0104__screen207121444175712">curl -XPOST -H 'Content-Type: application/json' localhost:8000/init</pre>
|
|
<p id="functiongraph_04_0104__p11235659183714">The following information is returned based on the module code:</p>
|
|
<pre class="screen" id="functiongraph_04_0104__screen1265281710582">Hello init</pre>
|
|
</li></ol><ol start="3" id="functiongraph_04_0104__ol22512286217"><li id="functiongraph_04_0104__li15251132812117">Open a new Command Prompt, and send a message through port 8000 to access the <strong id="functiongraph_04_0104__b811172233012">/invoke</strong> directory specified in the template code.<pre class="screen" id="functiongraph_04_0104__screen124071828202015">curl -XPOST -H 'Content-Type: application/json' -d '{"message":"HelloWorld"}' localhost:8000/invoke</pre>
|
|
<p id="functiongraph_04_0104__p20629115182118">The following information is returned based on the module code:</p>
|
|
<pre class="screen" id="functiongraph_04_0104__screen186297572112">Hello invoke</pre>
|
|
</li></ol><ol start="4" id="functiongraph_04_0104__ol9502356212"><li id="functiongraph_04_0104__li191694822117">Check whether the following information is displayed:<pre class="screen" id="functiongraph_04_0104__screen671035515211">Listening on http://localhost:8000
|
|
receive {}
|
|
receive { message: 'HelloWorld' }</pre>
|
|
<p id="functiongraph_04_0104__p1969310287228"><span><img id="functiongraph_04_0104__image196921228112216" src="en-us_image_0000001472598601.png"></span></p>
|
|
<p id="functiongraph_04_0104__p15809135251513">Alternatively, run the <strong id="functiongraph_04_0104__b72862116733928">docker logs</strong> command to obtain container logs.</p>
|
|
<p id="functiongraph_04_0104__p2281115163"><span><img id="functiongraph_04_0104__image191981812181620" src="en-us_image_0000001472598777.png"></span></p>
|
|
</li></ol>
|
|
</div>
|
|
<div class="section" id="functiongraph_04_0104__section15137197135915"><h4 class="sectiontitle">Step 4: Upload the Image</h4><ol id="functiongraph_04_0104__ol10526155517598"><li id="functiongraph_04_0104__li1280144911552">Log in to the SWR console. In the navigation pane, choose <strong id="functiongraph_04_0104__b13947731193020">My Images</strong>.</li><li id="functiongraph_04_0104__li19526145511590">Click <strong id="functiongraph_04_0104__b1692611332300">Upload Through Client</strong> or <strong id="functiongraph_04_0104__b15926633133010">Upload Through SWR</strong> in the upper right corner.</li><li id="functiongraph_04_0104__li1169192171917">Upload the image as prompted.<p id="functiongraph_04_0104__p87902033161813"><a name="functiongraph_04_0104__li1169192171917"></a><a name="li1169192171917"></a></p>
|
|
<p id="functiongraph_04_0104__p114152117338"><span><img id="functiongraph_04_0104__image9415611113316" src="en-us_image_0000001630990134.png"></span></p>
|
|
</li><li id="functiongraph_04_0104__li823013951820">View the image on the <strong id="functiongraph_04_0104__b14941115153019">My Images</strong> page.</li></ol>
|
|
</div>
|
|
<div class="section" id="functiongraph_04_0104__section12330203912578"><h4 class="sectiontitle">Step 5: Create a Function</h4><ol id="functiongraph_04_0104__ol18740710529"><li id="functiongraph_04_0104__li7794535128">In the left navigation pane of the management console, choose <strong id="functiongraph_04_0104__b192576044995558">Compute</strong> > <strong id="functiongraph_04_0104__b178015406995558">FunctionGraph</strong>. On the FunctionGraph console, choose <strong id="functiongraph_04_0104__b12977753429565">Functions</strong> > <strong id="functiongraph_04_0104__b6862851479565">Function List</strong> from the navigation pane.</li><li id="functiongraph_04_0104__li27941371211">Click <strong id="functiongraph_04_0104__b4211204311">Create Function</strong> in the upper right corner and choose <strong id="functiongraph_04_0104__b192121005311">Container Image</strong>.</li><li id="functiongraph_04_0104__li1176013361624">Set the basic information.<ul id="functiongraph_04_0104__ul1714016229416"><li id="functiongraph_04_0104__li9143162215418"><strong id="functiongraph_04_0104__b42722483111">Function Type</strong>: Select <strong id="functiongraph_04_0104__b142722423112">Event Function</strong>.</li><li id="functiongraph_04_0104__li5121204615412"><strong id="functiongraph_04_0104__b1762711610316">Function Name</strong>: Enter <strong id="functiongraph_04_0104__b126276633115">custom_container_event</strong>.</li><li id="functiongraph_04_0104__li11250348182118"><strong id="functiongraph_04_0104__b7121191513116">Container Image</strong>: Enter the image uploaded to SWR. </li><li id="functiongraph_04_0104__li39981317382"><strong id="functiongraph_04_0104__b77311091413">Agency</strong>: Select an agency with the <strong id="functiongraph_04_0104__b1282141317412">SWR Admin</strong> permission. If no agency is available, create one by referring to section "Creating an Agency".</li></ul>
|
|
</li><li id="functiongraph_04_0104__li1416383714911">After the configuration is complete, click <strong id="functiongraph_04_0104__b10629132853113">Create Function</strong>.</li><li id="functiongraph_04_0104__li10240122622416">On the function details page, choose <strong id="functiongraph_04_0104__b1758141715325">Configuration</strong> > <strong id="functiongraph_04_0104__b10200921173217">Advanced Settings</strong>, and enable <strong id="functiongraph_04_0104__b5186183113324">Initialization</strong>. The <strong id="functiongraph_04_0104__b1068916486321">init</strong> API will be called to initialize the function.</li></ol>
|
|
</div>
|
|
<div class="section" id="functiongraph_04_0104__section623165141019"><h4 class="sectiontitle">Step 6: Test the Function</h4><ol id="functiongraph_04_0104__ol138801929154513"><li id="functiongraph_04_0104__li118801429194518">On the function details page, click <strong id="functiongraph_04_0104__b8564826193320">Test</strong>. In the displayed dialog box, create a test event.</li><li id="functiongraph_04_0104__li1355343014466">Select <strong id="functiongraph_04_0104__b1628082933310">blank-template</strong>, set <strong id="functiongraph_04_0104__b6280162943315">Event Name</strong> to <strong id="functiongraph_04_0104__b16280129113313">helloworld</strong>, modify the test event as follows, and click <strong id="functiongraph_04_0104__b728182915334">Create</strong>.<pre class="screen" id="functiongraph_04_0104__screen4222153532514">{
|
|
"message": "HelloWorld"
|
|
}</pre>
|
|
</li></ol>
|
|
</div>
|
|
<div class="section" id="functiongraph_04_0104__section109701256191214"><h4 class="sectiontitle">Step 7: View the Execution Result</h4><p id="functiongraph_04_0104__p852616631310">Click <strong id="functiongraph_04_0104__b1163404011330">Test</strong> and view the execution result on the right.</p>
|
|
<div class="fignone" id="functiongraph_04_0104__fig19835131516462"><span class="figcap"><b>Figure 1 </b>Execution result</span><br><span><img id="functiongraph_04_0104__image18836191584614" src="en-us_image_0000001422840354.png"></span></div>
|
|
<ul id="functiongraph_04_0104__ul1714875285210"><li id="functiongraph_04_0104__li20148952105216"><strong id="functiongraph_04_0104__b69861346133320">Function Output</strong>: displays the return result of the function.</li><li id="functiongraph_04_0104__li1659264116539"><strong id="functiongraph_04_0104__b21755118333">Log Output</strong>: displays the execution logs of the function.</li><li id="functiongraph_04_0104__li1014811523528"><strong id="functiongraph_04_0104__b8331854173313">Summary</strong>: displays key information of the logs.<div class="note" id="functiongraph_04_0104__note153221935131416"><img src="public_sys-resources/note_3.0-en-us.png"><span class="notetitle"> </span><div class="notebody"><p id="functiongraph_04_0104__functiongraph_04_0101_p1235012235414">A maximum of 2 KB logs can be displayed. For more log information, see section "Querying Function Logs".</p>
|
|
</div></div>
|
|
</li></ul>
|
|
</div>
|
|
<div class="section" id="functiongraph_04_0104__section0486613514"><h4 class="sectiontitle">Step 8: View Monitoring Metrics</h4><p id="functiongraph_04_0104__p17904185720618">On the function details page, click the <strong id="functiongraph_04_0104__functiongraph_04_0101_b1337097146">Monitoring</strong> tab.</p>
|
|
<ul id="functiongraph_04_0104__ul514673445811"><li id="functiongraph_04_0104__functiongraph_04_0101_li1814673415587">On the <strong id="functiongraph_04_0104__functiongraph_04_0101_b152431737165312">Monitoring</strong> tab page, choose <strong id="functiongraph_04_0104__functiongraph_04_0101_b17548418101316">Metrics</strong>, and select a time range (such as 5 minutes, 15 minutes, or 1 hour) to query the function.</li><li id="functiongraph_04_0104__functiongraph_04_0101_li88981734907">The following metrics are displayed: invocations, errors, duration (including the maximum, average, and minimum durations), and throttles.</li></ul>
|
|
</div>
|
|
<div class="section" id="functiongraph_04_0104__section5661458145412"><h4 class="sectiontitle">Step 9: Delete the Function</h4><ol id="functiongraph_04_0104__ol07481824023"><li id="functiongraph_04_0104__functiongraph_04_0101_li197481224129">On the function details page, choose <strong id="functiongraph_04_0104__functiongraph_04_0101_b6137103021213">Operation</strong> > <strong id="functiongraph_04_0104__functiongraph_04_0101_b12443175210478">Delete Function</strong> in the upper right corner.</li><li id="functiongraph_04_0104__functiongraph_04_0101_li0745531425">In the confirmation dialog box, enter <strong id="functiongraph_04_0104__functiongraph_04_0101_b3374104583013">DELETE</strong> and click <strong id="functiongraph_04_0104__functiongraph_04_0101_b179661748143013">OK</strong> to release resources in a timely manner.</li></ol>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="familylinks">
|
|
<div class="parentlink"><strong>Parent topic:</strong> <a href="functiongraph_04_0105.html">Deploying a Function Using a Container Image</a></div>
|
|
</div>
|
|
</div>
|
|
|