日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
如何利用OpenTelemetry識別數(shù)據(jù)庫依賴關(guān)系?

審校 | 孫淑娟

10多年的鳳泉網(wǎng)站建設(shè)經(jīng)驗(yàn),針對設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。營銷型網(wǎng)站建設(shè)的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整鳳泉建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“鳳泉網(wǎng)站設(shè)計(jì)”,“鳳泉網(wǎng)站推廣”以來,每個客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

隨著組織將單體應(yīng)用程序分解成微服務(wù),遇到的主要障礙之一就是識別數(shù)據(jù)庫依賴關(guān)系。

數(shù)據(jù)庫共享可能是復(fù)雜的挑戰(zhàn)。數(shù)據(jù)庫不允許您定義什么是共享的、什么不是。在修改模式以更好地服務(wù)于一個微服務(wù)時,您可能無意中破壞另一微服務(wù)使用這同一數(shù)據(jù)庫的方式。

此外,常常很難識別數(shù)據(jù)所有者、確定處理數(shù)據(jù)的業(yè)務(wù)邏輯。

本文探討如何使用OpenTelemetry來識別共享同一數(shù)據(jù)庫和數(shù)據(jù)庫對象(比如表)的組件。

可觀察性和OpenTelemetry:基礎(chǔ)

在構(gòu)建演示應(yīng)用程序之前,不妨先討論可觀察性和OpenTelemetry。

什么讓應(yīng)用程序高度可觀察?

如果可以通過研究在任何時間點(diǎn)的輸出來推斷系統(tǒng)的內(nèi)部狀態(tài),該系統(tǒng)就被稱為高度可觀察。

比如說,與多個服務(wù)交互的可觀察移動應(yīng)用程序可以重建生成錯誤響應(yīng)的事務(wù),以便開發(fā)人員識別失敗的根本原因。

圖1. 可觀察應(yīng)用程序示例

可觀察應(yīng)用程序?yàn)槊總€事務(wù)收集三種類型的信息:

  1. 日志:記錄構(gòu)成事務(wù)的各個事件。
  2. 指標(biāo):記錄構(gòu)成事務(wù)的群體事件。
  3. 跟蹤:記錄操作延遲,以識別事務(wù)中的瓶頸。

OpenTelemetry簡介

OpenTelemetry 是一個以集成方式生成日志、指標(biāo)和跟蹤的系統(tǒng)。OpenTelemetry定義了一個標(biāo)準(zhǔn)來捕獲可觀察性數(shù)據(jù)。OpenTelemetry數(shù)據(jù)模型有幾個關(guān)鍵部分。

屬性

OpenTelemetry中的每個數(shù)據(jù)結(jié)構(gòu)都由屬性組成,屬性是鍵值對。OpenTelemetry標(biāo)準(zhǔn)定義了任何組件(比如SQL客戶端或HTTP請求)可以指定的屬性。

活動

事件就是時間戳和一組屬性。您可以記錄事件的詳細(xì)信息,比如消息和異常細(xì)節(jié)。

上下文

上下文包括一組事件共有的屬性。上下文有兩種:靜態(tài)上下文(或資源)定義了事件的位置。在應(yīng)用程序可執(zhí)行文件啟動后,它們的值不變,比如包括服務(wù)的名稱或版本或者庫名稱。

動態(tài)上下文(或span)定義了包含事件的活動操作。span屬性的值在操作執(zhí)行時發(fā)生變化。一些常見的span屬性包括請求的開始時間、HTTP響應(yīng)狀態(tài)代碼或HTTP請求路徑。

在分布式事務(wù)中,上下文需要傳遞給所有關(guān)聯(lián)的服務(wù)。在這種情況下,接收方使用上下文生成新的span??缭椒?wù)邊界的跟蹤稱為分布式跟蹤,將上下文傳輸?shù)狡渌?wù)的過程名為上下文傳播。

日志

日志是僅伴隨資源的事件。一個例子是程序啟動時發(fā)出的事件。

跟蹤

事件可以組織成與資源相關(guān)的操作圖。跟蹤是顯示與事務(wù)相關(guān)的事件的圖形。

指標(biāo)

