如何用 C# 从 Gotenberg 迁移到 IronPDF
从高登堡迁移到IronPDF可将您的 .NET PDF 工作流程从基于 Docker 的微服务架构与 HTTP API 调用转换为进程内的本地 C# 库。 本指南为专业的 .NET 开发人员提供了一个全面的、循序渐进的迁移路径,消除了基础架构开销、网络延迟和容器管理的复杂性。
为什么要从高登堡迁移到 IronPDF.
哥登堡架构问题
Gotenberg 是一种基于 Docker 的 PDF 生成微服务架构。 虽然功能强大且灵活,但它为 C# 应用程序带来了很大的复杂性:
1.基础设施开销:需要 Docker、容器编排(Kubernetes/Docker Compose)、服务发现和负载均衡。 每次部署都会变得更加复杂。
2.网络延迟:每次 PDF 操作都需要向单独的服务发起 HTTP 请求,每次请求会增加 10-100 毫秒以上的延迟。在高流量场景下,这种延迟会迅速累积。
3.冷启动问题:容器启动可能会给首次请求增加 2-5 秒的时间。 每次 pod 重启、每次扩展事件和每次部署都会触发冷启动。
4.操作复杂性:您必须将容器健康状况、扩展、日志记录和监控作为与主应用程序分开的独立问题进行管理。
5.多部分表单数据:每个请求都需要构建 multipart/form-data 有效负载——冗长、容易出错且难以维护。
6.故障点:网络超时、服务不可用和容器崩溃等问题都需要您负责处理。
7.版本管理:高登堡图片的更新与您的应用程序是分开的; API 的更改可能会意外破坏集成。
高登堡与IronPDF对比
| 方面 | 高登堡 | IronPDF |
|---|---|---|
| 部署 | Docker 容器 + 协调 | 单个 NuGet 软件包 |
| 结构 | 微服务(REST API) | 在建库 |
| 每次请求的延迟 | 10-100ms+(网络往返) | < 1ms 开销 |
| 冷启动 | 2-5 秒(容器启动) | 1-2 秒(仅限首次呈现) |
| 基础设施 | Docker、Kubernetes、负载平衡器 | 无要求 |
| 失败模式 | 网络、容器、服务故障 | .NET 标准例外情况 |
| API 风格 | REST 多art/表单数据 | 本地 C# 方法调用 |
| 缩放 | 横向(更多容器) | 纵向(处理中) |
| 调试 | 需要分布式跟踪 | 标准调试器 |
| 版本控制 | 容器图像标签 | NuGet 软件包版本 |
对于计划在 2025 年和 2026 年之前采用 .NET 10 和 C# 14 的团队来说,IronPDF 提供了一个面向未来的基础,零基础设施依赖性,可与现代 .NET 模式原生集成。
迁移复杂性评估
按功能估算的工作量
| 特征 | 迁移复杂性 |
|---|---|
| HTML 至 PDF | 极低 |
| URL 至 PDF | 极低 |
| 定制纸张大小 | low |
| 边距 | low |
| PDF 合并 | low |
| 页眉/页脚 | 语言 |
| 等待延迟 | low |
| PDF/A 转换 | low |
范式转换
Gotenberg 迁移的根本转变在于从使用 multipart 表单数据的 HTTP API 调用转变为原生 C# 方法调用:
高登堡: 向 Docker 容器发送 HTTP POST 多址/表单数据
IronPDF: 在 C# 对象上直接调用方法
开始之前
前提条件
- .NET 版本:IronPDF支持 .NET Framework 4.6.2+ 和 .NET Core 3.1+ / .NET 5/6/7/8/9+ 2.许可证密钥:从ironpdf.com获取您的IronPDF许可证密钥。 3.规划基础设施移除:记录哥登堡容器在迁移后的退役事宜
识别所有高登堡用法
# Find direct HTTP calls to Gotenberg
grep -r "gotenberg\|/forms/chromium\|/forms/libreoffice\|/forms/pdfengines" --include="*.cs" .
# Find GotenbergSharpApiClient usage
grep -r "GotenbergSharpClient\|Gotenberg.Sharp\|ChromiumRequest" --include="*.cs" .
# Find Docker/Kubernetes高登堡configuration
grep -r "gotenberg/gotenberg\|gotenberg:" --include="*.yml" --include="*.yaml" .
# Find direct HTTP calls to Gotenberg
grep -r "gotenberg\|/forms/chromium\|/forms/libreoffice\|/forms/pdfengines" --include="*.cs" .
# Find GotenbergSharpApiClient usage
grep -r "GotenbergSharpClient\|Gotenberg.Sharp\|ChromiumRequest" --include="*.cs" .
# Find Docker/Kubernetes高登堡configuration
grep -r "gotenberg/gotenberg\|gotenberg:" --include="*.yml" --include="*.yaml" .
NuGet 软件包变更
# Remove高登堡client (if using)
dotnet remove package Gotenberg.Sharp.API.Client
# Install IronPDF
dotnet add package IronPdf
# Remove高登堡client (if using)
dotnet remove package Gotenberg.Sharp.API.Client
# Install IronPDF
dotnet add package IronPdf
快速启动迁移
步骤 1:更新许可配置
之前(高登堡):
Gotenberg 不需要许可证,但需要带有容器 URL 的 Docker 基础设施。
private readonly string _gotenbergUrl = "http://localhost:3000";
private readonly string _gotenbergUrl = "http://localhost:3000";
Private ReadOnly _gotenbergUrl As String = "http://localhost:3000"
After (IronPDF):
// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";
// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";
' Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY"
步骤 2:更新名称空间导入
// Before (Gotenberg)
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;
// Before (Gotenberg)
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Imports IronPdf
Imports IronPdf.Rendering
完整的 API 参考
戈登堡端点到IronPDF的映射
| 哥登堡路线 | IronPDF 同等产品 |
|---|---|
POST /forms/chromium/convert/html |
ChromePdfRenderer.RenderHtmlAsPdf() |
POST /forms/chromium/convert/url |
ChromePdfRenderer.RenderUrlAsPdf() |
POST /forms/pdfengines/merge |
PdfDocument.Merge() |
POST /forms/pdfengines/convert |
pdf.SaveAs() 带设置 |
GET /health |
不适用 |
表单参数到渲染选项映射
| 高登贝格参数 | IronPDF 属性 | 转换注意事项 |
|---|---|---|
paperWidth(英寸) |
RenderingOptions.PaperSize |
使用枚举或自定义大小 |
paperHeight(英寸) |
RenderingOptions.PaperSize |
使用枚举或自定义大小 |
marginTop(英寸) |
RenderingOptions.MarginTop |
毫米数乘以 25.4 |
marginBottom(英寸) |
RenderingOptions.MarginBottom |
毫米数乘以 25.4 |
printBackground |
RenderingOptions.PrintHtmlBackgrounds |
布尔 |
landscape |
RenderingOptions.PaperOrientation |
Landscape枚举 |
waitDelay |
RenderingOptions.RenderDelay |
转换为毫秒 |
代码迁移示例
示例 1:将基本 HTML 转换为 PDF.
之前(高登堡):
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergExample
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Hello from Gotenberg</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("output.pdf", pdfBytes);
Console.WriteLine("PDF generated successfully");
}
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergExample
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Hello from Gotenberg</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("output.pdf", pdfBytes);
Console.WriteLine("PDF generated successfully");
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Module GotenbergExample
Async Function Main() As Task
Dim gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html"
Using client As New HttpClient()
Using content As New MultipartFormDataContent()
Dim html = "<html><body><h1>Hello from Gotenberg</h1></body></html>"
content.Add(New StringContent(html), "files", "index.html")
Dim response = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
Await File.WriteAllBytesAsync("output.pdf", pdfBytes)
Console.WriteLine("PDF generated successfully")
End Using
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfExample
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var html = "<html><body><h1>Hello from IronPDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF generated successfully");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfExample
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var html = "<html><body><h1>Hello from IronPDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF generated successfully");
}
}
Imports System
Imports IronPdf
Class IronPdfExample
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html = "<html><body><h1>Hello from IronPDF</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
Console.WriteLine("PDF generated successfully")
End Sub
End Class
区别很大:Gotenberg 需要构造一个 HttpClient,构建 MultipartFormDataContent,向正在运行的 Docker 容器发出异步 HTTP POST 请求,并处理字节数组响应。IronPDF将其简化为三行代码,并调用 ChromePdfRenderer 方法——没有网络开销,没有容器依赖,没有异步复杂性。 有关其他渲染选项,请参阅 HTML to PDF 文档。
示例 2:URL 到 PDF 的转换
之前(高登堡):
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergUrlToPdf
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/url";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
content.Add(new StringContent("https://example.com"), "url");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("webpage.pdf", pdfBytes);
Console.WriteLine("PDF from URL generated successfully");
}
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergUrlToPdf
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/url";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
content.Add(new StringContent("https://example.com"), "url");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("webpage.pdf", pdfBytes);
Console.WriteLine("PDF from URL generated successfully");
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Module GotenbergUrlToPdf
Async Function Main() As Task
Dim gotenbergUrl As String = "http://localhost:3000/forms/chromium/convert/url"
Using client As New HttpClient()
Using content As New MultipartFormDataContent()
content.Add(New StringContent("https://example.com"), "url")
Dim response As HttpResponseMessage = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes As Byte() = Await response.Content.ReadAsByteArrayAsync()
Await File.WriteAllBytesAsync("webpage.pdf", pdfBytes)
Console.WriteLine("PDF from URL generated successfully")
End Using
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfUrlToPdf
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("PDF from URL generated successfully");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfUrlToPdf
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("PDF from URL generated successfully");
}
}
Imports System
Imports IronPdf
Class IronPdfUrlToPdf
Shared Sub Main()
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
pdf.SaveAs("webpage.pdf")
Console.WriteLine("PDF from URL generated successfully")
End Sub
End Class
Gotenberg 方法需要不同的端点(/forms/chromium/convert/url),使用 URL 作为表单字段构建多部分内容,并处理异步 HTTP 响应。IronPDF的 RenderUrlAsPdf() 方法直接接受 URL,并同步返回一个 PdfDocument 对象。 了解有关 URL 至 PDF 转换的更多信息。
示例 3:自定义纸张大小和页边距
之前(高登堡):
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergCustomSize
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
content.Add(new StringContent("8.5"), "paperWidth");
content.Add(new StringContent("11"), "paperHeight");
content.Add(new StringContent("0.5"), "marginTop");
content.Add(new StringContent("0.5"), "marginBottom");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("custom-size.pdf", pdfBytes);
Console.WriteLine("Custom size PDF generated successfully");
}
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergCustomSize
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
content.Add(new StringContent("8.5"), "paperWidth");
content.Add(new StringContent("11"), "paperHeight");
content.Add(new StringContent("0.5"), "marginTop");
content.Add(new StringContent("0.5"), "marginBottom");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("custom-size.pdf", pdfBytes);
Console.WriteLine("Custom size PDF generated successfully");
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Class GotenbergCustomSize
Shared Async Function Main() As Task
Dim gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html"
Using client As New HttpClient()
Using content As New MultipartFormDataContent()
Dim html = "<html><body><h1>Custom Size PDF</h1></body></html>"
content.Add(New StringContent(html), "files", "index.html")
content.Add(New StringContent("8.5"), "paperWidth")
content.Add(New StringContent("11"), "paperHeight")
content.Add(New StringContent("0.5"), "marginTop")
content.Add(New StringContent("0.5"), "marginBottom")
Dim response = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
Await File.WriteAllBytesAsync("custom-size.pdf", pdfBytes)
Console.WriteLine("Custom size PDF generated successfully")
End Using
End Using
End Function
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;
class IronPdfCustomSize
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 50;
renderer.RenderingOptions.MarginBottom = 50;
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom-size.pdf");
Console.WriteLine("Custom size PDF generated successfully");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;
class IronPdfCustomSize
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 50;
renderer.RenderingOptions.MarginBottom = 50;
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom-size.pdf");
Console.WriteLine("Custom size PDF generated successfully");
}
}
Imports System
Imports IronPdf
Imports IronPdf.Rendering
Module IronPdfCustomSize
Sub Main()
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter
renderer.RenderingOptions.MarginTop = 50
renderer.RenderingOptions.MarginBottom = 50
Dim html As String = "<html><body><h1>Custom Size PDF</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("custom-size.pdf")
Console.WriteLine("Custom size PDF generated successfully")
End Sub
End Module
Gotenberg 要求将基于字符串的参数("8.5"、"11"、"0.5")添加到 multipart 表单数据中——没有类型安全,没有 IntelliSense,容易输入错误。IronPDF提供具有枚举和数值边距值的强类型属性。 请注意,IronPDF 页边距以毫米为单位(50 毫米≈ 2 英寸),而高登堡使用英寸。
关键迁移说明
单位转换
此次高登堡迁移中最重要的转换是保证金单位:
// Gotenberg: margins in inches
content.Add(new StringContent("0.5"), "marginTop"); // 0.5 inches
content.Add(new StringContent("1"), "marginBottom"); // 1 inch
// IronPDF: margins in millimeters
renderer.RenderingOptions.MarginTop = 12.7; // 0.5 inches × 25.4 = 12.7mm
renderer.RenderingOptions.MarginBottom = 25.4; // 1 inch × 25.4 = 25.4mm
// Gotenberg: margins in inches
content.Add(new StringContent("0.5"), "marginTop"); // 0.5 inches
content.Add(new StringContent("1"), "marginBottom"); // 1 inch
// IronPDF: margins in millimeters
renderer.RenderingOptions.MarginTop = 12.7; // 0.5 inches × 25.4 = 12.7mm
renderer.RenderingOptions.MarginBottom = 25.4; // 1 inch × 25.4 = 25.4mm
' Gotenberg: margins in inches
content.Add(New StringContent("0.5"), "marginTop") ' 0.5 inches
content.Add(New StringContent("1"), "marginBottom") ' 1 inch
' IronPDF: margins in millimeters
renderer.RenderingOptions.MarginTop = 12.7 ' 0.5 inches × 25.4 = 12.7mm
renderer.RenderingOptions.MarginBottom = 25.4 ' 1 inch × 25.4 = 25.4mm
转换公式: millimeters = inches × 25.4
同步与异步
由于 HTTP 通信,Gotenberg 需要异步操作:
// Gotenberg: Forced async due to network calls
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
// IronPDF: Synchronous in-process execution
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// IronPDF: Async wrapper if needed
var pdf = await Task.Run(() => renderer.RenderHtmlAsPdf(html));
// Gotenberg: Forced async due to network calls
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
// IronPDF: Synchronous in-process execution
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// IronPDF: Async wrapper if needed
var pdf = await Task.Run(() => renderer.RenderHtmlAsPdf(html));
Imports System.Net.Http
' Gotenberg: Forced async due to network calls
Dim response = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
' IronPDF: Synchronous in-process execution
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
' IronPDF: Async wrapper if needed
Dim pdf = Await Task.Run(Function() renderer.RenderHtmlAsPdf(html))
错误处理
// Gotenberg: HTTP error handling
try
{
var response = await client.PostAsync(gotenbergUrl, content);
response.EnsureSuccessStatusCode(); // What if 500? 503? Timeout?
}
catch (HttpRequestException ex) { /* Network error */ }
catch (TaskCanceledException ex) { /* Timeout */ }
// IronPDF: Standard .NET exceptions
try
{
var pdf = renderer.RenderHtmlAsPdf(html);
}
catch (Exception ex)
{
Console.WriteLine($"PDF generation failed: {ex.Message}");
}
// Gotenberg: HTTP error handling
try
{
var response = await client.PostAsync(gotenbergUrl, content);
response.EnsureSuccessStatusCode(); // What if 500? 503? Timeout?
}
catch (HttpRequestException ex) { /* Network error */ }
catch (TaskCanceledException ex) { /* Timeout */ }
// IronPDF: Standard .NET exceptions
try
{
var pdf = renderer.RenderHtmlAsPdf(html);
}
catch (Exception ex)
{
Console.WriteLine($"PDF generation failed: {ex.Message}");
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
' Gotenberg: HTTP error handling
Try
Dim response = Await client.PostAsync(gotenbergUrl, content)
response.EnsureSuccessStatusCode() ' What if 500? 503? Timeout?
Catch ex As HttpRequestException
' Network error
Catch ex As TaskCanceledException
' Timeout
End Try
' IronPDF: Standard .NET exceptions
Try
Dim pdf = renderer.RenderHtmlAsPdf(html)
Catch ex As Exception
Console.WriteLine($"PDF generation failed: {ex.Message}")
End Try
基础架构移除
迁移后,从您的基础架构中移除 Gotenberg:
# REMOVE from docker-compose.yml:
# services:
# gotenberg:
# image: gotenberg/gotenberg:8
# ports:
# - "3000:3000"
# deploy:
# resources:
# limits:
# memory: 2G
# REMOVE from docker-compose.yml:
# services:
# gotenberg:
# image: gotenberg/gotenberg:8
# ports:
# - "3000:3000"
# deploy:
# resources:
# limits:
# memory: 2G
性能考虑
延迟比较
| 手术 | 哥登堡(温暖) | 高登堡(冷启动) | IronPDF (初渲染) | IronPDF (后续) |
|---|---|---|---|---|
| 简单的 HTML | 150-300 毫秒 | 2-5 秒 | 1-2 秒 | 50-150ms |
| 复杂的 HTML | 500-1500ms | 3-7 秒 | 1.5-3 秒 | 200-800ms |
| URL 渲染 | 1-5 秒 | 3-10 秒 | 1-5 秒 | 500ms-3s |
消除基础设施成本
| 资源 | 高登堡 | IronPDF |
|---|---|---|
| 所需容器 | 1-N(缩放) | 0 |
| 每个容器的内存 | 512MB-2GB | 不适用 |
| 每次请求的网络开销 | 10-100 毫秒 | 0ms |
| 健康检查终点 | 要求 | 不需要 |
| 负载平衡器 | 经常需要 | 不需要 |
故障排除
问题 1:不需要 HttpClient 模式
问题:代码仍然使用 HttpClient 和 MultipartFormDataContent。
解决方案:完全替换为 ChromePdfRenderer:
// Remove all of this:
// using var client = new HttpClient();
// using var content = new MultipartFormDataContent();
// content.Add(new StringContent(html), "files", "index.html");
// var response = await client.PostAsync(url, content);
// Replace with:
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Remove all of this:
// using var client = new HttpClient();
// using var content = new MultipartFormDataContent();
// content.Add(new StringContent(html), "files", "index.html");
// var response = await client.PostAsync(url, content);
// Replace with:
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
问题 2:边距单位错误
问题:迁移后 PDF 文件的边距不正确。
解决方法:将英寸转换为毫米:
//高登堡used inches: "0.5"
//IronPDFuses millimeters: 0.5 × 25.4 = 12.7
renderer.RenderingOptions.MarginTop = 12.7;
//高登堡used inches: "0.5"
//IronPDFuses millimeters: 0.5 × 25.4 = 12.7
renderer.RenderingOptions.MarginTop = 12.7;
问题 3:容器 URL 引用
问题:代码包含 http://gotenberg:3000 或类似 URL。
解决方案:移除所有容器 URL 引用——IronPDF 以进程内方式运行:
// Remove:
// private readonly string _gotenbergUrl = "http://gotenberg:3000";
//IronPDFneeds no URL - it's in-process
var renderer = new ChromePdfRenderer();
// Remove:
// private readonly string _gotenbergUrl = "http://gotenberg:3000";
//IronPDFneeds no URL - it's in-process
var renderer = new ChromePdfRenderer();
迁移清单
迁移前
- 清点代码库中所有高登堡HTTP 调用
- 记录当前高登堡配置(超时、页边距、纸张尺寸)
- 识别所有 Docker/Kubernetes高登堡配置
- 获取IronPDF许可证密钥
- 规划基础设施退役
代码迁移
- 安装 IronPdf NuGet 包:
dotnet add package IronPdf - 移除高登堡客户端软件包
- 将所有对高登堡的 HTTP 调用替换为IronPDF方法调用
- 将边距单位从英寸转换为毫米
- 更新错误处理(HTTP 错误 → .NET 异常)
- 添加启动时许可证密钥初始化功能
基础架构迁移
- 从 Docker Compose/Kubernetes 中移除 Gotenberg
- 更新 CI/CD 流水线(移除高登堡镜像拉取)
- 移除哥特堡健康检查
- 从配置中移除高登堡URL
测试
- 测试 HTML 到 PDF 的转换
- 测试 URL 到 PDF 的转换
- 核实边距和尺寸准确性
- 负载下的性能测试
- 测试首次渲染预热时间
后迁移
- 移除高登堡容器部署
- 归档高登堡配置文件
- 更新文档
- 监控应用程序内存使用情况
- 检查是否存在孤立的网络连接

