整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          SemanticKernel之使用結構化Prompt

          之前說過結構化Prompt,這是一個具體案例的使用,本例是把公眾號上中文技術文章翻譯成選擇的語言。

          基本思路是用戶輸入文章的url,系統(tǒng)用Playwright讀取html內容,然后利用SemanticKernel的OpenAIChatCompletionService功能,按照提示詞翻譯,最后用Playwright把結果發(fā)送到Qiit(一個日本技術博客網站)上。

          結構化的提示詞如下:

          • # Role: 軟件技術翻譯專家
            ## Profile:### Author: gsw### Version: 2.0### Language: {{language}}### Description: 我是一個專門把中文技術文章翻譯成Language指定的技術文章的AI 角色。
            ## Goals: 能準確地把中文技術文章翻譯成Language指定技術文章。
            ## Constrains:1. 把html轉成markdown輸出,在輸出時,請注意要翻譯成Language指定的語言2. 把代碼放在專有的代碼塊標識中,如果分析不出是什么類型的代碼,就以 C# 代碼塊進行標識4. 你不會在翻譯時添加自己的看法,只是原文翻譯5. 翻譯完后, 不會詢問是否有其它問題6. 注意html中的圖片(img)標簽,要轉成markdown的形式同時給出7. 保持原文輸出,請全部翻譯輸出,請全部翻譯輸出,請全部翻譯輸出8. 在翻譯完成后,最后一行添加“(Translated by GPT)”字樣
            ## Skills:1. 具有強大的軟件技術知識獲取和整合能力2. 擁有廣泛的編程語言知識庫, 掌握提問和回答的技巧3. 擁有排版審美, 會利用序號, 縮進, 分隔線和換行符等等來美化信息排版4. 擅長使用比喻的方式來讓用戶理解知識5. 充分利用markdown語法來排版
            ## Workflows: 1. 讓用戶以 "標題:[]" 的方式指定需要翻譯的標題。2. 讓用戶以 "內容:[]" 的方式指定需要翻譯的內容。3. 針對用戶給定的標題和內容進行翻譯,不要帶“標題:”和“內容:”字樣,第一行是標題,第二行以后是內容。
            ## Initialization作為角色 <Role>,你擁有 <Skills>,嚴格遵守 <Constrains>,使用默認 <Language> ,按照 <Workflows>輸出結果。

            原來提示詞是把網頁文字取出來,進行翻譯,圖片進行了特殊處理,像表格之類的格式就會丟掉,后來作了一下優(yōu)化,讓GPT直接把html轉成markdown,這樣即使有特列的html表示,也能轉成相對友好的markdown格式。

            具體C#代碼實現如下:

            • using Microsoft.Playwright;using Microsoft.SemanticKernel.ChatCompletion;using Microsoft.SemanticKernel.Connectors.OpenAI;using System.Text.RegularExpressions;using System.Text;
              namespace TranslateAgent{ public partial class MainForm : Form { public MainForm() { InitializeComponent(); }
              private void MainForm_Load(object sender, EventArgs e) { var lans = new List<string> { "日語","英語","法語","德語","韓語" }; LanComBox.DataSource = lans; }
              (string title, string content) SplitArticle(string article) { if (!string.IsOrWhiteSpace(article)) { var reader = new StringReader(article); var title = reader.ReadLine(); var content = reader.ReadToEnd(); return (title, content); } throw new Exception("文章為空!"); }
              async Task<bool> PublishArticleAsync(string translatorContent) { var (title, content) = SplitArticle(translatorContent); var url = ""; this.Invoke(() => { url = UrlTextBox.Text; }); if (!string.IsOrWhiteSpace(url)) { content += $"\r\n元のリンク:{url}"; } using var playwright = await Playwright.CreateAsync(); await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = false, Args = ["--start-maximized"] });
              var page = await browser.NewPageAsync(); await page.GotoAsync("https://qiita.com/");
              await page.ClickAsync("a[href='/login?callback_action=login_or_signup&redirect_to=%2F&realm=qiita']"); var userArr = File.ReadAllLines("C:/gpt/qiita_user.txt"); await page.FillAsync("#identity", userArr[0]); await page.FillAsync("#password", userArr[1]); await page.ClickAsync("input[name='commit']"); await page.GotoAsync("https://qiita.com/drafts/new"); await page.FillAsync("input[placeholder='記事タイトル']", title); await page.FillAsync("input[placeholder='タグを入力してください。スペース區(qū)切りで5つまで入力できます。']", "C# .NET"); await page.FillAsync("div[role='textbox']", content); MessageBox.Show("請確認發(fā)表內容,并且手動在彈出的內核瀏覽器中發(fā)布!請注意,點擊確定后會自動關閉內核瀏覽器!!!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
              return true; } async Task<(string Title, string Content)> GetArticleAsync(string url) { using var playwright = await Playwright.CreateAsync(); await using var browser = await playwright.Chromium.LaunchAsync(/*new BrowserTypeLaunchOptions { Headless = false }*/); var page = await browser.NewPageAsync(); await page.GotoAsync(url); var title = await page.Locator("#activity-name").InnerTextAsync(); var locator = page.Locator("#js_content"); var images = await locator.GetByRole(AriaRole.Img).ElementHandlesAsync(); var imageList = new List<string>(); foreach (var image in images) { var imgUrl = await image.GetAttributeAsync("data-src"); imageList.Add(imgUrl); } var html = await locator.InnerHTMLAsync(); var imgTagPattern = @"<img[^>]*>"; html = Regex.Replace(html, imgTagPattern, "[圖片]"); await page.SetContentAsync("<div id='js_content'>" + html + "</div>"); var content = await page.Locator("#js_content").InnerTextAsync(); var reader = new StringReader(content); var index = 0; var contentBuilder = new StringBuilder(); while (true) { var line = await reader.ReadLineAsync(); if (!string.IsOrWhiteSpace(line.Trim())) { if (line.Trim() == "[圖片]") { contentBuilder.AppendLine($"![alt 圖片]({imageList[index]})"); index++; } else { contentBuilder.AppendLine(line); } } if (reader.Peek() <= 0) { break; } } return (title, contentBuilder.ToString()); }
              async Task<string> OpenAIChatSampleAsync(string title, string content) { var key = File.ReadAllText(@"C:\GPT\key.txt"); var chatModelId = "gpt-4-0125-preview"; OpenAIChatCompletionService chatCompletionService = new(chatModelId, key); return await StartChatAsync(chatCompletionService, title, content); }
              async Task<string> StartChatAsync(IChatCompletionService chatGPT, string title, string content) { var lan = "日文"; this.Invoke(() => { lan = LanComBox.Text; }); var prompt = File.ReadAllText(Environment.CurrentDirectory + "/Prompt.md"); prompt = prompt.Replace("{{language}}", lan); var chatHistory = new ChatHistory(prompt); var userContent = $"標題:{title}\r\n內容:{content}"; chatHistory.AddUserMessage(userContent); return await MessageStreamOutputAsync(chatGPT, chatHistory); }
              async Task<string> MessageStreamOutputAsync(IChatCompletionService chatGPT, ChatHistory chatHistory) { var list = chatGPT.GetStreamingChatMessageContentsAsync(chatHistory);

              var fullMessage = string.Empty; await foreach (var item in list) { if (item == ) { continue; } fullMessage += item.Content; this.Invoke(() => { TranslationTextBox.AppendText(item.Content); }); } return fullMessage; }
              private void TranButton_Click(object sender, EventArgs e) {
              try { var url = UrlTextBox.Text; if (string.IsOrWhiteSpace(url)) { MessageBox.Show("輸入的url有誤,請重新輸入!", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } var pattern = @"^(https?:\/\/)?(?s).*$"; var regex = new Regex(pattern, RegexOptions.IgnoreCase); bool isValid = regex.IsMatch(url); if (!isValid) { MessageBox.Show("輸入的url有誤,請重新輸入!", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } else { Task.Run(() => { try { var (title, content) = GetArticleAsync(url).Result; this.Invoke(() => { OriginalTextBox.Lines = new string[] { title, content };
              });
              var translatorContent = OpenAIChatSampleAsync(title, content).Result;
              var result = PublishArticleAsync(translatorContent).Result; if (!result) { MessageBox.Show("翻譯失敗!", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error); } } catch (Exception exc) { MessageBox.Show(exc.Message, "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error); } }); } }
              catch (Exception ex) { MessageBox.Show(ex.Message, "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
              private void LanComBox_SelectedIndexChanged(object sender, EventArgs e) { this.Text = "中文->" + LanComBox.Text; }
              private void ClearButton_Click(object sender, EventArgs e) { UrlTextBox.Clear(); OriginalTextBox.Clear(); TranslationTextBox.Clear(); } }}

              運行結果一:

              運行結果二:

          國長安網北京8月1日電(郭莎莎)公安部今天在京發(fā)布,公安部“互聯(lián)網+政務服務”平合正式上線,實現全國一次認證、一網通辦。

          公安部科技信息化局局長厲劍通報,公安部“互聯(lián)網+政務服務”平臺今天正式上線,網址為https://zwfw.mps.gov.cn/。普通網友均可登錄使用。平臺已對接貫通國家政務服務平臺,統(tǒng)一了用戶體系,解決了企業(yè)和群眾在公安平臺和政府平臺重復注冊、多次驗證等問題,實現了一次認證、單點登錄、全網通辦。

          “平臺的上線,是公安機關為民服務的又一創(chuàng)新成果,也標志著全國公安政務服務工作水平邁上了一個新臺階。”厲劍說。

          他介紹,“互聯(lián)網+公安政務服務”是公安機關在深入調研、充分聽取企業(yè)、群眾和民警意見的基礎上,敢于刀刃向內,打破數據和系統(tǒng)壁壘,運用互聯(lián)網思維,通過數據共享和業(yè)務流程再造,減少警種部門之間和上下級公安機關之間審批流轉的中間環(huán)節(jié),最大程度地簡化群眾辦事流程,促進服務審批工作更加高效,讓企業(yè)、群眾充分得到公安“放管服”改革的紅利和實惠,同時也釋放出更多的警力從事治安防范、打擊犯罪等其他公安業(yè)務工作。

          公安部科信委專職副主任劉明芳介紹,公安部的平臺綜合集成了各層級公安機關和公安部各警種、各部門的網上辦事系統(tǒng),形成了集中的辦事中心、查詢中心、評價中心,主要有以下三個特色:

          一是統(tǒng)一應用支撐。平臺建設了統(tǒng)一身份認證、統(tǒng)一事項管理、統(tǒng)一數據交換、統(tǒng)一評價服務等基礎支撐功能,為各地公安機關網上政務服務平臺提供共性應用支撐,各地平臺可在此基礎上,開發(fā)符合本地實際的個性化應用。

          二是四級業(yè)務聯(lián)動。平臺強化協(xié)同聯(lián)動,將原來分布在部、省、市、縣四級公安機關的網上辦事平臺與公安部“互聯(lián)網+政務服務”平臺逐級對接貫通,將四級公安機關網上政務服務的數據流、業(yè)務流、管理流有效融合,建立了網上政務服務動態(tài)更新機制,確保公安政務服務事項的源頭一致,更新同步,服務同頻,實現群眾辦理公安政務服務事項只進一張網、不用多頭跑。

          三是身份雙源認證。以全國人口信息和居民身份證辦理信息作為網上身份信息核驗的兩大權威數據源,支撐全國一體化在線政務服務平臺用戶身份信息的實人、實名、實證的在線核驗,有效解決了網上政務服務“我就是我”、“是我在辦”的難題。

          記者從發(fā)布會獲悉,各級公安機關緊貼群眾需求,勇于推陳出新,不斷增強“互聯(lián)網+公安政務服務”工作的創(chuàng)新活力。通過網站、APP、公眾號、小程序,將服務的入口從線下移到線上;通過在線申請、網上受理、遠程寄遞等多種方式,有效打通了網上服務的“最后一公里”通過刷臉認證、一鍵挪車等便捷應用,將服務的觸角延伸至各個角落。

          陜西作為全國首批4個試點對接公安部“互聯(lián)網+平臺”的省份,率先建成陜西“互聯(lián)網+公安政務服務”平臺并正式上線運行。在平臺建設應用推廣中,結合地方特色,重點從優(yōu)化辦事流程、打通關鍵環(huán)節(jié)、完善平臺問題三方面來打通網上辦事的“最后一公里”。廣東省公安機關按照有關要求,打造了既支持內地居民也服務港澳居民注冊和使用的“智慧新民生”平臺,并且實現了和公安部“互聯(lián)網+政務服務”平臺的全面對接。目前,可面向港澳居民在線辦理的有粵港澳直通車、警務非稅收入繳款兩方面業(yè)務。

          公安部“互聯(lián)網+政務服務”平臺目前已匯聚服務事項548項,為群眾提供了公安服務事項的辦理、查詢、評價一站式服務,打造了“一大平合全網貫通、雙源數據全面支撐、四級聯(lián)動全警應用、多種措施全力防護”的應用體系。

          厲劍提及,信息安全與服務同樣重要。通過將技術防護和安全管理的有效結合,著力構建全方位、多層次的縱深安全防護體系,確保公安部“互聯(lián)網+政務服務”平臺的系統(tǒng)安全和數據安全。

          在技術上,該平臺采取五方面的措施:

          一是邀請信息安全方面的專家和相關專業(yè)力量,制定了“云+端”的安全技術方案。二是采用安全網關、防火墻、入侵防護、堡壘機等各種安全加固措施抵御外部的攻擊,保障平臺信息安全。三是建設安全風險發(fā)現預警功能,出現安全漏洞時及時預警,并能阻斷數據外泄。四是利用國產加密算法、身份鑒權等相關技術,保障接口安全及數據的加密傳輸和存儲安全。目前已經通過密碼應用安全方面的測評。五是嚴格對照信息系統(tǒng)等級保護相關要求,配置相應的安全防護設備和防護手段。目前,已經通過了等保三級相關測評。

          在管理上,該平臺采取了三個方面的安保措施。一是制定統(tǒng)一的安全管理規(guī)定,明確各級公安機關負責的網上辦理事項網站相關的主體責任,建立了上下聯(lián)動相關機制,確保公安機關一體化政務平臺整體安全。二是定期對平臺進行攻防演練,發(fā)現漏洞及時修補。三是建立安全事故應急預案,一旦發(fā)生安全事故后,確保能夠快速響應,并及時地修復。

          發(fā)布會公布,下一步,公安部將進一步整合全國公安機關的相關資源,優(yōu)化流程、完善機制,不斷豐富公安部“互聯(lián)網+政務服務”平合功能,結合公安行業(yè)特點,聚焦“一網通辦,便民惠警”目標,加強應用創(chuàng)新,推進線上線下深度融合,推動公安政務服務整體聯(lián)動全程在線,不斷擴大公安“放管服”改革的受益群體,確保讓廣大人民群眾有更多、更直接、更實在的獲得感。

          EventBridge 作為構建 EDA 架構的基礎設施,通過一些核心概念和特性提供了靈活豐富的事件收集、處理和路由的能力。對于不少用戶來說,通過控制臺里的便捷的引導來使用 EventBridge 應該是最快的上手方式。此外,也有很多用戶面臨著大量的云產品的管理,使用控制臺管理每一個資源的方式變成了沉重的手工操作負擔。

          為了解決這個問題,現在已經能夠通過 OpenAPI、terraform 等方式將 EventBridge 的能力方便快捷的帶給用戶。本文將重點介紹 EventBridge 和 IaC 的重點概念和特性,然后演示如何應用 IaC 理念自動化部署 EventBridge 來使用這些概念和特性。

          EventBridge 概述

          事件驅動架構

          事件驅動架構是一種松耦合、分布式的驅動架構,收集到某應用產生的事件后實時對事件采取必要的處理,緊接著路由至下游系統(tǒng),無需等待系統(tǒng)響應。使用事件總線 EventBridge 可以構建各種簡單或復雜的事件驅動架構,以標準化的 CloudEvents 1.0 協(xié)議連接云產品和應用、應用和應用等。

          事件驅動架構體系架構具備以下三個能力:

          • 事件收集:負責收集各種應用發(fā)生的事件,如新建訂單,退換貨訂單等其他狀態(tài)變更;
          • 事件處理:對事件進行脫敏處理,并對事件進行初步的過濾和篩選;
          • 事件路由:分析事件內容并將事件路由分發(fā)至下游產品。

          事件驅動架構具有以下優(yōu)勢:

          • 降低耦合:降低事件生產者和訂閱者的耦合性。事件生產者只需關注事件的發(fā)生,無需關注事件如何處理以及被分發(fā)給哪些訂閱者;任何一個環(huán)節(jié)出現故障,都不會影響其他業(yè)務正常運行;
          • 異步執(zhí)行:事件驅動架構適用于異步場景,即便是需求高峰期,收集各種來源的事件后保留在事件總線中,然后逐步分發(fā)傳遞事件,不會造成系統(tǒng)擁塞或資源過剩的情況;
          • 可擴展性:事件驅動架構中路由和過濾能力支持劃分服務,便于擴展和路由分發(fā);
          • 敏捷性:事件驅動架構支持與各種阿里云產品和應用集成,支持事件路由至任何系統(tǒng)服務,提供各種敏捷高效的部署方案。

          使用 EventBridge 構建 EDA 架構

          事件總線 EventBridge 是阿里云提供的一款無服務器事件總線服務。EventBridge 提供的幾個核心概念,可以滿足構建 EDA 架構的需要。

          事件總線 EventBridge 支持以下事件源:

          • 阿里云官方事件源
          • 自定義事件源

          事件總線 EventBridge 的事件總線包括以下類型:

          • 云服務專用事件總線:一個無需創(chuàng)建且不可修改的內置事件總線,用于接收您的阿里云官方事件源的事件;阿里云官方事件源的事件只能發(fā)布到云服務專用總線;
          • 自定義事件總線:需要您自行創(chuàng)建并管理的事件總線,用于接收自定義應用或存量消息數據的事件;自定義應用或存量消息數據的事件只能發(fā)布到自定義總線。

          在 EventBridge 中,一個事件規(guī)則包含以下內容:

          • 事件模式:用于過濾事件并將事件路由到事件目標;
          • 事件目標:包括事件的轉換和處理,負責消費事件。

          EventBridge 提供了簡潔的事件模式匹配語法,同時具備靈活的事件轉換能力,后面將會通過演示來展示一些具體的例子。

          此外,EventBridge 還提供了一些增強能力,這些能力使得 EDA 架構中流經的事件更加透明,具備了開箱即用的觀測和分析能力:

          • 事件追蹤:可以查看發(fā)布到事件總線 EventBridge 的事件內容和處理軌跡;
          • 事件分析:對發(fā)布到事件總線的各種事件進行查詢分析處理和可視化圖表展示,以便發(fā)現事件內在價值。

          IaC 簡介

          在介紹完事件總線 EventBridge 的相關基礎內容后,接下來一起了解下 IaC。在 DevOps 的實踐中,IaC 是非常重要的部分,通過將基礎設施代碼化,版本化,便可以輕松的借助版本控制工具來提供 single source of truth、協(xié)調多人合作的變更、實施嚴格的 review、借助一些 CI/CD pipeline 工具(甚至 GitOps)來自動觸發(fā)部署。軟件系統(tǒng)的開發(fā)者僅付出很小的努力去描述需求,就可以在幾分鐘后得到所需的虛擬機、網絡等云上的服務,極大的縮短了部署時間,同時還能夠保證多個環(huán)境的配置一致性,通過減少人為操作也降低了引入錯誤的概率。

          IaC的代碼實踐中一般有兩種方式,命令式和聲明式。

          • 命令式:顧名思義,需要明確發(fā)出每一個動作的指令,描述的是 How,比如“創(chuàng)建一臺 xx 規(guī)格的 ECS”。代碼需要對每一步動作的順序仔細編排,處理各種可能的錯誤,尤其要注意處理好每次變更對已經存在的資源的影響,否則稍有不慎就可能造成服務中斷。舉例來說,作為開發(fā)者可以通過自己熟悉的編程語言調用阿里云的 OpenAPI 來管理資源,因為這些 API 是類似 Create、Describe、Delete 等操作,這就是一種命令式的 IaC 實踐。
          • 聲明式:意味著開發(fā)者僅描述自己的需求終態(tài)是什么樣子,即描述 What,比如“一臺 xx 規(guī)格的 ECS”。熟悉 Kubernetes 的同學應該對這個概念很熟悉了。IaC 工具可以通過描述資源之間的依賴關系自動編排順序,如果有已經存在的資源,則比對期望的狀態(tài)和實際狀態(tài)的差異,并根據差異做出更新;如果不存在,需要進行創(chuàng)建。可以看出,聲明式對開發(fā)者非常友好,極大的降低了開發(fā)者的心智負擔。

          IaC 帶來的優(yōu)勢:

          • 降低成本:有效管理資源,并減少為此投入的人力;
          • 提升效率:加快資源交付和軟件部署的速度;
          • 風險控制:
            • 減少錯誤;
            • 提高基礎架構一致性;
            • 消除配置偏移

          terraform 作為 IaC 領域的佼佼者,提供了強大的自動化管理基礎設施的能力。生態(tài)豐富,很多云廠商都提供了官方插件,阿里云的大多數產品(包括 EventBridge)都對 terraform 做了很全面的支持,使得跨多云部署基礎設施變得極其簡單。既然是 IaC,terraform 提供了自己的語言 HCL(hashicorp configuration language),HCL 具有類似 json 的簡潔的語法,通過聲明式的資源描述,可以讓開發(fā)者快速上手。

          動手實踐

          準備工作

          • 安裝 terraform cli 工具,可以參見 https://www.terraform.io/cli 的內容。
          • 創(chuàng)建一個 tf 文件 terraform.tf,內容如下(需要替換<>內的值)
          provider "alicloud" {
            access_key = "<your access key>"
            secret_key = "<your secret key>"
            region = "<region id>"
          }
          

          案例1:通過釘釘監(jiān)控云上資源變化

          假設一個用戶使用了很多云上的資源作為生產環(huán)境,需要感知線上資源的變更操作,一個可行的方案是利用 EventBridge 將來自于 ActionTrail 的審計事件投遞到用戶的釘釘。

          首先根據釘釘官方文檔創(chuàng)建一個機器人,記下 webhook url 和加簽的秘鑰,接下來會用到。

          創(chuàng)建一個 tf 文件 1_actiontrail2dingding.tf,內容如下(需要替換<>內的值)

          
          # 案例1:通過釘釘監(jiān)控云上資源變化
          # 目標:
          # - 熟悉部署使用EventBridge的default總線
          # - 熟悉EventBridge的事件模式匹配
          # - 熟悉EventBridge的事件轉換配置
          
          # 聲明一個default總線上的規(guī)則
          resource "alicloud_event_bridge_rule" "audit_notify" {
            # default總線默認存在,所以這里可以直接使用
            event_bus_name = "default"
            rule_name      = "audit_notify"
            description    = "demo"
            # 通過后綴匹配的方式過濾來自所有云產品事件源的ActionTrail:ApiCall事件
            # 其他更多模式匹配的介紹可以查閱文檔:https://help.aliyun.com/document_detail/181432.html
            filter_pattern = jsonencode(
              {
                "type" : [
                  {
                    "suffix" : ":ActionTrail:ApiCall"
                  }
                ]
              }
            )
          
            targets {
              target_id = "test-target"
              endpoint  = "<your dingtalk bot webhook url>"
              # type的取值可以查閱文檔:https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/event_bridge_rule#type
              type      = "acs.dingtalk"
              # 每個事件目標都有一組對應的param_list,具體可以查閱文檔:https://help.aliyun.com/document_detail/185887.html
              # 每一個param的form關系到事件轉換的配置,可以查閱文檔:https://help.aliyun.com/document_detail/181429.html
              param_list {
                resource_key = "URL"
                form         = "CONSTANT"
                value        = "<your dingtalk bot webhook url>"
              }
              param_list {
                resource_key = "SecretKey"
                form         = "CONSTANT"
                value        = "<your dingtalk bot secret key>"
              }
              # 這里展示了TEMPLATE類型的事件轉換描述
              # value是使用jsonpath引用事件內容的字典,template則是模板內容,EventBridge最終會根據這兩者結合事件本身渲染出這個參數的值
              param_list {
                resource_key = "Body"
                form         = "TEMPLATE"
                value        = jsonencode(
                  {
                    "source": "$.source",
                    "type": "$.type"
                    "region": "$.data.acsRegion",
                    "accountId" : "$.data.userIdentity.accountId",
                    "eventName" : "$.data.eventName",
                  }
                )
                template = jsonencode(
                  {
                    "msgtype" : "text",
                    "text" : {
                      "content": "來自 $${source} 的 $${type} 審計事件:$${accountId} 在 $${region} 執(zhí)行了 $${eventName} 操作"
                    }
                  }
                )
              }
            }
          }
          

          在命令行窗口依次執(zhí)行命令:

          • 初始化 terraform init
          • 預覽變更 terraform plan
          • 應用變更 terraform apply

          在云產品控制臺進行操作,這里以 KMS 為例

          釘釘上收到消息通知

          在 EventBridge 控制臺查看事件軌跡

          案例 2:自定義總線觸發(fā) FunctionCompute

          假設一個用戶的應用會產生一些事件,其中一個鏈路是通過 FunctionCompute 對這些事件進行彈性的處理。那么就可以通過 EventBridge 的自定義事件源和函數計算事件目標來實現這個方案。

          創(chuàng)建一個模擬對事件進行處理的 python 腳本文件 src/index.py,內容如下:

          # -*- coding: utf-8 -*-
          import logging
          
          def handler(event, context):
            logger = logging.getLogger()
            logger.info('evt: ' + str(event))
            return str(event)
            

          創(chuàng)建一個 tf 文件 2_trigger_function.tf,內容如下(需要替換<>內的值)

          # 案例2:自定義總線觸發(fā)FunctionCompute
          # 目標:
          # - 熟悉部署使用EventBridge的自定義總線
          # - 熟悉"自定義應用"事件源配置
          # - 熟悉“FunctionCompute”事件目標配置
          
          
          # 由于用戶自己產生的事件需要投遞到自定義總線,這里聲明一個叫demo_event_bus的自定義總線
          resource "alicloud_event_bridge_event_bus" "demo_event_bus" {
            event_bus_name = "demo_event_bus"
            description    = "demo"
          }
          
          # 聲明一個在demo_event_bus總線上的自定義事件源,用于通過sdk或者控制臺向EventBridge投遞事件
          resource "alicloud_event_bridge_event_source" "demo_event_source" {
            event_bus_name         = alicloud_event_bridge_event_bus.demo_event_bus.event_bus_name
            event_source_name      = "demo_event_source"
            description            = "demo"
            linked_external_source = false
          }
          
          # 聲明一個叫fc_service的函數計算服務,publish=true意味著會立即部署上傳的函數代碼。
          resource "alicloud_fc_service" "fc_service" {
            name        = "eb-fc-service"
            description = "demo"
            publish     = true
          }
          
          # 將前面準備的python腳本文件打包成zip用于部署到函數計算
          data "archive_file" "code" {
            type        = "zip"
            source_file = "${path.module}/src/index.py"
            output_path = "${path.module}/code.zip"
          }
          
          # 聲明一個fc_service服務中的函數,其中filename引用了上面描述的zip包,會將這個代碼包上傳。
          resource "alicloud_fc_function" "fc_function" {
            service     = alicloud_fc_service.fc_service.name
            name        = "eb-fc-function"
            description = "demo"
            filename    = data.archive_file.code.output_path
            memory_size = "128"
            runtime     = "python3"
            handler     = "index.handler"
          }
          
          # 聲明一個在demo_event_bus總線上的規(guī)則
          resource "alicloud_event_bridge_rule" "demo_rule" {
            event_bus_name = alicloud_event_bridge_event_bus.demo_event_bus.event_bus_name
            rule_name      = "demo_rule"
            description    = "demo"
            # 通過匹配source過濾來自于前面創(chuàng)建的自定義事件源的事件
            filter_pattern = jsonencode(
              {
                "source" : ["${alicloud_event_bridge_event_source.demo_event_source.id}"]
              }
            )
          
            targets {
              target_id = "demo-fc-target"
              # type的取值可以查閱文檔:https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/event_bridge_rule#type
              type      = "acs.fc.function"
              endpoint  = "acs:fc:<region id>:<your account id>:services/${alicloud_fc_service.fc_service.name}.LATEST/functions/${alicloud_fc_function.fc_function.name}"
              param_list {
                resource_key = "serviceName"
                form         = "CONSTANT"
                value        = alicloud_fc_service.fc_service.name
              }
              param_list {
                resource_key = "functionName"
                form         = "CONSTANT"
                value        = alicloud_fc_function.fc_function.name
              }
              param_list {
                resource_key = "Qualifier"
                form         = "CONSTANT"
                value        = "LATEST"
              }
              # 注意form=ORIGINAL意味著每次投遞事件都會將事件的原始內容作為這個參數的值
              param_list {
                resource_key = "Body"
                form         = "ORIGINAL"
              }
            }
          }

          在命令行窗口依次執(zhí)行命令

          • 初始化 terraform init
          • 預覽變更 terraform plan
          • 應用變更 terraform apply

          在控制臺模擬自定義事件源發(fā)布事件

          在 FunctionCompute 的控制臺頁面查看函數調用日志

          在 EventBridge 控制臺查看事件軌跡

          總結

          EventBridge 作為構建 EDA 架構的基礎設施,通過一些核心概念和特性提供了靈活豐富的事件收集、處理和路由的能力,并支持通過 OpenAPI、terraform 等方式將這些能力方便快捷的帶給用戶。本文介紹了 EventBridge 和 IaC 的重點概念和特性,然后演示了如何應用 IaC 理念自動化部署 EventBridge 來使用這些概念和特性。

          期待大家可以發(fā)掘更多利用 EventBridge 快速搭建 EDA 架構的 idea,并使用 terraform 快捷的將這些 idea 變?yōu)楝F實。

          相關鏈接

          [1] 阿里云 terraform 文檔

          https://help.aliyun.com/product/95817.html

          [2] terraform registry 文檔

          https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/event_bridge_event_bus

          [3] 釘釘官方文檔

          https://open.dingtalk.com/document/group/custom-robot-access

          作者:王川(弗丁)

          原文鏈接:https://developer.aliyun.com/article/882907?utm_content=g_1000334839

          本文為阿里云原創(chuàng)內容,未經允許不得轉載。


          主站蜘蛛池模板: 国产精品视频一区麻豆| 国产亚洲欧洲Aⅴ综合一区| 无码人妻久久久一区二区三区| 国产91一区二区在线播放不卡| 国产精品免费综合一区视频| 成人在线观看一区| 日韩一区二区三区在线精品| 上原亚衣一区二区在线观看| 亚洲一区精品中文字幕| 亚洲高清一区二区三区| 国产精品亚洲一区二区三区久久 | 国产主播一区二区三区在线观看| 亚洲av色香蕉一区二区三区蜜桃 | 一区二区三区四区精品| 亚洲AV无码一区二区二三区入口| 日韩精品无码一区二区三区免费| 69久久精品无码一区二区| 精品视频一区二区| 精品无码人妻一区二区免费蜜桃| 国产日产久久高清欧美一区| 国产激情无码一区二区三区| 乱精品一区字幕二区| 精品一区二区三区在线观看l | 精品视频午夜一区二区| 国产伦精品一区二区三区| 亚洲av无码片vr一区二区三区| 亚洲一区二区三区乱码A| 无码国产精品一区二区免费16| 最新中文字幕一区| 夜夜嗨AV一区二区三区| 韩国精品一区视频在线播放| 国产在线无码一区二区三区视频| 久久一区二区三区精华液使用方法| 日本免费精品一区二区三区| 亚洲一区二区在线视频| 精品国产一区二区三区在线观看 | 亚洲A∨精品一区二区三区下载| 福利视频一区二区牛牛| 最新欧美精品一区二区三区 | 中文字幕一区视频| 波多野结衣的AV一区二区三区|