一個事件可能在任何應(yīng)用程序中發(fā)生多次,或者它的值可能會變。指標(biāo)是一種事件,其值可以是相關(guān)事件的計(jì)數(shù)或事件值的某種計(jì)算。指標(biāo)的一個例子是系統(tǒng)內(nèi)存事件,它的屬性是使用和利用率。

想詳細(xì)了解OpenTelemetry的概念,請參閱文檔:https://opentelemetry.lightstep.com/。

使用OpenTelemetry識別數(shù)據(jù)庫依賴關(guān)系

我們之前討論過,OpenTelemetry規(guī)定了應(yīng)用程序各組件應(yīng)捕獲的屬性。許多流行語言提供了開箱即用的工具庫,以收集用于數(shù)據(jù)庫操作的遙測數(shù)據(jù)。

本文演示使用面向OpenTelemetry的??.NET SQLClient工具??,以及用于遙測數(shù)據(jù)存儲和分析的Lightstep。

不妨討論演示應(yīng)用程序的架構(gòu),以了解遙測數(shù)據(jù)到達(dá)Lightstep的路徑。我們僅討論跟蹤,因?yàn)楦欁阋宰R別數(shù)據(jù)庫和單體組件之間的依賴關(guān)系。

然而,任何企業(yè)應(yīng)用程序都會生成相關(guān)的日志和指標(biāo)以及跟蹤以實(shí)現(xiàn)完整的可見性。

圖2. 從.NET應(yīng)用程序?qū)С鯫TEL跟蹤

首先,我們使用OpenTelemetry SDK檢測單體應(yīng)用程序,以發(fā)出可觀察性信號。雖然檢測應(yīng)用程序是.NET應(yīng)用程序的手動過程,但使用Golang或Java等語言構(gòu)建的應(yīng)用程序可使用自動檢測。

我們使用SDK含有的OpenTelemetry Protocol(OTLP)Exporter。該導(dǎo)出工具讓我們可以將數(shù)據(jù)直接發(fā)送到遙測數(shù)據(jù)攝取服務(wù)。Jaeger和Lightstep等OpenTelemetry平臺聚合跟蹤,幫助您獲得洞察力。

與SDK集成后,應(yīng)用程序的各個部分(比如ASP.NET Core請求處理程序和SQL客戶端)會自動開始生成含有相關(guān)信息的跟蹤。您的代碼可以生成其他跟蹤,以豐富可用信息。

以.NET為例,OpenTelemetry實(shí)現(xiàn)基于System.Diagnostics.*命名空間中的現(xiàn)有類型,如下所示:

  1. System.Diagnostics.ActivitySource代表負(fù)責(zé)生成Span的OpenTelemetry跟蹤器。
  2. System.Diagnostics.Activity代表 Span。
  3. 您可以使用AddTag函數(shù)為span添加屬性。此外,您可以使用AddBaggage功能添加行李。行李被運(yùn)送到子活動,使用W3C標(biāo)頭的其他服務(wù)中有子活動。

檢測應(yīng)用程序后,您可以運(yùn)行自動化測試,或允許用戶使用您的應(yīng)用程序來覆蓋應(yīng)用程序和數(shù)據(jù)庫之間的所有交互路徑。

演示

不妨創(chuàng)建一個簡單的單體員工管理服務(wù)(EMS),以SP.NET Core minimal API為模型。我們的API將具有以下端點(diǎn):

  1. POST /ems/billing:記錄員工為項(xiàng)目所花的工時。
  2. GET /ems/billing/{employeeId}:獲取員工為不同項(xiàng)目所花的工時。
  3. POST /ems/payroll/add:將員工添加到工資單上。
  4. GET /ems/payroll/{employeeId}:獲取員工的工資單數(shù)據(jù)。

您會注意到單體應(yīng)用程序服務(wù)于兩個不同的領(lǐng)域:計(jì)費(fèi)和工資單。這種依賴關(guān)系在復(fù)雜的單體應(yīng)用程序中可能不是很明顯,將它們分離開來可能需要大量的代碼重構(gòu)。

然而,如果研究依賴關(guān)系,您可以輕松地將它們分離開來。EMS應(yīng)用程序的完整源代碼可在該??GitHub存儲庫??中找到。

啟動數(shù)據(jù)庫

我們先在Docker中啟動一個SQL server實(shí)例:

docker run \
-e "ACCEPT_EULA=Y" \
-e "SA_PASSWORD=Str0ngPa$$w0rd" \
-p 1433:1433 \
--name monolith-db \
--hostname sql1 \
-d mcr.microsoft.com/mssql/server:2019-latest

我們使用下列SQL腳本來創(chuàng)建我們的應(yīng)用程序所使用的EMS數(shù)據(jù)庫和表:

IF NOT EXISTS(SELECT * FROM sys.databases WHERE name = 'EMSDb')
BEGIN
CREATE DATABASE EMSDb
END
GO

USE EMSDb

IF OBJECT_ID('[dbo].[Timekeeping]', 'U') IS NULL
BEGIN
CREATE TABLE [Timekeeping] (
[EmployeeId] INT NOT NULL,
[ProjectId] INT NOT NULL,
[WeekClosingDate] DATETIME NOT NULL,
[HoursWorked] INT NOT NULL,
CONSTRAINT [PK_Timekeeping] PRIMARY KEY CLUSTERED ([EmployeeId] ASC, [ProjectId] ASC, [WeekClosingDate] ASC)
)
END
GO

IF OBJECT_ID('[dbo].[Payroll]', 'U') IS NULL
BEGIN
CREATE TABLE [Payroll] (
[EmployeeId] INT NOT NULL,
[PayRateInUSD] MONEY DEFAULT 0 NOT NULL,
CONSTRAINT [PK_Payroll] PRIMARY KEY CLUSTERED ([EmployeeId] ASC)
)
END
GO

實(shí)現(xiàn)API服務(wù)

接下來,我們?yōu)锳PI端點(diǎn)編寫代碼。我們把Program類中的樣板代碼換成以下代碼:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped(_ =>
new SqlConnection(builder.Configuration.GetConnectionString("EmployeeDbConnectionString")));
var app = builder.Build();

app.UseSwagger();
app.UseSwaggerUI();

app.MapPost("/ems/billing", async (Timekeeping timekeepingRecord, SqlConnection db) =>
{
await db.ExecuteAsync(
"INSERT INTO Timekeeping Values(@EmployeeId, @ProjectId, @WeekClosingDate, @HoursWorked)",
timekeepingRecord);
return Results.Created($"/ems/billing/{timekeepingRecord.EmployeeId}", timekeepingRecord);
})
.WithName("RecordProjectWork")
.Produces(StatusCodes.Status201Created);

app.MapGet("/ems/billing/{empId}/", async (int empId, SqlConnection db) =>
{
var result = await db.QueryAsync("SELECT * FROM Timekeeping WHERE EmployeeId=@empId", empId);
return result.Any() ? Results.Ok(result) : Results.NotFound();
})
.WithName("GetBillingDetails")
.Produces>()
.Produces(StatusCodes.Status404NotFound);

app.MapPost("/ems/payroll/add/", async (Payroll payrollRecord, SqlConnection db) =>
{
await db.ExecuteAsync(
"INSERT INTO Payroll Values(@EmployeeId, @PayRateInUSD)", payrollRecord);
return Results.Created($"/ems/payroll/{payrollRecord.EmployeeId}", payrollRecord);
})
.WithName("AddEmployeeToPayroll")
.Produces(StatusCodes.Status201Created);

app.MapGet("/ems/payroll/{empId}", async (int empId, SqlConnection db) =>
{
var result = await db.QueryAsync("SELECT * FROM Payroll WHERE EmployeeId=@empId", empId);
return result.Any() ? Results.Ok(result) : Results.NotFound();
})
.WithName("GetEmployeePayroll")
.Produces>()
.Produces(StatusCodes.Status404NotFound);

app.Run();


public class Timekeeping
{
public int EmployeeId { get; set; }
public int ProjectId { get; set; }
public DateTime WeekClosingDate { get; set; }
public int HoursWorked { get; set; }
}

public class Payroll
{
public int EmployeeId { get; set; }
public decimal PayRateInUSD { get; set; }
}

此時,我們可以運(yùn)行應(yīng)用程序,測試各端點(diǎn),并查看保存在數(shù)據(jù)庫中的記錄。雖然各端點(diǎn)和請求路徑的數(shù)據(jù)庫依賴關(guān)系在這個演示示例中很明顯,但在大型應(yīng)用程序中實(shí)際情況并非如此。

接下來,不妨使發(fā)現(xiàn)數(shù)據(jù)庫依賴關(guān)系的過程實(shí)現(xiàn)自動化。

添加檢測

我們使用OpenTelemetry SDK和面向.NET的SqlClient檢測庫來檢測應(yīng)用程序。我們先將以下NuGet包引用添加到API的項(xiàng)目文件中:






SDK為我們提供了幾種擴(kuò)展方法,我們可以使用這些方法將OpenTelemetry快速接入到請求處理管道。

以下代碼在我們的API中檢測OpenTelemetry。它還將檢測SqlClient以發(fā)出詳細(xì)的遙測數(shù)據(jù)。來自SqlClient的遙測數(shù)據(jù)是詳細(xì)識別數(shù)據(jù)庫依賴關(guān)系的關(guān)鍵。

// Configure tracing
builder.Services.AddOpenTelemetryTracing(builder => builder
// Customize the traces gathered by the HTTP request handler
.AddAspNetCoreInstrumentation(options =>
{
// Only capture the spans generated from the ems/* endpoints
options.Filter = context => context.Request.Path.Value?.Contains("ems") ?? false;
options.RecordException = true;
// Add metadata for the request such as the HTTP method and response length
options.Enrich = (activity, eventName, rawObject) =>
{
switch (eventName)
{
case "OnStartActivity":
{
if (rawObject is not HttpRequest httpRequest)
{
return;
}

activity.SetTag("requestProtocol", httpRequest.Protocol);
activity.SetTag("requestMethod", httpRequest.Method);
break;
}
case "OnStopActivity":
{
if (rawObject is HttpResponse httpResponse)
{
activity.SetTag("responseLength", httpResponse.ContentLength);
}

break;
}
}
};
})
// Customize the telemetry generated by the SqlClient
.AddSqlClientInstrumentation(options =>
{
options.EnableConnectionLevelAttributes = true;
options.SetDbStatementForStoredProcedure = true;
options.SetDbStatementForText = true;
options.RecordException = true;
options.Enrich = (activity, x, y) => activity.SetTag("db.type", "sql");
})
.AddSource("my-corp.ems.ems-api")
// Create resources (key-value pairs) that describe your service such as service name and version
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("ems-api")
.AddAttributes(new[] { new KeyValuePair("service.version", "1.0.0.0") }))
// Ensures that all activities are recorded and sent to exporter
.SetSampler(new AlwaysOnSampler())
// Exports spans to Lightstep
.AddOtlpExporter(otlpOptions =>
{
otlpOptions.Endpoint = new
Uri("https://ingest.lightstep.com:443/traces/otlp/v0.9");
otlpOptions.Headers = $"lightstep-access-token={lsToken}";
otlpOptions.Protocol = OtlpExportProtocol.HttpProtobuf;
}));

雖然檢測在當(dāng)前狀態(tài)下對我們來說足夠了,還是不妨添加相關(guān)跟蹤,進(jìn)一步豐富數(shù)據(jù)。

首先,我們定義跟蹤器,應(yīng)用程序的span將來自該跟蹤器。

var activitySource = new ActivitySource("my-corp.ems.ems-api");

接下來,我們創(chuàng)建一個span,并添加相關(guān)細(xì)節(jié)、屬性和事件:

app.MapPost("/ems/billing", async (Timekeeping timekeepingRecord, SqlConnection db) =>
{
using var activity = activitySource.StartActivity("Record project work", ActivityKind.Server);
activity?.AddEvent(new ActivityEvent("Project billed"));
activity?.SetTag(nameof(Timekeeping.EmployeeId), timekeepingRecord.EmployeeId);
activity?.SetTag(nameof(Timekeeping.ProjectId), timekeepingRecord.ProjectId);
activity?.SetTag(nameof(Timekeeping.WeekClosingDate), timekeepingRecord.WeekClosingDate);

await db.ExecuteAsync(
"INSERT INTO Timekeeping Values(@EmployeeId, @ProjectId, @WeekClosingDate, @HoursWorked)",
timekeepingRecord);
return Results.Created($"/ems/billing/{timekeepingRecord.EmployeeId}", timekeepingRecord);
})
.WithName("RecordProjectWork")
.Produces(StatusCodes.Status201Created);

我們遵循同樣的程序來檢測剩余的端點(diǎn)。

連接到Lightstep

最后,我們需要一個API密鑰將跟蹤信息發(fā)送到Lightstep。我們先創(chuàng)建一個帳戶。在賬戶的Project設(shè)置頁面中,我們找到令牌(Token),它將充當(dāng)API密鑰。

圖3. Lightstep中的API密鑰

我們拷貝令牌,并將它粘貼到appsettings文件中。

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"EmployeeDbConnectionString": "Server=localhost;Database=EMSDb;User Id=sa;Password=Str0ngPa$$w0rd;"
},
"LsToken": ""
}

發(fā)送請求

我們的應(yīng)用程序已準(zhǔn)備就緒。我們啟動應(yīng)用程序,向每個端點(diǎn)發(fā)送一些請求。以下是我發(fā)送到/ems/billing端點(diǎn)的請求。該請求應(yīng)在數(shù)據(jù)庫的Timekeeping表中創(chuàng)建一條記錄。

圖4. 將請求發(fā)送到計(jì)費(fèi)端點(diǎn)

這是我向/emp/payroll/add端點(diǎn)發(fā)出的另一個請求,用于將記錄添加到Payroll表:

圖5. 將請求發(fā)送到工資單端點(diǎn)

進(jìn)入到Lightstep可觀察性門戶網(wǎng)站后,我們可以點(diǎn)擊Operations選項(xiàng)卡,查看Lightstep從應(yīng)用程序接收到的所有span。

圖6. Lightstep中查看來自應(yīng)用程序的span

我們點(diǎn)擊/ems/payroll/add操作后,可以查看端到端跟蹤。通過查看span,我們可以確定任何請求的操作順序。點(diǎn)擊span可顯示其事件和屬性,從中我們可以更深入地了解操作。

跟蹤中可見的最后一個span是EMSDb,它是由我們檢測的SQL客戶端生成的。點(diǎn)擊span可查看其屬性和事件,如下所示:

圖7. 工資單端點(diǎn)生成的span詳細(xì)信息

我們可以從屬性得到一些關(guān)鍵信息:

  1. 數(shù)據(jù)庫名稱
  2. 數(shù)據(jù)庫操作中使用的SQL語句
  3. SQL語句的類型(文本或存儲過程)
  4. 發(fā)出請求的服務(wù)的主機(jī)名

我們從/ems/billing操作的子span中找到了一組類似的詳細(xì)信息。

圖8. 計(jì)費(fèi)端點(diǎn)生成的span的詳細(xì)信息

如果梳理來自跟蹤的信息,我們可以推斷出以下內(nèi)容:

  1. 入站操作(接收外部請求的操作)
  2. 完成請求的一系列活動,包括外部服務(wù)調(diào)用和數(shù)據(jù)庫操作。
  3. 每個操作涉及的數(shù)據(jù)庫操作。

總之,這些信息足以讓我們規(guī)劃服務(wù)和數(shù)據(jù)庫的分離,并為微服務(wù)之間的通信建立聯(lián)系。

結(jié)論

本文討論了開發(fā)人員將單體應(yīng)用程序轉(zhuǎn)換成微服務(wù)時遇到的常見挑戰(zhàn)之一。在所有問題中,拆分?jǐn)?shù)據(jù)庫是一項(xiàng)復(fù)雜的工作,因?yàn)樵L問數(shù)據(jù)庫的任何服務(wù)都可以處理數(shù)據(jù)庫。

通過使用OpenTelemetry,我們可以識別各組件之間以及組件與數(shù)據(jù)庫之間的依賴關(guān)系。 了解依賴關(guān)系后,我們可以為自己的組件制定重構(gòu)計(jì)劃,規(guī)劃它們作為獨(dú)立的微服務(wù)應(yīng)如何與時俱進(jìn)。

原文標(biāo)題:??How to Use OpenTelemetry to Identify Database Dependencies???,作者:Rahul Rai?


網(wǎng)頁名稱:如何利用OpenTelemetry識別數(shù)據(jù)庫依賴關(guān)系?
本文來源:http://www.5511xx.com/article/cddsiio.html