<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans"><generator uri="https://jekyllrb.com/" version="3.8.6">Jekyll</generator><link href="https://openliberty.io/zh-Hans/feed.xml" rel="self" type="application/atom+xml" /><link href="https://openliberty.io/zh-Hans/" rel="alternate" type="text/html" hreflang="zh-Hans" /><updated>2026-05-20T04:54:27+00:00</updated><id>https://openliberty.io/zh-Hans/feed.xml</id><title type="html">Open Liberty</title><subtitle>Open Liberty is the most flexible server runtime available to Earth’s Java developers.
</subtitle><entry><title type="html">在 Open Liberty 上运行支持 AI 的 Jakarta EE 和 MicroProfile 应用程序</title><link href="https://openliberty.io/zh-Hans/blog/2025/09/26/open-liberty-with-langchain4j-example.html" rel="alternate" type="text/html" title="在 Open Liberty 上运行支持 AI 的 Jakarta EE 和 MicroProfile 应用程序" /><published>2025-09-26T00:00:00+00:00</published><updated>2025-09-26T00:00:00+00:00</updated><id>https://openliberty.io/zh-Hans/blog/2025/09/26/open-liberty-with-langchain4j-example</id><content type="html" xml:base="https://openliberty.io/zh-Hans/blog/2025/09/26/open-liberty-with-langchain4j-example.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>人工智能（Artificial Intelligence，AI）是一个令人兴奋且具有颠覆性的领域，它已经通过实现自动化、改进决策制定和从数据中获取新见解来转变企业甚至整个行业。随着 ChatGPT 等大型语言模型（Large Language Model，LLM）的兴起，AI 的性能及其推动企业价值的潜力发生了重大转变。那么，这将如何影响企业的软件开发以及云原生 Java 应用程序的构建呢？</p>
</div>
<div class="paragraph">
<p>在本文中，我们将探讨什么是 LLM 以及如何在 Java 应用程序中使用它们。我们也将在一个 Jakarta EE/MicroProfile 示例应用程序中入门实践。</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#what_Are_LLMs">了解什么是大型语言模型（LLM）</a></p>
</li>
<li>
<p><a href="#Java_LLMs">探索简化 LLM 使用的 Java 应用框架</a></p>
</li>
<li>
<p><a href="#using_Langchain4j">学习如何在 Java 应用中使用 LangChain4j</a></p>
</li>
<li>
<p><a href="#tryout">试用 jakartaee-microprofile-example 示例应用</a></p>
</li>
<li>
<p><a href="#how_app_work">了解该示例应用的工作原理和架构</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="what_Are_LLMs">什么是 LLM？</h2>
<div class="sectionbody">
<div class="paragraph">
<p>语言模型是基于概率的自然语言模型，它们能够生成一系列词语组合的概率。而<a href="https://www.ibm.com/cn-zh/think/topics/large-language-models">大型语言模型（LLM）</a>是指规模庞大的语言模型，通常以其参数数量巨大而被分类为“大型”。这些模型通过自监督和半监督学习技术，在海量数据上进行训练，参数量可能达到数十亿级别。训练后的模型具备生成自然语言及其他类型内容的能力，能够执行广泛的任务。</p>
</div>
<div class="paragraph">
<p>您可以观看这个<a href="https://www.youtube.com/watch?v=5sLYAQS9sWQ">介绍视频</a>，了解 LLM 的基本概念、工作原理以及在商业中的应用场景。</p>
</div>
<div class="paragraph">
<p>目前几乎所有主流云服务提供商都在其产品中集成了 LLM。例如，IBM 通过其 <a href="https://www.ibm.com/watsonx">watsonx</a> 服务提供模型；<a href="https://azure.microsoft.com/en-us/solutions/ai">Microsoft Azure</a> 提供如 Llama 2 和 OpenAI GPT-4 等模型；<a href="https://aws.amazon.com/bedrock/">Amazon Bedrock</a> 则聚合了来自多家 AI 公司的模型服务。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="Java_LLMs">我们如何在 Java 应用中充分利用 LLM？</h2>
<div class="sectionbody">
<div class="paragraph">
<p>将 AI/LLM 能力集成到应用程序中可能具有一定挑战性。开源框架 LangChain 于 2022 年推出，旨在帮助简化创建生成式 AI 应用程序的开发流程。</p>
</div>
<div class="paragraph">
<p>LangChain 提供了一系列工具和抽象层，用于提升模型生成内容的定制性、准确性和相关性。例如，开发者可以使用 LangChain 组件构建新的提示链（Prompt chain），或自定义已有的提示模板（Prompt template）。LangChain 还包括使 LLM 能够在不重新训练的情况下访问新数据集的组件，并能高效组织模型所需的大量数据，以便可以轻松访问和使用。</p>
</div>
<div class="paragraph">
<p>虽然 LangChain 主要提供 Python 和 JavaScript/TypeScript 版本，但 GitHub 上的 Java 社区开源项目如 <a href="https://github.com/langchain4j/langchain4j">LangChain4j</a> 也提供了在 Java 应用中使用 LangChain 的选项。通过 LangChain4j API，开发者可以将 LLM 集成到 Java 应用中，并连接到不同的 AI 平台，如 OpenAI 和 Hugging Face。</p>
</div>
<div class="imageblock text-center">
<div class="content">
<img src="/img/blog/langchain4j.png" alt="langchain4j GitHub README image" width="70%">
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="using_Langchain4j">如何在 Jakarta EE 和 MicroProfile 应用程序中使用 LangChain4j</h2>
<div class="sectionbody">
<div class="paragraph">
<p>LangChain4j 提供了一个非常有用的开源 <a href="https://github.com/langchain4j/langchain4j-examples">langchain4j-examples</a> GitHub 仓库，用于存放示例应用程序。然而，我们没有找到任何展示如何在基于 Jakarta EE 或 MicroProfile 的应用程序中体验这些 AI 技术的示例。因此，我们决定自行构建一个名为 <code>jakartaee-microprofile-example</code> 的示例应用，且目前已收录在 <a href="https://github.com/langchain4j/langchain4j-examples/tree/main/jakartaee-microprofile-example">langchain4j-examples</a> GitHub 仓库中。该示例应用展示了如何在 Open Liberty 上使用 Jakarta EE 和 MicroProfile 来集成 LangChain4j API。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="tryout">试用 jakartaee-microprofile-example 示例应用</h2>
<div class="sectionbody">
<div class="paragraph">
<p>要了解如何将 LangChain4j 应用于你自己的 Jakarta EE 和 MicroProfile 应用，请亲自查看这个示例项目。</p>
</div>
<div class="sect2">
<h3 id="pre-reqs">前提条件</h3>
<div class="paragraph">
<p>在将应用克隆到本地之前，请先安装 JDK 17，并确保已正确设置 <code>JAVA_HOME</code> 环境变量。您可以选择使用 <a href="https://developer.ibm.com/languages/java/semeru-runtimes/downloads">IBM Semeru Runtime</a> 作为您的 Java 运行时。该运行时基于 Eclipse OpenJ9 等项目的深度技术投入，在多种硬件和软件平台上都具备良好的性能优势。更多关于 IBM Semeru Runtime 的信息，请参阅文章 <a href="https://openliberty.io/blog/2022/08/19/open-liberty-semeru-performance.html">Open Liberty 和 Semeru Runtimes，重要的云原生性能</a>。</p>
</div>
<div class="paragraph">
<p>该应用程序使用 Hugging Face。您需要获取 Hugging Face API 密钥：</p>
</div>
<div class="ulist">
<ul>
<li>
<p>注册并登录 <a href="https://huggingface.co" class="bare">https://huggingface.co</a></p>
</li>
<li>
<p>前往<a href="https://huggingface.co/settings/tokens">访问令牌页面</a></p>
</li>
<li>
<p>创建一个具有 <code>read</code> 权限的访问令牌</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>如果您尚未安装 Git，可以参考 <a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git">Git 安装指南</a>进行安装。安装完成后，运行以下命令将 <code>langchain4j-examples</code> GitHub 仓库克隆到本地：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>git clone https://github.com/langchain4j/langchain4j-examples.git</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="env_setup">环境配置</h3>
<div class="paragraph">
<p>要运行该应用，请访问 <code>jakartaee-microprofile-example</code> 目录：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>cd langchain4j-examples/jakartaee-microprofile-example</code></pre>
</div>
</div>
<div class="paragraph">
<p>设置以下环境变量：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>export JAVA_HOME=&lt;your Java 17 home path&gt;
export HUGGING_FACE_API_KEY=&lt;your Hugging Face read token&gt;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="start_app">启动应用程序</h3>
<div class="paragraph">
<p>要启动该应用程序，请使用项目中提供的 Maven Wrapper，在 Open Liberty <a href="https://openliberty.io/docs/latest/development-mode.html">dev mode</a> 下运行：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>./mvnw liberty:dev</code></pre>
</div>
</div>
<div class="paragraph">
<p>当您看到以下消息时，说明应用程序已准备就绪：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>************************************************************************
*    Liberty is running in dev mode.
*        Automatic generation of features: [ Off ]
*        h - see the help menu for available actions, type 'h' and press Enter.
*        q - stop the server and quit dev mode, press Ctrl-C or type 'q' and press Enter.
*
*    Liberty server port information:
*        Liberty server HTTP port: [ 9080 ]
*        Liberty server HTTPS port: [ 9443 ]
*        Liberty debug port: [ 7777 ]
************************************************************************</pre>
</div>
</div>
<div class="paragraph">
<p>为确认应用是否成功启动，您可以在命令行中按下 <code>enter/return</code> 键运行测试。如果测试通过，您将看到类似如下的输出：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running it.dev.langchan4j.example.ChatServiceIT
[INFO] ...
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.439 s...
[INFO] ...
[INFO] Running it.dev.langchan4j.example.ModelResourceIT
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.733 s...
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0</pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="access_app">访问应用程序</h3>
<div class="paragraph">
<p>应用启动后，您可以通过任意浏览器访问 <a href="http://localhost:9080/" class="bare">http://localhost:9080/</a> 并开始试验。</p>
</div>
<div class="imageblock text-center">
<div class="content">
<img src="/img/blog/langchain4j-example-chat-room.png" alt="Chat Room of LangChain4j Jakarta EE and MicroProfile example" width="70%">
</div>
</div>
<div class="paragraph">
<p>您可以输入任意文本与 AI 代理进行对话。以下是一些推荐的消息示例：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>什么是 MicroProfile？</code></p>
</li>
<li>
<p><code>目前有哪些主要公司在推动 MicroProfile 项目的发展？</code></p>
</li>
<li>
<p><code>有任何文档吗？</code></p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="how_app_work">应用程序的工作原理</h2>
<div class="sectionbody">
<div class="paragraph">
<p>该应用展示了如何结合使用以下技术：</p>
</div>
<div class="ulist">
<ul>
<li>
<p>LangChain4j API</p>
</li>
<li>
<p><a href="https://openliberty.io/docs/ref/feature/#cdi-4.0.html">Jakarta Contexts and Dependency Injection</a></p>
</li>
<li>
<p><a href="https://openliberty.io/docs/latest/reference/feature/websocket-2.1.html">Jakarta WebSocket</a></p>
</li>
<li>
<p><a href="https://openliberty.io/docs/ref/feature/#mpConfig-3.0.html">MicroProfile Config</a></p>
</li>
<li>
<p><a href="https://openliberty.io/docs/latest/reference/feature/mpMetrics-5.1.html">MicroProfile Metrics</a></p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="create_service">创建 LangChain4j AI 服务</h3>
<div class="paragraph">
<p>该应用使用 <code>HuggingFaceChatModel</code> 类作为构建 AI 服务的模型。</p>
</div>
<div class="paragraph">
<p>请参阅文件：<a href="https://github.com/langchain4j/langchain4j-examples/tree/main/jakartaee-microprofile-example/src/main/java/dev/langchain4j/example/chat/ChatAgent.java">src/main/java/dev/langchain4j/example/chat/ChatAgent.java</a></p>
</div>
<div class="listingblock no_copy">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    <span class="directive">public</span> Assistant getAssistant() {
        ...
            HuggingFaceChatModel model = HuggingFaceChatModel.builder()
                .accessToken(HUGGING_FACE_API_KEY)
                .modelId(CHAT_MODEL_ID)
                .timeout(ofSeconds(TIMEOUT))
                .temperature(TEMPERATURE)
                .maxNewTokens(MAX_NEW_TOKEN)
                .waitForModel(<span class="predefined-constant">true</span>)
                .build();
            assistant = AiServices.builder(Assistant.class)
                .chatLanguageModel(model)
                .chatMemoryProvider(
                    sessionId -&gt; MessageWindowChatMemory.withMaxMessages(MAX_MESSAGES))
                .build();
       ...
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>通过自定义的 <code>Assistant</code> 接口，应用程序可以通过其 <code>chat()</code> 方法向 LLM 发送消息。</p>
</div>
<div class="listingblock">
<div class="content">
<pre>    interface Assistant {
       String chat(@MemoryId String sessionId, @UserMessage String userMessage);
    }</pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="external_config">外部化配置</h3>
<div class="paragraph">
<p>访问模型需要 API 密钥。出于安全考虑，密钥不会硬编码在代码中。应用通过 MicroProfile Config 特性将 API 密钥和 LangChain4j 模型属性外部化，从而支持在不同环境中运行而无需修改代码。详细信息请参考<a href="https://openliberty.io/docs/latest/external-configuration.html">微服务的外部配置</a>文档。</p>
</div>
<div class="paragraph">
<p>请参阅文件：<a href="https://github.com/langchain4j/langchain4j-examples/tree/main/jakartaee-microprofile-example/src/main/java/dev/langchain4j/example/chat/ChatAgent.java">src/main/java/dev/langchain4j/example/chat/ChatAgent.java</a></p>
</div>
<div class="listingblock no_copy">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    <span class="annotation">@Inject</span>
    <span class="annotation">@ConfigProperty</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">hugging.face.api.key</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">private</span> <span class="predefined-type">String</span> HUGGING_FACE_API_KEY;

    <span class="annotation">@Inject</span>
    <span class="annotation">@ConfigProperty</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">chat.model.id</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">private</span> <span class="predefined-type">String</span> CHAT_MODEL_ID;

    <span class="annotation">@Inject</span>
    <span class="annotation">@ConfigProperty</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">chat.model.timeout</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">private</span> <span class="predefined-type">Integer</span> TIMEOUT;

    <span class="annotation">@Inject</span>
    <span class="annotation">@ConfigProperty</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">chat.model.max.token</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">private</span> <span class="predefined-type">Integer</span> MAX_NEW_TOKEN;

    <span class="annotation">@Inject</span>
    <span class="annotation">@ConfigProperty</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">chat.model.temperature</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">private</span> <span class="predefined-type">Double</span> TEMPERATURE;

    <span class="annotation">@Inject</span>
    <span class="annotation">@ConfigProperty</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">chat.memory.max.messages</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">private</span> <span class="predefined-type">Integer</span> MAX_MESSAGES;</code></pre>
</div>
</div>
<div class="paragraph">
<p>要微调 LangChain4j 模型或尝试其他 LLM，只需更新配置文件 <a href="https://github.com/langchain4j/langchain4j-examples/tree/main/jakartaee-microprofile-example/src/main/resources/META-INF/microprofile-config.properties">langchain4j-examples/jakartaee-microprofile-example/src/main/resources/META-INF/microprofile-config.properties</a> 中的值或通过环境变量提供它们。</p>
</div>
<div class="listingblock">
<div class="content">
<pre>hugging.face.api.key=set it by env variable
chat.model.id=NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO
chat.model.timeout=120
chat.model.max.token=200
chat.model.temperature=1.0
chat.memory.max.messages=20</pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="communicate">客户端与 LLM 的通信</h3>
<div class="paragraph">
<p>该应用提供了交互式 UI 客户端，供用户与 LLM 进行通信。Jakarta WebSocket 实现了客户端与 <code>ChatService</code> 服务之间的双向通信。每个客户端通过 HTTP 建立连接，并通过 <code>send()</code> 方法发送消息。</p>
</div>
<div class="paragraph">
<p>请参阅文件：<a href="https://github.com/langchain4j/langchain4j-examples/tree/main/jakartaee-microprofile-example/src/main/webapp/chatroom.js">src/main/webapp/chatroom.js</a></p>
</div>
<div class="listingblock no_copy">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    <span class="reserved">const</span> webSocket = <span class="keyword">new</span> WebSocket(<span class="string"><span class="delimiter">'</span><span class="content">ws://localhost:9080/chat</span><span class="delimiter">'</span></span>);
    ...
    function sendMessage() {
        ...
        var myMessage = document.getElementById(<span class="string"><span class="delimiter">'</span><span class="content">myMessage</span><span class="delimiter">'</span></span>).value;
        ...
        webSocket.send(myMessage);
        ...
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>服务端通过 WebSocket 的 <code>onMessage()</code> 方法接收用户消息，调用 <code>ChatAgent.chat()</code> 方法将消息转发给 LLM，并通过 <code>sendObject()</code> 方法将 LLM 的回复广播回客户端会话。</p>
</div>
<div class="paragraph">
<p>请参阅文件：<a href="https://github.com/langchain4j/langchain4j-examples/tree/main/jakartaee-microprofile-example/src/main/java/dev/langchain4j/example/chat/ChatService.java">src/main/java/dev/langchain4j/example/chat/ChatService.java</a></p>
</div>
<div class="listingblock no_copy">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    <span class="annotation">@OnMessage</span>
    <span class="directive">public</span> <span class="type">void</span> onMessage(<span class="predefined-type">String</span> message, Session session) {
        ...
        try {
            ...
            answer = agent.chat(sessionId, message);
        } <span class="keyword">catch</span> (<span class="exception">Exception</span> e) {
            ...
        }

        <span class="keyword">try</span> {
            session.getBasicRemote().sendObject(answer);
        } <span class="keyword">catch</span> (<span class="exception">Exception</span> e) {
            e.printStackTrace();
        }

    }</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="enable_metrics">启用指标数据</h3>
<div class="paragraph">
<p>为了确定应用程序的性能和健康状况，应用使用 MicroProfile Metrics 通过在 <code>onMessage()</code> 方法上添加 <code>@Timed</code> 注解来收集聊天处理时间。</p>
</div>
<div class="paragraph">
<p>请参阅文件：<a href="https://github.com/langchain4j/langchain4j-examples/tree/main/jakartaee-microprofile-example/src/main/java/dev/langchain4j/example/chat/ChatService.java">src/main/java/dev/langchain4j/example/chat/ChatService.java</a></p>
</div>
<div class="listingblock no_copy">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    <span class="annotation">@OnMessage</span>
    <span class="annotation">@Timed</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">chatProcessingTime</span><span class="delimiter">&quot;</span></span>,
           absolute = <span class="predefined-constant">true</span>,
           description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Time needed chatting to the agent.</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">public</span> <span class="type">void</span> onMessage(<span class="predefined-type">String</span> message, Session session) {
        ...</code></pre>
</div>
</div>
<div class="paragraph">
<p>访问 <a href="http://localhost:9080/metrics?scope=application" class="bare">http://localhost:9080/metrics?scope=application</a> 以查看指标数据。</p>
</div>
<div class="listingblock">
<div class="content">
<pre># HELP chatProcessingTime_seconds Time needed chatting to the agent.
# TYPE chatProcessingTime_seconds summary
chatProcessingTime_seconds{mp_scope="application",quantile="0.5",} 0.0
chatProcessingTime_seconds{mp_scope="application",quantile="0.75",} 0.0
chatProcessingTime_seconds{mp_scope="application",quantile="0.95",} 0.0
chatProcessingTime_seconds{mp_scope="application",quantile="0.98",} 0.0
chatProcessingTime_seconds{mp_scope="application",quantile="0.99",} 0.0
chatProcessingTime_seconds{mp_scope="application",quantile="0.999",} 0.0
chatProcessingTime_seconds_count{mp_scope="application",} 6.0
chatProcessingTime_seconds_sum{mp_scope="application",} 31.674357666
# HELP chatProcessingTime_seconds_max Time needed chatting to the agent.
# TYPE chatProcessingTime_seconds_max gauge
chatProcessingTime_seconds_max{mp_scope="application",} 13.191547042</pre>
</div>
</div>
<div class="paragraph">
<p>如果您对 LangChain4j API 的其他使用方式感兴趣，可以参考此文件中提供的 REST API 示例：<a href="https://github.com/langchain4j/langchain4j-examples/tree/main/jakartaee-microprofile-example/src/main/java/dev/langchain4j/example/rest/ModelResource.java">src/main/java/dev/langchain4j/example/rest/ModelResource.java</a></p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="where_to_next">下一步做什么？</h2>
<div class="sectionbody">
<div class="paragraph">
<p>访问 <a href="https://openliberty.io/guides/" target="_blank" rel="noopener">Open Liberty 指南</a>，学习如何在 Open Liberty 中使用更多 Jakarta EE 和 MicroProfile API。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="help_links">相关链接</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/langchain4j">LangChain4j</a></p>
</li>
<li>
<p><a href="https://huggingface.co/models">Hugging Face LLMs</a></p>
</li>
<li>
<p><a href="https://openliberty.io/guides/jakarta-websocket.html" target="_blank" rel="noopener">Bidirectional communication between services using Jakarta WebSocket</a></p>
</li>
<li>
<p><a href="https://openliberty.io/guides/cdi-intro.html" target="_blank" rel="noopener">Injecting dependencies into microservices</a></p>
</li>
<li>
<p><a href="https://openliberty.io/guides/microprofile-config.html" target="_blank" rel="noopener">Configuring microservices</a></p>
</li>
<li>
<p><a href="https://openliberty.io/guides/microprofile-metrics.html" target="_blank" rel="noopener">Providing metrics from a microservice</a></p>
</li>
</ul>
</div>
</div>
</div>]]></content><author><name>Gilbert Kwan</name></author><category term="blog" /><category term="microprofile" /><category term="jakarta-ee" /><category term="developer-experience" /><summary type="html"><![CDATA[人工智能（Artificial Intelligence，AI）是一个令人兴奋且具有颠覆性的领域，它已经通过实现自动化、改进决策制定和从数据中获取新见解来转变企业甚至整个行业。随着 ChatGPT 等大型语言模型（Large Language Model，LLM）的兴起，AI 的性能及其推动企业价值的潜力发生了重大转变。那么，这将如何影响企业的软件开发以及云原生 Java 应用程序的构建呢？]]></summary></entry><entry><title type="html">在 Open Liberty 25.0.0.9 中为 JWT Builder 新增 ECDH-ES 密钥管理算法的支持</title><link href="https://openliberty.io/zh-Hans/blog/2025/09/09/25.0.0.9.html" rel="alternate" type="text/html" title="在 Open Liberty 25.0.0.9 中为 JWT Builder 新增 ECDH-ES 密钥管理算法的支持" /><published>2025-09-09T00:00:00+00:00</published><updated>2025-09-09T00:00:00+00:00</updated><id>https://openliberty.io/zh-Hans/blog/2025/09/09/25.0.0.9</id><content type="html" xml:base="https://openliberty.io/zh-Hans/blog/2025/09/09/25.0.0.9.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>本次发布在 JWT Builder 中引入了对 ECDH-ES 密钥管理算法的支持，提供了比 RSA-OAEP 更安全的替代方案。</p>
</div>
<div class="paragraph">
<p>在 <a href="/">Open Liberty</a> 25.0.0.9 中：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#ECDH_ES">为 JWT Builder 新增 ECDH-ES 密钥管理算法的支持</a></p>
</li>
<li>
<p><a href="#CVEs">修复安全漏洞（CVE）</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>查看版本 <a href="https://github.com/OpenLiberty/open-liberty/issues?q=label%3Arelease%3A25009+label%3A%22release+bug%22">25.0.0.9</a> 中修复的 bug 列表。</p>
</div>
<div class="paragraph">
<p>浏览<a href="/blog/?search=release&amp;search!=beta">之前的 Open Liberty GA 发布博客</a>。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="run">使用 25.0.0.9 开发和运行应用程序</h2>
<div class="sectionbody">
<div class="paragraph">
<p>如使用 <a href="/guides/maven-intro.html">Maven</a>，在您的 <code>pom.xml</code> 文件中添加以下插件配置：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.11.5<span class="tag">&lt;/version&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>如使用 <a href="/guides/gradle-intro.html">Gradle</a>，在您的 <code>build.gradle</code> 文件中添加：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:3.9.5'
    }
}
apply plugin: 'liberty'</code></pre>
</div>
</div>
<div class="paragraph">
<p>如使用<a href="/docs/latest/container-images.html">容器镜像</a>：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty</code></pre>
</div>
</div>
<div class="paragraph">
<p>或者您也可以访问我们的<a href="/start/">下载页面</a>获取归档包。</p>
</div>
<div class="paragraph">
<p>此外，您若使用 <a href="https://plugins.jetbrains.com/plugin/14856-liberty-tools">IntelliJ IDEA</a>、<a href="https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext">Visual Studio Code</a> 或 <a href="https://marketplace.eclipse.org/content/liberty-tools">Eclipse IDE</a>，还集成使用我们的开源 <a href="https://openliberty.io/docs/latest/develop-liberty-tools.html">Liberty 开发工具 (Liberty developer tools)</a>，在 IDE 内实现应用程序的开发、测试、调试及运行管理等全流程支持。</p>
</div>
<div class="imageblock text-center">
<div class="content">
<a class="image" href="https://stackoverflow.com/tags/open-liberty"><img src="/img/blog/blog_btn_stack_zh_hans.svg" alt="Ask a question on Stack Overflow"></a>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="ECDH_ES">为 JWT Builder 新增 ECDH-ES 密钥管理算法的支持</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Open Liberty 在其 JSON Web Token 1.0（<code>jwt-1.0</code>）功能中新增对 ECDH-ES（Elliptic Curve Diffie-Hellman Ephemeral Static，椭圆曲线 Diffie-Hellman 临时静态）作为密钥管理算法的支持。通过在 <code>jwtBuilder</code> 配置中启用该算法，应用开发者可利用椭圆曲线密码学（Elliptic Curve Cryptography）生成 JSON Web Encryption（JWE）令牌的内容加密密钥（CEK）。</p>
</div>
<div class="paragraph">
<p>与之前支持的 RSA-OAEP 相比，ECDH-ES 提供了更现代、更安全的密钥协商机制。</p>
</div>
<div class="paragraph">
<p>要启用 ECDH-ES，开发者需在 <code>keyManagementKeyAlias</code> 属性中指定一个EC（Elliptic Curve，椭圆曲线）公钥。EC 公私钥对可通过 <code>securityUtility</code> 或 <code>keytool</code> 工具生成，例如：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>./securityUtility createSSLCertificate --sigAlg=SHA256withECDSA --keySize=256 --server=myServer --validity=3650 --password=password</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>keytool -genkeypair -alias eccert -keyalg EC -groupname secp256r1 -validity 3650 -storetype pkcs12 -keystore myKeystore.p12 -storepass password</pre>
</div>
</div>
<div class="paragraph">
<p>在 JSON Web Token 1.0（<code>jwt-1.0</code>）功能的 <code>jwtBuilder</code> 元素中，可通过 <code>keyManagementKeyAlgorithm</code> 属性配置使用 ECDH-ES 密钥管理算法。开发者需通过 <code>keyManagementKeyAlias</code> 属性引用用于 ECDH-ES 密钥管理的 EC 公钥别名，并通过 <code>trustStoreRef</code> 属性指定密钥库。</p>
</div>
<div class="paragraph">
<p>在 <code>server.xml</code> 文件中配置这些特性，示例如下：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;jwtBuilder</span>
    <span class="attribute-name">keyManagementKeyAlgorithm</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">ECDH-ES</span><span class="delimiter">&quot;</span></span>
    <span class="attribute-name">keyManagementKeyAlias</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">myECPublicKey</span><span class="delimiter">&quot;</span></span>
    <span class="attribute-name">trustStoreRef</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">myTrustStore</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">...</span> <span class="tag">/&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>更多关于 <code>jwtBuilder</code> 的配置信息，请参阅 <a href="https://openliberty.io/docs/latest/reference/config/jwtBuilder.html">Open Liberty 官方文档</a>。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="CVEs">本次发布修复的安全漏洞（CVE）</h2>
<div class="sectionbody">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">CVE 编号</th>
<th class="tableblock halign-left valign-top">CVSS 分数</th>
<th class="tableblock halign-left valign-top">漏洞类型</th>
<th class="tableblock halign-left valign-top">受影响版本</th>
<th class="tableblock halign-left valign-top">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2025-36000">CVE-2025-36000</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">4.4</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">存储型跨站脚本（Stored XSS）</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">17.0.0.3-25.0.0.8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">影响 <code>adminCenter-1.0</code> 功能</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2025-36047">CVE-2025-36047</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">5.3</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">拒绝服务（Denial of Service）</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">18.0.0.2-25.0.0.8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">影响 <code>servlet-3.1</code>、<code>servlet-4.0</code>、<code>servlet-5.0</code> 和 <code>servlet-6.0</code> 功能</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2025-48976">CVE-2025-48976</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">7.5</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">拒绝服务（Denial of Service）</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">17.0.0.3-25.0.0.8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">影响 <code>servlet-3.1</code>、<code>servlet-4.0</code>、<code>servlet-5.0</code> 和 <code>servlet-6.0</code> 功能</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2025-36124">CVE-2025-36124</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">5.9</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Bypass security</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">17.0.0.3-25.0.0.8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">影响 <code>wasJmsServer-1.0</code>、<code>wasJmsSecurity-1.0</code>、<code>wasJmsClient-2.0</code>、<code>messagingServer-3.0</code>、<code>messagingSecurity-3.0</code> 和 <code>messagingClient-3.0</code> 功能</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>如需查看历史版本中已修复的安全漏洞，请参阅<a href="/docs/latest/security-vulnerabilities.html">安全漏洞（CVE）列表</a>。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="立即开始使用-open-liberty-25-0-0-9">立即开始使用 Open Liberty 25.0.0.9</h2>
<div class="sectionbody">
<div class="paragraph">
<p>通过 <a href="#run">Maven、Gradle、Docker或下载归档包进行获取</a>.</p>
</div>
</div>
</div>]]></content><author><name>Ismath Badsha</name></author><category term="blog" /><category term="announcements" /><category term="release" /><category term="security" /><summary type="html"><![CDATA[本次发布在 JWT Builder 中引入了对 ECDH-ES 密钥管理算法的支持，提供了比 RSA-OAEP 更安全的替代方案。]]></summary></entry><entry><title type="html">Open Liberty 23.0.0.9中的Spring Boot 3.0支持和新的安全功能</title><link href="https://openliberty.io/zh-Hans/blog/2023/09/19/23.0.0.9.html" rel="alternate" type="text/html" title="Open Liberty 23.0.0.9中的Spring Boot 3.0支持和新的安全功能" /><published>2023-09-19T00:00:00+00:00</published><updated>2023-09-19T00:00:00+00:00</updated><id>https://openliberty.io/zh-Hans/blog/2023/09/19/23.0.0.9</id><content type="html" xml:base="https://openliberty.io/zh-Hans/blog/2023/09/19/23.0.0.9.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>您可以在您的Liberty应用程序中添加新的Spring Boot Support 3.0特性来使用Spring Boot 3.x的功能。现在还可以使用私钥对OpenID Connect客户端进行身份验证，这比使用客户端秘钥更安全。如果使用LTPA或JWT cookies，现在可以根据上下文根为不同的应用程序使用不同的cookies。</p>
</div>
<div class="paragraph">
<p>最后，生日快乐！Open Liberty已经成立6年了，可以看看<a href="/blog/2022/09/21/history-maker-projects.html">我们项目的创建历史</a>。</p>
</div>
<div class="paragraph">
<p>在<a href="/">Open Liberty</a> 23.0.0.9里:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#sb3">支持Spring Boot 3.0</a></p>
</li>
<li>
<p><a href="#jwt">支持OIDC客户端的私钥JWT认证</a></p>
</li>
<li>
<p><a href="#cookie">支持为不同应用程序使用不同的LTPA/JWT cookies</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>查看<a href="https://github.com/OpenLiberty/open-liberty/issues?q=label%3Arelease%3A23009+label%3A%22release+bug%22">23.0.0.9</a>里修复的bug列表.</p>
</div>
<div class="paragraph">
<p>查看<a href="/blog/?search=release&amp;search!=beta">之前的Open Liberty GA发布博客文章</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="run">使用23.0.0.9运行应用程序</h2>
<div class="sectionbody">
<div class="paragraph">
<p>如果您正在使用<a href="/guides/maven-intro.html">Maven</a>, 在您的pom.xml文件里包含以下内容：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.8.2<span class="tag">&lt;/version&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>或者对于<a href="/guides/gradle-intro.html">Gradle</a>, 在您的 build.gradle文件里包含以下内容：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:3.6.2'
    }
}
apply plugin: 'liberty'</code></pre>
</div>
</div>
<div class="paragraph">
<p>或者如果您使用<a href="/docs/latest/container-images.html">容器镜像</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty</code></pre>
</div>
</div>
<div class="paragraph">
<p>或者看看我们的<a href="/start/">下载页面</a>.</p>
</div>
<div class="imageblock text-center">
<div class="content">
<a class="image" href="https://stackoverflow.com/tags/open-liberty"><img src="/img/blog/blog_btn_stack.svg" alt="Ask a question on Stack Overflow"></a>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="sb3">支持Spring Boot 3.0</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Liberty Spring Boot 3.0特性为在Liberty上运行Spring Boot 3.0的应用程序提供了更完整的支持。它还提供了在容器中创建应用程序时<a href="/docs/latest/deploy-spring-boot.html#thin">精简应用程序</a>的功能。</p>
</div>
<div class="paragraph">
<p>之前的Liberty版本提供了对Spring Boot 1.5和Spring Boot 2.0应用程序的支持。Liberty还支持打包成WAR文件的Spring Boot应用程序，这在<a href="https://openliberty.io/blog/2023/06/15/running-spring-boot-3.html">最近的这篇博客文章</a>里有演示。使用Open Liberty 23.0.0.9，您可以通过启用springBoot-3.0特性来部署Spring Boot 3.x的应用程序，可以同时支持JAR和WAR文件类型。</p>
</div>
<div class="paragraph">
<p>在Liberty上运行Spring Boot 3.x的应该程序，您必须使用Java 17或更高版本运行。另外，如果您的应用程序使用<a href="/docs/latest/reference/feature/servlet.html">Jakarta Servlet</a>特性，那么必须是Jakarta Servet 6.0。在server.xml文件中配置这些特性，示例如下：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;features&gt;</span>
   <span class="tag">&lt;feature&gt;</span>springBoot-3.0<span class="tag">&lt;/feature&gt;</span>
   <span class="tag">&lt;feature&gt;</span>servlet-6.0<span class="tag">&lt;/feature&gt;</span>
<span class="tag">&lt;/features&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>与以前版本的Spring Boot support特性一样，您可以将Spring Boot应用程序JAR文件放在/dropins/ Spring /目录中。或者，在server.xml文件中指定<a href="/docs/latest/reference/config/springBootApplication.html">Spring Boot配置元素</a>。例如:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"> <span class="tag">&lt;springBootApplication</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">spring-boot-app</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">location</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">spring-boot-app-0.1.0.jar</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">spring-boot-app</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>有关更多信息，请参见<a href="/docs/latest/deploy-spring-boot.html">配置和部署Spring Boot应用程序</a>。</p>
</div>
<div class="paragraph">
<p>如果您已经使用了以前版本的Spring Boot Support特性，现在正在将您的应用程序迁移到Spring Boot 3，请注意以下要求:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>必须使用<a href="/docs/latest/reference/feature/webProfile-10.0.html">Jakarta EE 10功能</a>.</p>
</li>
<li>
<p>安全配置需要在应用程序中修改. </p>
<div class="ulist">
<ul>
<li>
<p><a href="https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter">没有WebSecurityConfigurerAdapter的Spring Security</a></p>
</li>
<li>
<p><a href="https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html">授权HttpServletRequests</a></p>
</li>
</ul>
</div>
</li>
<li>
<p>新的<a href="/docs/latest/reference/command/server-create.html#_options">服务器模版</a> (<code>springBoot3</code>)可用.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jwt">支持OIDC客户端的私钥JWT认证</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Liberty中的OpenID Connect客户端现在支持带有OpenID Connect令牌端点的‘private_key_jwt’客户端身份验证方法。</p>
</div>
<div class="paragraph">
<p>当OpenID Connect客户端调用OpenID Connect提供程序的令牌端点时，需要向OpenID Connect提供程序提供身份验证数据。客户端可以使用几种不同的方法进行身份验证，但大多数方法都需要客户端密钥。‘private_key_jwt’身份验证方法使客户端能够使用非对称密钥来创建签名的JSON Web令牌(jwt)来进行身份验证，而不是使用客户端秘钥。使用此身份验证方法的OpenID Connect客户端不再需要拥有客户端秘钥。</p>
</div>
<div class="paragraph">
<p>在您的客户端应用程序中，使用‘tokenEndpointAuthMethod’属性的‘private_key_jwt’选项，以及客户端‘server.xml’文件中的‘openidConnectClient’或‘oidcLogin’元素中的‘tokenEndpointAuthSigningAlgorithm’和‘keyAliasName’属性启用此功能。</p>
</div>
<div class="paragraph">
<p>例如，当您使用OpenID Connect Client特性时，需要包括以下配置:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;featureManager&gt;</span>
   <span class="tag">&lt;feature&gt;</span>openidConnectClient-1.0<span class="tag">&lt;/feature&gt;</span>
<span class="tag">&lt;/featureManager&gt;</span>
    ...
<span class="tag">&lt;openidConnectClient</span> <span class="attribute-name">tokenEndpointAuthMethod</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">private_key_jwt</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">keyAliasName</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">privateKeyJwtAliasRS512</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">...</span> <span class="tag">/&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>如果您正在使用社交媒体登录功能，请包括以下配置:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;featureManager&gt;</span>
    <span class="tag">&lt;feature&gt;</span>socialLogin-1.0<span class="tag">&lt;/feature&gt;</span>
<span class="tag">&lt;/featureManager&gt;</span>
...
<span class="tag">&lt;oidcLogin</span> <span class="attribute-name">tokenEndpointAuthMethod</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">private_key_jwt</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">tokenEndpointAuthSigningAlgorithm</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">E512</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">keyAliasName</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">privateKeyJwtAliasES512</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">...</span> <span class="tag">/&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>‘tokenEndpointAuthSigningAlgorithm’属性为用于客户端身份验证的JWT签名指定签名算法。‘keyAliasName’属性指向用于签署JWT的密钥，并且还必须是对应于私钥的公钥的别名。私钥必须位于OIDC客户端配置中由‘sslRef’引用的SSL配置指定的密钥库中。公钥必须位于以下位置之一:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>由‘trustStoreRef’属性指定的信任库</p>
</li>
<li>
<p>由‘sslRef’引用的SSL配置指定的信任库</p>
</li>
<li>
<p>由‘sslRef’引用的SSL配置指定的密钥库</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>有关配置选项的更多信息，请参阅文档:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="/docs/latest/reference/config/openidConnectClient.html">openidConnectClient元素</a></p>
</li>
<li>
<p><a href="/docs/latest/reference/config/oidcLogin.html">oidcLogin元素</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>有关JWT认证的更多信息，请查看：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication">OpenID Connect核心规范</a></p>
</li>
<li>
<p><a href="https://datatracker.ietf.org/doc/html/rfc7523">RFC 7523</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="cookie">支持为不同应用程序使用不同的LTPA/JWT cookies</h2>
<div class="sectionbody">
<div class="paragraph">
<p>在以前的版本中，LTPA和JWT cookies总是将cookie路径设置为/，因此向域上的任何路径发出的任何请求都包含该cookie。现在可以将LTPA或JWT cookie路径设置为应用程序上下文根目录。通过这种配置，您可以为不同的应用程序使用不同的LTPA和JWT令牌。</p>
</div>
<div class="paragraph">
<p>在‘webAppSecurity’元素中启用‘useContextRootForSSOCookiePath’属性。例如，在‘server.xml’中添加以下行:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;webAppSecurity</span> <span class="attribute-name">useContextRootForSSOCookiePath</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">true</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>有关Open Liberty中LTPA的更多信息，请参阅文档:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="/docs/latest/single-sign-on.html#_ltpa">单点登录(SSO)</a></p>
</li>
<li>
<p><a href="/docs/latest/reference/feature/appSecurity-5.0.html">应用程序安全(Jakarta Security)功能</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="现在就开始使用liberty-23-0-0-9">现在就开始使用Liberty 23.0.0.9</h2>
<div class="sectionbody">
<div class="paragraph">
<p>可以通过<a href="#run">Maven、Gradle、Docker以及可下载的归档文件获得</a></p>
</div>
</div>
</div>]]></content><author><name>Laura Cowen</name></author><category term="blog" /><category term="announcements" /><category term="release" /><category term="security" /><category term="spring" /><summary type="html"><![CDATA[您可以在您的Liberty应用程序中添加新的Spring Boot Support 3.0特性来使用Spring Boot 3.x的功能。现在还可以使用私钥对OpenID Connect客户端进行身份验证，这比使用客户端秘钥更安全。如果使用LTPA或JWT cookies，现在可以根据上下文根为不同的应用程序使用不同的cookies。]]></summary></entry><entry><title type="html">实现快速启动云原生Java应用程序的打包方法</title><link href="https://openliberty.io/zh-Hans/blog/2023/06/29/rapid-startup-instanton.html" rel="alternate" type="text/html" title="实现快速启动云原生Java应用程序的打包方法" /><published>2023-06-29T00:00:00+00:00</published><updated>2023-06-29T00:00:00+00:00</updated><id>https://openliberty.io/zh-Hans/blog/2023/06/29/rapid-startup-instanton</id><content type="html" xml:base="https://openliberty.io/zh-Hans/blog/2023/06/29/rapid-startup-instanton.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>您是否知道我们可以重新打包云原生Java应用程序，使其以毫秒为单位启动，而不会影响吞吐量、内存、开发-生产对等性或Java语言特性？并且不需要重构应用程序代码吗？方法就是……</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="提高启动速度的必要性">提高启动速度的必要性</h2>
<div class="sectionbody">
<div class="paragraph">
<p>在无服务器（serverless）环境中，通过在没有请求处理时关闭不需要的应用程序实例，缩容至0（scale-to-zero）可以帮助降低部署应用程序的总体云计算成本。当应用程序的活动开始时，新的实例能快速启动，而不会给应用程序终端用户带来明显的延迟。</p>
</div>
<div class="paragraph">
<p>尽管JDK技术有很大改进，使得它可以在不到1秒的时间内启动，比如类数据共享和动态AOT编译，但它的启动速度仍然不够快，无法支持从零缩放。但是，JDK对于优化吞吐量和内存、确保开发与生产的一致性以及支持各种Java语言特性等非常重要。那么，我们如何既改善启动时间，又从完整运行的JDK中获益呢？</p>
</div>
<div class="paragraph">
<p>Open Liberty运行时中的InstantOn功能使用IBM Semeru JDK和称为<a href="https://criu.org/Main_Page">用户空间中的检查点/恢复点</a>(CRIU)的Linux技术来获取应用程序进程的检查点或时间点快照。然后可以非常快速地恢复这个检查点，使应用程序进程恢复到使用检查点时的状态。应用程序可以多次恢复，因为Open Liberty和Semeru JDK保留了容器中每个恢复进程的唯一性。每个恢复的应用程序进程都可以不必先经历整个启动序列而运行，从而节省高达90%的启动时间（取决于您的应用程序）。InstantOn只需要对Java应用程序进行很少的修改就可以实现这种改进。</p>
</div>
<div class="paragraph">
<p>下图演示了如何在容器镜像构建期间生成检查点，通过将它们恢复到应用程序进程的检查点阶段来快速启动生产环境中多个应用程序实例的。</p>
</div>
<div class="imageblock text-center img_border_light">
<div class="content">
<img src="/img/blog/checkpoint4.jpg" alt="diagram of the checkpoint and restore process" width="70%">
</div>
</div>
<div class="paragraph">
<p>InstantOn不能在容器镜像构建之外使用。应用程序容器镜像提供了一个一致的环境，这是确保Open Liberty应用程序进程可靠恢复所必需的。由于InstantOn检查点包含在应用程序容器镜像的最后一层中，因此从检查点创建到镜像恢复期间，镜像底层中的资源不会发生变化。</p>
</div>
<div class="paragraph">
<p>下面的教程将引导您使用Linux上的 Open Liberty Java运行时、InstantOn、IBM Semeru JDK和Podman容器工具对应用程序进行容器化。有关使用Open Liberty容器化应用程序的信息，请参阅<a href="/guides/containerize-podman.html">使用Podman进行容器化微服务</a>指南。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="检查点恢复容器化应用程序的先决条件">检查点/恢复容器化应用程序的先决条件</h2>
<div class="sectionbody">
<div class="paragraph">
<p>目前，<a href="/blog/2023/06/27/23.0.0.6.html">Open Liberty 23.0.0.6</a>或更高版本只支持在x86-64/amd64架构上运行InstantOn。我们所有的测试都是在RHEL 9.0和Ubuntu 22.04上完成的，但如果具备以下先决条件，也可以在其他Linux发行版本上运行:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>内核必须支持Linux <a href="https://man7.org/linux/man-pages/man7/capabilities.7.html">CAP_CHECKPOINT_RESTORE</a>功能，此功能是在内核5.9版本中引入的</p>
</li>
<li>
<p>必须安装Linux发行版最新版本的Podman</p>
</li>
<li>
<p>Linux发行版必须允许使用Podman或Docker来执行特权容器构建</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>有关运行时和主机构建系统先决条件的更多信息，请参阅<a href="/docs/latest/instanton.html#prereq">Open Liberty InstantOn文档</a>。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="创建一个应用程序war文件">创建一个应用程序WAR文件</h2>
<div class="sectionbody">
<div class="paragraph">
<p>如果您手上没有自己的应用程序，您可以按照<a href="/guides/getting-started.html">Open Liberty入门指南</a>中的示例应用程序进行操作：</p>
</div>
<div class="paragraph">
<p>首先，克隆指南的<a href="https://github.com/openliberty/guide-getting-started">Git存储库</a>：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">git clone https://github.com/openliberty/guide-getting-started.git
cd guide-getting-started</code></pre>
</div>
</div>
<div class="paragraph">
<p>然后，在&#8217;finish/'目录下构建应用程序，并将其部署到Open Liberty：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">cd finish
mvn liberty:run</code></pre>
</div>
</div>
<div class="paragraph">
<p>当您看到下面的消息时，您的Open Liberty实例已经准备好了:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">The defaultServer server is ready to run a smarter planet.</code></pre>
</div>
</div>
<div class="paragraph">
<p>在http://localhost:9080/dev/system/properties的URL上查看该服务。在启动Open Liberty的命令行会话中按<strong>CTRL+C</strong>停止正在运行的Open Liberty实例。</p>
</div>
<div class="paragraph">
<p>最后，为应用程序构建WAR：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">mvn package</code></pre>
</div>
</div>
<div class="paragraph">
<p>这个命令会构建一个`target/guide-getting-started.war`的归档。现在，我们可以在使用InstantOn特性的容器镜像中加入这个WAR。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="测试应用程序的启动时间">测试应用程序的启动时间</h2>
<div class="sectionbody">
<div class="paragraph">
<p>为了比较使用和不使用InstantOn时Open Liberty应用程序容器镜像启动所需的时间，我们首先先介绍如何在不使用InstantOn的情况下构建容器镜像。然后，再说明如何使用InstantOn构建并运行生成的容器。</p>
</div>
<div class="sect2">
<h3 id="在没有instanton的情况下容器化open-liberty应用程序">在没有InstantOn的情况下容器化Open Liberty应用程序</h3>
<div class="paragraph">
<p>构建不使用InstantOn的应用程序容器镜像：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">podman build -t getting-started .</code></pre>
</div>
</div>
<div class="paragraph">
<p>这个命令创建的是一个不包含任何检查点镜像的getting-started入门容器镜像。</p>
</div>
<div class="paragraph">
<p>运行这个应用容器：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">podman run --name getting-started --rm -p 9080:9080 getting-started</code></pre>
</div>
</div>
<div class="paragraph">
<p>请注意Open Liberty报告它已启动所花费的时间，并通过http://localhost:9080/dev/system/properties URL检查容器中运行的服务。检出应用程序后，在运行`podman run`命令的命令行会话中按<strong>CTRL+C</strong>停止正在运行的容器。</p>
</div>
</div>
<div class="sect2">
<h3 id="用instanton容器化open-liberty应用程序">用InstantOn容器化Open Liberty应用程序</h3>
<div class="paragraph">
<p>Open Liberty容器镜像包含构建具有检查点运行时进程的应用程序容器镜像的先决条件。应用程序可以使用Open Liberty镜像作为基础来构建自己的应用程序容器镜像，并以此为基础，使用检查点进程创建自己的应用程序容器镜像。</p>
</div>
<div class="sect3">
<h4 id="build">构建应用程序容器镜像并检查应用程序</h4>
<div class="paragraph">
<p>通过在应用程序容器镜像的构建步骤中启动Open Liberty运行时，可以创建一个InstantOn检查点。在此启动期间，运行时处理配置、加载所有启用的功能并开始处理配置的应用程序。根据应用程序的需要，您可以在Open Liberty启动期间选择两个特定阶段中的一个来检查进程。您必须配置Dockerfile以指定您选择的阶段(稍后会介绍)。</p>
</div>
<div class="paragraph">
<p>官方link:/docs/latest/container-images.htmlIBM Container Registry] (ICR)的Open Liberty镜像包含了InstantOn检查应用程序进程所需的所有先决条件。对于本例，`getting-started`入门应用程序容器镜像使用来自ICR的`icr.io/appcafe/open-liberty:full-java11-openj9-ubi`映像作为父镜像。目前，InstantOn只支持基于Java 11和Java 17的Open Liberty UBI镜像。</p>
</div>
<div class="paragraph">
<p>更新应用的Dockerfile文件，在文件末尾添加`checkpoint.sh`脚本的`RUN`命令，如下面的例子所示</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">FROM icr.io/appcafe/open-liberty:full-java11-openj9-ubi
ARG VERSION=1.0
ARG REVISION=SNAPSHOT
LABEL \
  org.opencontainers.image.authors=&quot;Your Name&quot; \
  org.opencontainers.image.vendor=&quot;IBM&quot; \
  org.opencontainers.image.url=&quot;local&quot; \
  org.opencontainers.image.source=&quot;https://github.com/OpenLiberty/guide-getting-started&quot; \
  org.opencontainers.image.version=&quot;$VERSION&quot; \
  org.opencontainers.image.revision=&quot;$REVISION&quot; \
  vendor=&quot;Open Liberty&quot; \
  name=&quot;system&quot; \
  version=&quot;$VERSION-$REVISION&quot; \
  summary=&quot;The system microservice from the Getting Started guide&quot; \
  description=&quot;This image contains the system microservice running with the Open Liberty runtime.&quot;

COPY --chown=1001:0 src/main/liberty/config/ /config/
COPY --chown=1001:0 target/*.war /config/apps/

RUN configure.sh
RUN checkpoint.sh afterAppStart</code></pre>
</div>
</div>
<div class="paragraph">
<p>此配置将应用程序进程检查点添加为应用程序容器镜像的最后一层。`checkpoint.sh`脚本允许指定&#8217;afterAppStart&#8217;或&#8217;beforeAppStart'，以指示在启动的哪个阶段执行进程检查。</p>
</div>
<div class="paragraph">
<p>两个选项可选来确定检查点发生在应用程序启动之前还是之后：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>beforeAppStart</code>: 检查点发生在处理配置的应用程序元数据之后。如果应用程序有作为应用程序启动的一部分运行的任何组件，则在执行应用程序中的任一代码之前采取检查点。这个选项是InstantOn提供的最早检查点阶段。</p>
</li>
<li>
<p><code>afterAppStart</code>: 此选项是检查点能够发生的最后阶段，因此在恢复应用程序实例时，它有可能提供最快的启动时间。检查点发生在所有已配置的应用程序报告为已启动之后。它发生在打开任何监听端口以侦听应用程序的传入请求之前。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>afterAppStart`阶段会为应用程序提供最快的启动时间，但它也可能导致一些应用程序代码在服务器进程检查点发生之前运行。由于本教程中使用的`getting-started`应用程序在其启动逻辑中没有做任何会导致恢复问题的事情，因此我们可以选择使用`afterAppStart</code> 。</p>
</div>
<div class="paragraph">
<p>为了InstantOn创建检查点并恢复进程，CRIU二进制文件需要额外的<a href="/docs/latest/instanton.html#linux-capabilities">Linux功能</a>。虽然Open Liberty容器镜像包含赋予二进制文件的必要功能。但是，容器在启动时还必须要赋这些功能。</p>
</div>
<div class="paragraph">
<p>使用podman，您可以使用`-–cap-add`和`--security-opt`选项为容器构建赋予必要的功能，以便在容器构建步骤中创建检查点。启动Podman容器的用户必须具有赋予它必要的Linux功能的权限，因此必须以root或sudo身份运行以下命令：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">podman build \
   -t dev.local/getting-started-instanton \
   --cap-add=CHECKPOINT_RESTORE \
   --cap-add=SYS_PTRACE\
   --cap-add=SETPCAP \
   --security-opt seccomp=unconfined .</code></pre>
</div>
</div>
<div class="paragraph">
<p>Dockerfile中的最后一条指令是运行`checkpoint.sh`脚本。当您执行前面的Podman构建命令时，它会启动Open Liberty并在Dockerfile中指定的阶段执行检查点。容器进程数据持久化后，Open Liberty停止，容器镜像构建完成。生成的应用程序容器镜像包含检查点进程数据作为容器镜像的最后一层。输出如下面的例子:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">Performing checkpoint --at=afterAppStart

Launching defaultServer (Open Liberty 23.0.0.6/wlp-1.0.78.cl230620230612-1100) on Eclipse OpenJ9 VM, version 11.0.19+7 (en_US)
[AUDIT   ] CWWKE0001I: The server defaultServer has been launched.
[AUDIT   ] CWWKG0093A: Processing configuration drop-ins resource: /opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/keystore.xml
[AUDIT   ] CWWKG0093A: Processing configuration drop-ins resource: /opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/open-default-port.xml
[AUDIT   ] CWWKZ0058I: Monitoring dropins for applications.
[AUDIT   ] CWWKZ0001I: Application guide-getting-started started in 1.886 seconds.
[AUDIT   ] CWWKC0451I: A server checkpoint &quot;afterAppStart&quot; was requested. When the checkpoint completes, the server stops.</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="run">运行InstantOn应用程序映像</h4>
<div class="paragraph">
<p>使用以下命令运行`getting-started-instanton`容器:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">podman run \
  --rm \
  --cap-add=CHECKPOINT_RESTORE \
  --cap-add=SETPCAP \
  --security-opt seccomp=unconfined \
  -p 9080:9080 \
  getting-started-instanton</code></pre>
</div>
</div>
<div class="paragraph">
<p>`--cap-add`的选项赋予容器两个Linux功能，这两个功能是CRIU恢复应用程序进程所需的。当Open Liberty恢复应用程序进程时，它会输出以下消息:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">[AUDIT   ] Launching defaultServer (Open Liberty 23.0.0.6/wlp-1.0.78.cl230620230612-1100) on Eclipse OpenJ9 VM, version 11.0.19+7 (en_US)
[AUDIT   ] CWWKZ0001I: Application guide-getting-started started in 0.233 seconds.
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://850ba43df239:9080/dev/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://850ba43df239:9080/metrics/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://850ba43df239:9080/health/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://850ba43df239:9080/ibm/api/
[AUDIT   ] CWWKC0452I: The Liberty server process resumed operation from a checkpoint in 0.283 seconds.
[AUDIT   ] CWWKF0012I: The server installed the following features: [cdi-4.0, distributedMap-1.0, jndi-1.0, json-1.0, jsonb-3.0, jsonp-2.1, monitor-1.0, mpConfig-3.0, mpHealth-4.0, mpMetrics-5.0, restfulWS-3.1, restfulWSClient-3.1, ssl-1.0, transportSecurity-1.0].
[AUDIT   ] CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in 0.297 seconds.</code></pre>
</div>
</div>
<div class="paragraph">
<p>如果Open Liberty未能恢复检查点进程，它会通过启动没有检查点的镜像来恢复，并输出以下消息:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="console">CWWKE0957I: Restoring the checkpoint server process failed. Check the /logs/checkpoint/restore.log log to determine why the checkpoint process was not restored. Launching the server without using the checkpoint image.</code></pre>
</div>
</div>
<div class="paragraph">
<p>检查Open Liberty启动所需的时间，并将其与没有InstantOn的时间进行比较。</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="性能结果">性能结果</h2>
<div class="sectionbody">
<div class="paragraph">
<p>InstantOn通过从检查点状态恢复进程，显著改善了Open Liberty应用程序的启动时间。对第一次响应时间(即服务第一个请求所花费的时间)的改进也令人印象深刻，但在这种情况下，显然更多的应用程序逻辑是在恢复之后运行。我们测量了在容器中运行和使用afterAppStart 检查点两种情况下运行多个应用程序的指标。</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/HotswapProjects/pingperf-quarkus/">Pingperf</a>是一个非常简单的ping类型应用程序，涉及单个REST端点</p>
</li>
<li>
<p><a href="https://github.com/johnaohara/quarkusRestCrudDemo/">Rest crud</a>有点复杂，涉及JPA和远程数据库</p>
</li>
<li>
<p><a href="https://github.com/blueperf/acmeair-mainservice-java#acme-air-main-service---javaliberty/">AcmeAir Microservice Main</a>使用MicroProfile功能</p>
</li>
</ul>
</div>
<div class="imageblock text-center">
<div class="content">
<img src="/img/blog/startup.png" alt="Startup time in ms" width="70%">
</div>
</div>
<div class="paragraph">
<p><br>
<br></p>
</div>
<div class="imageblock text-center">
<div class="content">
<img src="/img/blog/response.png" alt="First response time in ms" width="70%">
</div>
</div>
<div class="paragraph">
<p>这些实验表明，与没有InstantOn的普通JVM模式相比，所有3个应用程序的启动时间都有了健康的改善，第一次响应的时间也提高了8.8倍。<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="总结">总结</h2>
<div class="sectionbody">
<div class="paragraph">
<p>这篇文章描述了如何通过使用Open Liberty InstantOn特性生成应用程序容器镜像来配置云原生应用程序，使其几乎立即启动。InstantOn的关键价值主张是，您可以重新打包云原生Java应用程序，使其以毫秒为单位启动，而不会影响吞吐量、内存、开发-生产对等性或Java语言特性。
该特性现在可以在公共云AWS EKS和Azure AKS环境中X86-64/AMD64平台上的<a href="/blog/2023/06/27/23.0.0.6.html">Open Liberty 23.0.0.6</a>中可用。</p>
</div>
<div class="paragraph">
<p>在未来，我们计划扩大我们的平台覆盖范围，并扩展到能够在更受管理的公共云和混合云环境中运行。我们还打算探索更大的Open Liberty特性集来支持InstantOn。有关Open Liberty InstantOn的更多详细信息，请参阅link:/docs/latest/instanton.html[使用Open Liberty InstantOn的容器化应用程序的快速启动文档】，该文档会包含已知限制条件以及Semeru JDK对该特性支持情况的更详细讨论。</p>
</div>
</div>
</div>
<div id="footnotes">
<hr>
<div class="footnote" id="_footnotedef_1">
<a href="#_footnoteref_1">1</a>. 这些实验是在24核Linux X86-64系统上运行，使用 `taskset -c`为每种情况下容器中运行的Open Liberty进程分配4核CPU资源。启动时间是计算的从Open Liberty服务器启动的开始时间到服务器准备好接受请求的时间，表示为messages.log里的信息：“ The &lt;server name&gt; server is ready to run a smarter planet”。启动容器本身所需的时间也包含在显示的结果中。InstantOn和应用程序的正常启动时间在这里以毫秒为单位显示。您的结果可能会根据您的环境、系统上安装的硬件和软件以及其他因素而有所不同。
</div>
</div>]]></content><author><name>Thomas Watson</name></author><category term="blog" /><category term="microprofile" /><category term="jakarta-ee" /><category term="developer-experience" /><category term="performance-enhancements" /><category term="devops" /><summary type="html"><![CDATA[您是否知道我们可以重新打包云原生Java应用程序，使其以毫秒为单位启动，而不会影响吞吐量、内存、开发-生产对等性或Java语言特性？并且不需要重构应用程序代码吗？方法就是……]]></summary></entry><entry><title type="html">Open Liberty 23.0.0.3里对Jakarta EE 10, MicroProfile 6, 和Java SE 20的支持</title><link href="https://openliberty.io/zh-Hans/blog/2023/04/04/23.0.0.3.html" rel="alternate" type="text/html" title="Open Liberty 23.0.0.3里对Jakarta EE 10, MicroProfile 6, 和Java SE 20的支持" /><published>2023-04-04T00:00:00+00:00</published><updated>2023-04-04T00:00:00+00:00</updated><id>https://openliberty.io/zh-Hans/blog/2023/04/04/23.0.0.3</id><content type="html" xml:base="https://openliberty.io/zh-Hans/blog/2023/04/04/23.0.0.3.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>翻译：Haiyan Zhang</p>
</div>
<div class="paragraph">
<p>我们很高兴地宣布 Open Liberty 23.0.0.3发布了，这是自5年前首次亮相以来最大的运行时版本之一！ 此版本包括 Jakarta EE 10 Platform、Web Profile，并且首次包含Core Profile。还在构成profiles的大部分功能中添加了许多新的增强功能。</p>
</div>
<div class="paragraph">
<p>包含Jakarta EE Core Profile 10的MicroProfile 6也将在23.0.0.3版本中正式亮相。它包括新的MicroProfile Telemetry 1.0特性，以及对Metrics、OpenAPI和JWT Authentication规范的更新。</p>
</div>
<div class="paragraph">
<p>在23.0.0.3发行版中还引入了对Java SE 20(撰写本文时的最新版本)的支持，并提供了各种新特性和更改。许多值得注意的错误修复也包含在这个Open Liberty版本中。</p>
</div>
<div class="paragraph">
<p><a href="/">Open Liberty</a> 23.0.0.3里包含:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#jakarta10">Jakarta EE 10 Core Profile, Web Profile, 和Platform</a></p>
<div class="ulist">
<ul>
<li>
<p><a href="#coreprofile">Core Profile</a></p>
</li>
<li>
<p><a href="#webprofile">Web Profile</a></p>
</li>
<li>
<p><a href="#platform">Platform</a></p>
</li>
</ul>
</div>
</li>
<li>
<p><a href="#mp6">MicroProfile 6.0</a></p>
<div class="ulist">
<ul>
<li>
<p><a href="#telemetry">MicroProfile Telemetry 1.0</a></p>
</li>
<li>
<p><a href="#metrics">MicroProfile Metrics 5.0</a></p>
</li>
<li>
<p><a href="#openapi">MicroProfile OpenAPI 3.1</a></p>
</li>
<li>
<p><a href="#jwt">MicroProfile JWT Authentication 2.1</a></p>
</li>
</ul>
</div>
</li>
<li>
<p><a href="#java20">对Java SE 20的支持</a></p>
</li>
<li>
<p><a href="#bugs">值得注意的错误修复</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>查看 <a href="/blog/?search=release&amp;search!=beta">之前Open Liberty GA 发布的blog</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="run">使用Open Liberty 23.0.0.3运行应用程序</h2>
<div class="sectionbody">
<div class="paragraph">
<p>如果您使用 <a href="/guides/maven-intro.html">Maven</a>, 可以参考:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;dependency&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>openliberty-runtime<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>23.0.0.3<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;type&gt;</span>zip<span class="tag">&lt;/type&gt;</span>
<span class="tag">&lt;/dependency&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>或者是 <a href="/guides/gradle-intro.html">Gradle</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">dependencies {
    libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '[23.0.0.3,)'
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>或者您使用的是 <a href="/docs/latest/container-images.html">container images</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty</code></pre>
</div>
</div>
<div class="paragraph">
<p>或者可以查看我们的 <a href="/downloads/">下载页面</a>, 我们已经添加了Jakarta EE 10 和MicroProfile 6 的包.</p>
</div>
<div class="imageblock text-center">
<div class="content">
<a class="image" href="https://stackoverflow.com/tags/open-liberty"><img src="/img/blog/blog_btn_stack.svg" alt="Stack Overflow中提问"></a>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jakarta10">Jakarta EE 10 Core Profile, Web Profile还有Platform</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Jakarta EE 10 Core Profile, Web Profile和Platform现在正式支持Open Liberty! 我们首先要感谢所有在我们的各种测试版中提供反馈的人。</p>
</div>
<div class="paragraph">
<p>Jakarta EE 10标志着一个重要的里程碑。这是自2017年Java EE 8以来第一个提供规范更新的Jakarta版本，因此也是自Eclipse基金会接管该规范以来第一个提供规范更新的版本。在对现有规范的众多更新中，它还引入了Core Profile。Core Profile的目标是轻量级运行时，比如Open Liberty，它针对运行云原生Java微服务进行了优化。</p>
</div>
<div class="paragraph">
<p>Jakarta Platform以及Core和Web Profile由以下规范组成：</p>
</div>
<div class="sect2">
<h3 id="coreprofile">Jakarta EE Core Profile 10</h3>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 44.4444%;">
<col style="width: 22.2222%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">规范</th>
<th class="tableblock halign-left valign-top">变更</th>
<th class="tableblock halign-left valign-top">Liberty特性文档
<a id="cdi-lite"></a></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/cdi/4.0/">Context and Dependency Injection 4.0 Lite</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>新规</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/cdi-4.0.html">cdi-4.0</a></p>
<p class="tableblock"><a id="jsonb"></a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/jsonb/3.0/">JSON Binding 3.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/jsonb-3.0.html">jsonb-3.0</a></p>
<p class="tableblock"><a id="rest"></a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/restful-ws/3.1/">RESTful Web Services 3.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/restfulWS-3.1.html">restfulWS-3.1</a>, <a href="/docs/latest/reference/feature/restfulWSClient-3.1.html">restfulWSClient-3.1</a></p>
<p class="tableblock"><a id="jsonp"></a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/jsonp/2.1/">JSON Processing 2.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/jsonp-2.1.html">jsonp-2.1</a></p>
<p class="tableblock"><a id="cdi"></a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/annotations/2.1/">Annotations 2.1</a> &amp; <a href="https://jakarta.ee/specifications/interceptors/2.1/">Interceptors 2.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/cdi-4.0.html">cdi-4.0</a></p>
<p class="tableblock"><a id="cdi"></a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/dependency-injection/2.0/">Dependency Injection 2.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">未变更</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/cdi-4.0.html">cdi-4.0</a></p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="webprofile">Jakarta EE Web Profile 10</h3>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 44.4444%;">
<col style="width: 22.2222%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">规范</th>
<th class="tableblock halign-left valign-top">变更</th>
<th class="tableblock halign-left valign-top">Liberty特性文档</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/coreprofile/10/">Jakarta EE Core Profile 10</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>新规</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#coreprofile">See previous table</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/authentication/3.0/">Authentication 3.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/appAuthentication-3.0.html">appAuthentication-3.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/cdi/4.0/">Context and Dependency Injection 4.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/cdi-4.0.html">cdi-4.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/concurrency/3.0/">Concurrency 3.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/concurrent-3.0.html">concurrent-3.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/expression-language/5.0/">Expression Language 5.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/expressionLanguage-5.0.html">expressionLanguage-5.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/faces/4.0/">Faces 4.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/faces-4.0.html">faces-4.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/security/3.0/">Security 3.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/appSecurity-5.0.html">appSecurity-5.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/servlet/6.0/">Servlet 6.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/servlet-6.0.html">servlet-6.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/tags/3.0/">Standard Tag Library 3.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/pages-3.1.html">pages-3.1</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/persistence/3.1/">Persistence 3.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/persistence-3.1.html">persistence-3.1</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/pages/3.1/">Server Pages 3.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/pages-3.1.html">pages-3.1</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/websocket/2.1/">WebSocket 2.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/websocket-2.1.html">websocket-2.1</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/bean-validation/3.0/">Bean Validation 3.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">未变更</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/beanValidation-3.0.html">beanValidation-3.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/debugging/2.0/">Debugging Support for Other Languages 2.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">未变更</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">不适用</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/enterprise-beans/4.0/">Enterprise Beans 4.0 Lite</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">未变更</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/enterpriseBeansLite-4.0.html">enterpriseBeansLite-4.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/managedbeans/2.0/">Managed Beans 2.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">未变更</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/managedBeans-2.0.html">managedBeans-2.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/transactions/2.0/">Transactions 2.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">未变更</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">不适用 (见 <a href="/docs/latest/reference/javadoc/liberty-jakartaee10-javadoc.html?package=allclasses-frame.html&amp;class=jakarta/transaction/package-summary.html">Javadoc</a>)</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="platform">Jakarta EE Platform 10</h3>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 44.4444%;">
<col style="width: 22.2222%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">规范</th>
<th class="tableblock halign-left valign-top">变更</th>
<th class="tableblock halign-left valign-top">Liberty特性文档</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/webprofile/10/">Jakarta EE Web Profile 10</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#webprofile">见上表</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/authorization/2.1/">Authorization 2.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/appAuthorization-2.1.html">appAuthorization-2.1</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/activation/2.1/">Activation 2.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">不适用 (见 <a href="/docs/latest/reference/javadoc/liberty-jakartaee10-javadoc.html?package=allclasses-frame.html&amp;class=jakarta/activation/package-summary.html">Javadoc</a>)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/batch/2.1/">Batch 2.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/batch-2.1.html">batch-2.1</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/connectors/2.1/">Connectors 2.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/connectors-2.1.html">connectors-2.1</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/mail/2.1/">Mail 2.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/mail-2.1.html">mail-2.1</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/messaging/3.1/">Messaging 3.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/messaging-3.1.html">messaging-3.1</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/enterprise-beans/4.0/">Enterprise Beans 4.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">未变更</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/enterpriseBeans-4.0.html">enterpriseBeans-4.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/xml-binding/4.0/">XML Binding 4.0</a> (optional)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/xmlBinding-4.0.html">xmlBinding-4.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/xml-web-services/4.0/">XML Web Services 4.0</a> (optional)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/xmlWS-4.0.html">xmlWS-4.0</a></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Liberty为运行包含在Jakarta EE 10 Web Profile (webProfile-10.0)和Jakarta EE 10 Platform (jakartaee-10.0)中的所有组件规范提供了便利的特性。这些便利的特性使您能够使用各自规范中的所有API快速开发应用程序。对于应用程序客户端中的Jakarta EE 10特性，请使用Liberty jakartaeeClient-10.0特性。</p>
</div>
<div class="paragraph">
<p>要使用Jakarta EE Platform 10特性，请在server.xml文件里添加jakartaee-10.0 feature</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">  <span class="tag">&lt;featureManager&gt;</span>
    <span class="tag">&lt;feature&gt;</span>jakartaee-10.0<span class="tag">&lt;/feature&gt;</span>
  <span class="tag">&lt;/featureManager&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>或者，要启用Jakarta EE Web Profile 10功能，请在server.xml文件中添加webProfile-10.0 feature:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">  <span class="tag">&lt;featureManager&gt;</span>
    <span class="tag">&lt;feature&gt;</span>webProfile-10.0<span class="tag">&lt;/feature&gt;</span>
  <span class="tag">&lt;/featureManager&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>虽然没有针对Core Profile的便利功能，但您可以通过server.xml文件里添加以下功能来启用等效功能：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">  <span class="tag">&lt;featureManager&gt;</span>
    <span class="tag">&lt;feature&gt;</span>jsonb-3.0<span class="tag">&lt;/feature&gt;</span>
    <span class="tag">&lt;feature&gt;</span>jsonp-2.1<span class="tag">&lt;/feature&gt;</span>
    <span class="tag">&lt;feature&gt;</span>cdi-4.0<span class="tag">&lt;/feature&gt;</span>
    <span class="tag">&lt;feature&gt;</span>restfulWS-3.1<span class="tag">&lt;/feature&gt;</span>
  <span class="tag">&lt;/featureManager&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>要在应用程序客户端容器上运行Jakarta EE 10特性，请在应用程序的client .xml文件中添加以下条目:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">  <span class="tag">&lt;featureManager&gt;</span>
    <span class="tag">&lt;feature&gt;</span>jakartaeeClient-10.0<span class="tag">&lt;/feature&gt;</span>
  <span class="tag">&lt;/featureManager&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>更多的信息请参考</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://jakarta.ee/specifications/platform/10/">Jakarta EE Platform 10</a>, <a href="https://jakarta.ee/specifications/webprofile/10/">Jakarta EE Web Profile 10</a>, and <a href="https://jakarta.ee/specifications/coreprofile/10/">Jakarta EE Core Profile 10</a> 规范.</p>
</li>
<li>
<p><a href="/docs/latest/reference/javadoc/liberty-jakartaee10-javadoc.html">Jakarta EE 10 Javadoc</a></p>
</li>
<li>
<p><a href="/docs/latest/reference/diff/jakarta-ee10-diff.html">Jakarta EE 10 和 9.1的区别</a></p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="mp6">MicroProfile 6.0</h2>
<div class="sectionbody">
<div class="paragraph">
<p>MicroProfile在业界如何优化Java微服务上持续创新。MicroProfile 6.0版本允许应用程序使用MicroProfile APIs和 Jakarta EE Core Profile 10以及其他各种新功能和改进。MicroProfile 6.0包含以下规范:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 44.4444%;">
<col style="width: 22.2222%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">规范</th>
<th class="tableblock halign-left valign-top">变更</th>
<th class="tableblock halign-left valign-top">Liberty特性文档

<a id="telemetry"></a></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/eclipse/microprofile-telemetry/releases/tag/1.0">MicroProfile Telemetry 1.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>新规</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/mpTelemetry-1.0.html">mpTelemetry-1.0</a></p>
<p class="tableblock"><a id="metrics"></a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/eclipse/microprofile-metrics/releases/tag/5.0">MicroProfile Metrics 5.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">重大更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/mpMetrics-5.0.html">mpMetrics-5.0</a></p>
<p class="tableblock"><a id="openapi"></a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/eclipse/microprofile-open-api/releases/tag/3.1">MicroProfile OpenAPI 3.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/mpOpenAPI-3.1.html">mpOpenAPI-3.1</a></p>
<p class="tableblock"><a id="jwt"></a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/eclipse/microprofile-jwt-auth/releases/tag/2.1">MicroProfile JWT Authentication 2.1</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">次要更新</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/mpJwt-2.1.html">mpJwt-2.1</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/eclipse/microprofile-config/releases/tag/3.0.2">MicroProfile Config 3.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">未变更</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/mpConfig-3.0.html">mpConfig-3.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/eclipse/microprofile-health/releases/tag/4.0.1">MicroProfile Health 4.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">未变更</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/mpHealth-4.0.html">mpHealth-4.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/eclipse/microprofile-rest-client/releases/tag/3.0.1">MicroProfile Rest Client 3.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">未变更</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/mpRestClient-3.0.html">mpRestClient-3.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/eclipse/microprofile-fault-tolerance/releases/tag/4.0.2">MicroProfile Fault Tolerance 4.0</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">未变更</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="/docs/latest/reference/feature/mpFaultTolerance-4.0.html">mpFaultTolerance-4.0</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://jakarta.ee/specifications/coreprofile/10/">Jakarta EE Core Profile 10</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">新规</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#coreprofile">见 Core Profile table</a></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>要使用所有MicroProfile 6特性，请在server.xml文件中添加microProfile-6.0 feature:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">  <span class="tag">&lt;featureManager&gt;</span>
    <span class="tag">&lt;feature&gt;</span>microProfile-6.0<span class="tag">&lt;/feature&gt;</span>
  <span class="tag">&lt;/featureManager&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>可以通过MicroProfile 6.0 specification, release, Javadoc, 还有Differences between MicroProfile 6.0 and 5.0查看更多信息</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="java20">对Java SE 20的支持</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Java 20包含下面的特性和变更：</p>
</div>
<div class="ulist">
<ul>
<li>
<p>429: <a href="https://openjdk.org/jeps/429">Scoped Values (Incubator)</a></p>
</li>
<li>
<p>432: <a href="https://openjdk.org/jeps/432">Record Patterns (Second Preview)</a></p>
</li>
<li>
<p>433: <a href="https://openjdk.org/jeps/433">Pattern Matching for switch (Fourth Preview)</a></p>
</li>
<li>
<p>434: <a href="https://openjdk.org/jeps/434">Foreign Function &amp; Memory API (Second Preview)</a></p>
</li>
<li>
<p>436: <a href="https://openjdk.org/jeps/436">Virtual Threads (Second Preview)</a></p>
</li>
<li>
<p>437: <a href="https://openjdk.org/jeps/437">Structured Concurrency (Second Incubator)</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>如何使用Java 20:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><a href="https://adoptium.net/temurin/releases/?version=20">下载 Java 20</a>.</p>
</li>
<li>
<p>获取Open Liberty <a href="#run">23.0.0.3</a> 版本.</p>
</li>
<li>
<p>编辑Liberty <a href="/docs/latest/reference/config/server-configuration-overview.html#server-env">server.env 文件</a>，将 JAVA_HOME 指向Java 20 installation安装路径.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>有关Java 20的更多信息，可以参考Java 20<a href="https://jdk.java.net/20/release-notes">相关发布说明</a>,<a href="https://docs.oracle.com/en/java/javase/20/docs/api/index.html">API Javadoc 页面</a>, <a href="https://adoptium.net/temurin/releases/?version=20">download page</a> and <a href="https://docs.oracle.com/en/java/javase/20/migrate/toc.htm">Java 20 迁移手册</a>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
在Open Liberty中试用Java 20预览特性，请确保使用 --enable-preview进行编译，并在jvm.options文件中添加相同的参数。
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="bugs">此版本中值得注意的错误修复</h2>
<div class="sectionbody">
<div class="paragraph">
<p>我们花了一些时间来修复bug。下面的部分描述了在这个版本中解决的一些问题。如果您感兴趣，这里是<a href="https://github.com/OpenLiberty/open-liberty/issues?q=label%3Arelease%3A23003+label%3A%22release+bug%22"> 23.0.0.3中修复的完整错误列表</a>。</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/24566">启用了撤销的AcmeCA特性在某些操作系统和JDK组合上可能无法初始化</a></p>
<div class="paragraph">
<p>当在MacOS上运行带有IBM JDK8和自动证书管理环境(ACME)支持2.0功能并启用证书撤销检查的混合JDK时，SSL/TLS端点可能无法完成初始化，并且无法用于通信。</p>
</div>
<div class="paragraph">
<p>FFDC里记录如下NullPointerException，表示初始化流程失败:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>Exception = java.lang.NullPointerException
Source = com.ibm.ws.security.acme.internal.AcmeProviderImpl
probeid = 921
Stack Dump = java.lang.NullPointerException
at sun.security.provider.certpath.CertPathHelper.setDateAndTime(CertPathHelper.java:71)
at sun.security.provider.certpath.RevocationChecker.checkCRLs(RevocationChecker.java:525)
at sun.security.provider.certpath.RevocationChecker.checkCRLs(RevocationChecker.java:464)
at sun.security.provider.certpath.RevocationChecker.check(RevocationChecker.java:393)
at sun.security.provider.certpath.RevocationChecker.check(RevocationChecker.java:336)
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:125)
at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:225)
at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:145)
at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:84)
at java.security.cert.CertPathValidator.validate(CertPathValidator.java:304)
at com.ibm.ws.security.acme.internal.CertificateRevocationChecker.isRevoked(CertificateRevocationChecker.java:371)
....</code></pre>
</div>
</div>
<div class="paragraph">
<p>此问题已解决，端点已成功初始化，并可用于服务通信。</p>
</div>
</li>
</ul>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/24631">修复CDI注入事件反序列化期间的ClassCastException问题</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>被注入jakarta.enterprise.event.Event(或类似javax)的passivated (即可序列化)bean将无法正常恢复。当启用会话持久性并且从数据库序列化和反序列化会话数据时，可能会遇到这种情况。这会导致以下FFDC事件发生:</p>
</div>
<div class="paragraph">
<p>+</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>Stack Dump = java.lang.ClassCastException: cannot assign instance of org.jboss.weld.event.EventImpl$SerializationProxy to field org.apache.myfaces.flow.cdi.FlowScopeContextualStorageHolder.flowDestroyedEvent of type jakarta.enterprise.event.Event in instance of org.apache.myfaces.flow.cdi.FlowScopeContextualStorageHolder
        at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2076)
        at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2039)
        at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1293)
        at java.base/java.io.ObjectInputStream.defaultCheckFieldValues(ObjectInputStream.java:2512)</code></pre>
</div>
</div>
<div class="paragraph">
<p>+
此问题已解决，CDI事件对象恢复无误。</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/24465">需要更新JDBC DB2 queryDataSize的值</a></p>
<div class="paragraph">
<p>在DB2 11.5.7+中，将DB2数据源的queryDataSize设置为有效值时，会出现以下错误:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>[ERROR   ] CWWKG0075E: The value 10452991 is not valid for attribute `queryDataSize` of configuration element dataSource. The validation message was: Value &quot;10452991&quot; is out of range..</code></pre>
</div>
</div>
<div class="paragraph">
<p>此问题已得到解决，新的queryDataSize范围已被正确接受</p>
</div>
</li>
</ul>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/24651">Liberty服务器随机挂起</a></p>
<div class="paragraph">
<p>在使用JAX-RS时一个 <a href="https://github.com/eclipse-openj9/openj9/issues/14037">OpenJ9里的bug</a>可能会导致Liberty服务器因死锁而挂起。例如:、、</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>2LKMONINUSE      sys_mon_t:0x00007FCE3C16F258 infl_mon_t: 0x00007FCE3C16F2D8:
3LKMONOBJECT       org/apache/cxf/jaxrs/interceptor/CachedTime@0x00000000FBF1D0C8: Flat locked by &quot;Default Executor-thread-8&quot; (J9VMThread:0x0000000001B4BF00), entry count 1
3LKWAITERQ            Waiting to enter:
3LKWAITER                &quot;Default Executor-thread-1&quot; (J9VMThread:0x00000000006EB200)
3LKWAITER                &quot;Default Executor-thread-3&quot; (J9VMThread:0x0000000000718D00)
3LKWAITER                &quot;Default Executor-thread-17&quot; (J9VMThread:0x0000000002644B00)
3LKWAITER                &quot;Default Executor-thread-19&quot; (J9VMThread:0x0000000000346F00)
3LKWAITER                &quot;Default Executor-thread-20&quot; (J9VMThread:0x0000000000618300)
3LKWAITER                &quot;Default Executor-thread-29&quot; (J9VMThread:0x0000000002645700)
3LKWAITER                &quot;Default Executor-thread-30&quot; (J9VMThread:0x0000000002643F00)
3LKWAITER                &quot;Default Executor-thread-39&quot; (J9VMThread:0x00000000022FF900)
3LKWAITER                &quot;Default Executor-thread-40&quot; (J9VMThread:0x00000000022DAA00)
3LKWAITER                &quot;Default Executor-thread-49&quot; (J9VMThread:0x000000000216DE00)
3LKWAITER                &quot;Default Executor-thread-50&quot; (J9VMThread:0x00000000022FED00)
3LKWAITER                &quot;Default Executor-thread-59&quot; (J9VMThread:0x0000000001B74900)
3LKWAITER                &quot;Default Executor-thread-60&quot; (J9VMThread:0x0000000002178F00)
3LKWAITER                &quot;Default Executor-thread-62&quot; (J9VMThread:0x0000000001B72300)

&quot;Default Executor-thread-8&quot; J9VMThread:0x0000000001B4BF00, omrthread_t:0x00007FCE18012DF0, java/lang/Thread:0x00000000FBF99E78, state:B, prio=5
       (java/lang/Thread getId:0x4C, isDaemon:true)
       com/ibm/ws/classloading/internal/ThreadContextClassLoader(0x0000000086272FF8)
       (native thread ID:0x1A4, native priority:0x5, native policy:UNKNOWN, vmstate:B, vm thread flags:0x00000281)
       (native stack address range from:0x00007FCEA0FF6000, to:0x00007FCEA1036000, size:0x40000)
      CPU usage total: 3.272702139 secs, current category=&quot;Application&quot;
Blocked on: java/lang/StringBuffer@0x00000000FBF99F10 Owned by: &quot;Default Executor-thread-1&quot; (J9VMThread:0x00000000006EB200, java/lang/Thread:0x00000000804DA638)
      Heap bytes allocated since last GC cycle=0 (0x0)
      Java callstack:
          at java/lang/StringBuffer.setLength(Bytecode PC:0(Compiled Code))
             (entered lock: java/lang/StringBuffer@0x00000000FBF99F10, entry count: 1)
          at org/apache/cxf/jaxrs/interceptor/CachedTime.updateTime(CachedTime.java:86)
          at org/apache/cxf/jaxrs/interceptor/CachedTime.getTimeAsString(CachedTime.java:134)</code></pre>
</div>
</div>
<div class="paragraph">
<p>在Liberty中，通过从CXF的CachedTime类中删除SimpleDateFormat的使用，这个问题得到了缓解，死锁不再发生。</p>
</div>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="现在就来使用open-liberty-23-0-0-3">现在就来使用Open Liberty 23.0.0.3</h2>
<div class="sectionbody">
<div class="paragraph">
<p>可以通过 <a href="#run">Maven, Gradle, Docker, and as a downloadable archive</a>获取</p>
</div>
</div>
</div>]]></content><author><name>Michal Broz</name></author><category term="blog" /><category term="announcements" /><category term="microprofile" /><category term="java-se" /><category term="release" /><category term="metrics" /><category term="jakarta-ee" /><category term="monitoring" /><category term="data-sources" /><summary type="html"><![CDATA[翻译：Haiyan Zhang]]></summary></entry><entry><title type="html">使用Liberty InstantOn 快速启动云原生 Java 应用程序</title><link href="https://openliberty.io/zh-Hans/blog/2022/12/06/instant-on-beta.html" rel="alternate" type="text/html" title="使用Liberty InstantOn 快速启动云原生 Java 应用程序" /><published>2022-12-06T00:00:00+00:00</published><updated>2022-12-06T00:00:00+00:00</updated><id>https://openliberty.io/zh-Hans/blog/2022/12/06/instant-on-beta</id><content type="html" xml:base="https://openliberty.io/zh-Hans/blog/2022/12/06/instant-on-beta.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>翻译：王峰 (亚信安慧)</p>
</div>
<div class="paragraph">
<p>本文是在 Liberty InstantOn 仍处于测试阶段时发表的。 Liberty InstantOn 从以下链接开始退出测试版：<a href="/blog/2023/06/29/rapid-startup-instanton.html">Liberty 23.0.0.6 版本</a>。有关 Liberty InstantOn 的最新信息，请参阅 Open Liberty 文档中的链接：<a href="/docs/latest/instanton.html">使用 Open Liberty InstantOn 实现容器化应用程序的更快启动</a>。</p>
</div>
<div class="paragraph">
<p>你想让云原生Java应用在几毫秒内启动，而不影响吞吐量、内存、开发和生产等价或Java语言新特性吗？Open Liberty 22.0.0.11-beta带来了InstantOn，一个为MicroProfile和Jakarta EE应用程序提供了快速启动的新功能。InstantOn 于23.0.0.6已经正式发布了。这个<a href="/blog/2023/06/29/rapid-startup-instanton.html">博客</a>讲述了最新信息。</p>
</div>
<div class="paragraph">
<p>在无服务器环境中，应用程序的启动时间很重要。当应用程序不被使用时，InstantOn应用程序实例可以收缩到零。当没有持续的请求时，通过减少应用实例的总体数量，收缩到零有助于降低整体云成本。当应用程序的活动增加时，新的实例可以快速启动，不会给用户体验带来高延迟。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="open-liberty是如何实现instanton的呢">Open Liberty是如何实现InstantOn的呢？</h2>
<div class="sectionbody">
<div class="paragraph">
<p>为了实现InstantOn，Open Liberty使用了<a href="https://www.eclipse.org/openj9/">OpenJ9</a> JVM的新特性和一种叫做Checkpoint/Restore In Userspace <a href="https://criu.org/">CRIU</a>的Linux技术，在应用进程启动时对其设置<code>checkpoint</code>。这个<code>checkpoint</code>是正在运行的应用程序进程的快照，可以被持久化，也可以快速<code>restore</code>，使应用程序进程回到<code>checkpoint</code>时的状态。这个过程使Liberty实例，以及任何受保护的应用程序，可以多次<code>restore</code>为应用程序的不同实例。</p>
</div>
<div class="paragraph">
<p>要了解InstantOn的启动速度有多快，请跳转到链接"<a href="#benchmark">有多快</a>"。关于这种方法优势的更多细节，参考<a href="https://blog.openj9.org/2022/09/26/fast-jvm-startup-with-openj9-criu-support/">OpenJ9 CRIU下快速JVM启动</a>博文和早期的<a href="/blog/2020/02/12/faster-startup-Java-applications-criu.html">Open Liberty博文</a>，其中我们首次讨论了CRIU对快速启动Java应用程序的能力。</p>
</div>
<div class="paragraph">
<p>Open Liberty InstantOn功能提供了一个新的<code>checkpoint</code>行为，可以针对你现有的Open Liberty服务器有效，你可以很容易地使用它。可以具体指定一个阶段作为<code>checkpoint</code>，让Liberty在这个<code>checkpoint</code>启动、停止、保存这个<code>checkpoint</code>。当Liberty启动时，它将检测到保存的<code>checkpoint</code>进程，并从保存的<code>checkpoint</code>中<code>restore</code>进程状态。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="应用程序示例">应用程序示例</h2>
<div class="sectionbody">
<div class="paragraph">
<p>在我们讨论<code>checkpoint</code>如何工作的细节之前，让我们建立一个实例。对于这个例子，我们将了解一下<a href="/guides/getting-started.html">Open Liberty入门</a>指南。从克隆一个样例代码的<a href="https://github.com/openliberty/guide-getting-started.git">Git仓库</a>开始：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>git clone https://github.com/openliberty/guide-getting-started.git
cd guide-getting-started</code></pre>
</div>
</div>
<div class="paragraph">
<p>在本演示中，我们将在<code>finish/</code>目录下工作。请运行以下Maven goal，构建该应用程序并将其部署到Open Liberty：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>cd finish
mvn liberty:run</code></pre>
</div>
</div>
<div class="paragraph">
<p>以下信息说明你的应用服务器已经准备好了：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>The defaultServer server is ready to run a smarter planet.</code></pre>
</div>
</div>
<div class="paragraph">
<p>通过浏览器访问 <a href="http://localhost:9080/dev/system/properties" class="bare">http://localhost:9080/dev/system/properties</a> ，查看服务。在查看完应用程序后，在运行服务器的命令行会话中按CTRL+C停止Open Liberty服务器。下一步为应用程序构建WAR，请运行以下命令：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>mvn package</code></pre>
</div>
</div>
<div class="paragraph">
<p>这个命令建立了一个<code>target/guide-getting-started.war</code>文件。我们现在可以把这个WAR包含在使用InstantOn功能的容器镜像中。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="容器化应用程序">容器化应用程序</h2>
<div class="sectionbody">
<div class="paragraph">
<p>要使用Open Liberty InstantOn支持的应用程序，它必须首先使用Open Liberty beta InstantOn镜像进行容器化。关于如何使用Open Liberty对应用程序进行容器化，请参见<a href="/guides/containerize.html">容器化微服务</a>指南或用<a href="/guides/containerize-podman.html">Podman容器化微服务</a>指南。如果你不熟悉Podman，请先了解一下Podman指南，因为Open Liberty InstantOn目前需要使用到Podman。后期，一旦Docker支持CRIU所需的功能，InstantOn也会对Docker支持。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="使用open-liberty-beta-instanton镜像对一个应用程序进行容器化">使用Open Liberty Beta InstantOn镜像对一个应用程序进行容器化</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Liberty InstantOn测试版包含了构建带有<code>checkpoint</code>进程的应用容器镜像功能。应用程序可以使用Liberty InstantOn测试版作为基础来构建自己的应用程序容器镜像。涉及到以下步骤：</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><a href="#dockerfile">为应用程序创建Dockerfile</a></p>
</li>
<li>
<p><a href="#app-image">构建应用程序的容器镜像</a></p>
</li>
<li>
<p><a href="#checkpoint-app">设置容器镜像中应用程序的<code>checkpoint</code></a></p>
</li>
<li>
<p><a href="#checkpoint-image">创建应用程序的<code>checkpoint</code>镜像</a></p>
</li>
</ol>
</div>
</div>
</div>
<div class="sect1">
<h2 id="checkpointrestore容器化应用程序的先决条件"><code>checkpoint</code>/<code>restore</code>容器化应用程序的先决条件</h2>
<div class="sectionbody">
<div class="paragraph">
<p>目前，Open Liberty InstantOn的测试版只支持在x86-64/amd64架构上运行。为了构建和运行使用criu的容器镜像，主机操作系统需要安装一些先决条件。我们所有的测试都是在RHEL 8.6和RHEL 9.0上进行的。其他Linux发行版，如果具备必要的先决条件，也是可以的。需要具备以下条件：</p>
</div>
<div class="ulist">
<ul>
<li>
<p>内核必须支持Linux <a href="https://man7.org/linux/man-pages/man7/capabilities.7.html">CAP_CHECKPOINT_RESTORE</a>功能。该功能是在5.9版本的内核中引入的，但已经传回到RHEL 8.6中使用的RHEL内核版本。</p>
</li>
<li>
<p>必须安装Linux发行版的最新可用版本的Podman。</p>
</li>
<li>
<p>必须对Podman进行配置以使用<code>crun</code>或<code>runc</code>容器运行时。</p>
</li>
<li>
<p>如果你使用<code>runc</code>容器运行时，那么需要1.1.3或更高的版本，以便你有最新的纠错到<code>runc</code>。这个x可以使容器中的<code>/proc/sys/kernel/ns_last_pid</code>成功挂载。</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="dockerfile">为应用程序创建Dockerfile</h2>
<div class="sectionbody">
<div class="paragraph">
<p>对于<a href="/guides/getting-started.html">Open Liberty入门</a>指南的例子，第一步是创建一个<code>Dockerfile</code>，提供创建应用程序的容器化版本的说明。注意，<code>podman</code>也支持使用<code>Containerfile</code>格式来构建容器镜像。</p>
</div>
<div class="paragraph">
<p>在这个例子中，我们将使用IBM容器注册中心（ICR）的一个特殊镜像，<code>icr.io/appcafe/open-liberty:beta</code>，作为父镜像。这个镜像被标记为<code>beta</code>，意味着它包括了所有Liberty beta的功能以及完整镜像中的所有Liberty功能。这个镜像被标记为<code>instanton</code>，意思是它包括所有产生<code>checkpoint</code>进程镜像的先决条件，比如必要的<code>criu</code>二进制文件。</p>
</div>
<div class="paragraph">
<p>getting-started应用程序的<code>Dockerfile</code>已经存在于<code>finish/Dockerfile</code>中。编辑现有的<code>finish/Dockerfile</code>并修改<code>FROM</code>指令，使用<code>icr.io/appcafe/open-liberty:beta</code>父镜像。<code>Dockerfile</code>看起来像这样：</p>
</div>
<div class="listingblock">
<div class="title">Dockerfile</div>
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty:beta


ARG VERSION=1.
ARG REVISION=SNAPSHOT

LABEL \
org.opencontainers.image.authors=&quot;Your Name&quot; \
org.opencontainers.image.vendor=&quot;IBM&quot; \
org.opencontainers.image.url=&quot;local&quot; \
org.opencontainers.image.source=&quot;https://github.com/OpenLiberty/guide-getting-started&quot; \
org.opencontainers.image.version=&quot;$VERSION&quot; \
org.opencontainers.image.revision=&quot;$REVISION&quot; \
vendor=&quot;Open Liberty&quot; \
name=&quot;system&quot; \
version=&quot;$VERSION-$REVISION&quot; \
summary=&quot;The system microservice from the Getting Started guide&quot; \
description=&quot;This image contains the system microservice running with the Open Liberty runtime.&quot;

COPY --chown=1001:0 src/main/liberty/config/ /config/
COPY --chown=1001:0 target/*.war /config/apps/

RUN configure.sh</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="app-image">构建应用容器镜像</h2>
<div class="sectionbody">
<div class="paragraph">
<p>为了使 <code>criu</code> 能够对进程进行<code>checkpoint</code>和<code>restore</code>，<code>criu</code> 二进制文件必须被授予额外的<a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux_atomic_host/7/html/container_security_guide/linux_capabilities_and_seccomp">Linux功能</a>。特别是对于Open Liberty，它需要被授予<code>cap_checkpoint_restore</code>、<code>cap_net_admin</code>和<code>cap_sys_ptrace</code>。Open Liberty InstantOn 测试版镜像包括 <code>criu</code> 二进制文件，以及<code>criu</code> 二进制文件所需要的功能。为了使<code>criu</code>二进制文件在运行时被赋予访问权限，运行<code>criu</code>的容器在启动时也必须被授予必要的权限。你可以通过以下两种方式之一授予容器这些权限：</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>使用<code>--privileged</code>选项使用特权容器</p>
</li>
<li>
<p>使用<code>--cap-add</code>选项分配特定的权限</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>当你使用Docker时，守护程序通常有根权限。这个权限允许它在启动容器时授予任何要求的能力。在Podman中，没有守护程序，所以启动容器的用户必须有必要的Linux权限。当你以root身份运行或使用<code>sudo</code>来运行<code>podman</code>命令时，就有这个权限。在这个例子中，我们以根用户的身份运行<code>podman</code>命令。</p>
</div>
<div class="paragraph">
<p>有了这样的认识，我们现在可以通过使用<code>podman build</code>命令来构建容器镜像。在<code>finish/</code>目录下，运行以下命令来构建应用程序的容器镜像：</p>
</div>
<div class="paragraph">
<p>构建应用程序容器镜像</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>podman build -t getting-started.</code></pre>
</div>
</div>
<div class="paragraph">
<p>这个命令创建了得到启动的容器镜像。然而，这个容器镜像并不包含任何可用于InstantOn启动的<code>checkpoint</code>镜像文件。你可以用下面的命令来运行这个应用容器镜像。</p>
</div>
<div class="paragraph">
<p>运行应用程序容器</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>podman run --name getting-started --rm -p 9080:9080 getting-started</code></pre>
</div>
</div>
<div class="paragraph">
<p>注意Liberty显示了应用启动所需的时间，并在 <a href="http://localhost:9080/dev/system/properties" class="bare">http://localhost:9080/dev/system/properties</a> 上可以查看到容器中运行的服务。在检查完应用程序后，在运行<code>podman run</code>的命令行会话中按CTRL+C停止运行中的容器。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="checkpoint-app">对容器中的应用程序进行<code>checkpoint</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>在启动过程中，Open Liberty有三个阶段可以产生<code>checkpoint</code>：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>features</code>: 这是最早可以发生<code>checkpoint</code>的阶段。<code>checkpoint</code>发生在所有配置的Open Liberty功能启动之后，但在对已安装的应用程序进行任何处理之前。请注意，此检查点阶段已被删除，请参阅链接：/blog/2023/02/10/instant-on-beta-update.html[23.0.0.2-beta 中 Liberty InstantOn 的新增强功能]。</p>
</li>
<li>
<p><code>beforeAppStart</code>：<code>checkpoint</code>发生在对配置的应用程序元数据处理之后。如果应用程序有任何组件作为应用程序启动的一部分被运行，<code>checkpoint</code>将在执行应用程序任何代码之前进行。</p>
</li>
<li>
<p><code>afterAppStart</code> - 这是<code>checkpoint</code>可以发生的最后一个阶段，在这个阶段做<code>checkpoint</code>，可以在<code>restore</code>应用实例时提供最快的启动时间。<code>checkpoint</code>发生在所有被指导的应用程序状态为启动之后。这个阶段发生在打开任何用于监听应用程序传入请求的端口之前。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>这个<code>afterAppStart</code>阶段通常为应用程序提供最快的启动时间，但如果有一些应用程序在进程<code>checkpoint</code><code>restore</code>之前运行，就会导致不可知的错误。另外如果<code>checkpoint</code>的应用程序持有不应该被同步到多个应用程序实例的状态或数据，例如，在<code>checkpoint</code>之前连接到外部资源（如数据库）会导致<code>checkpoint</code><code>restore</code>到多实例进程时失败，原因是这会多次<code>restore</code>相同的连接，造成资源冲突。但是，如果您的应用程序初始化不执行打开数据库连接等操作，您也许可以使用<code>afterAppStart</code>阶段作为检查点。</p>
</div>
<div class="paragraph">
<p>在应用容器镜像构建完成后，它可以被用来在之前描述的<code>checkpoint</code>阶段（<code>features</code>, <code>beforeAppStart</code>, <code>afterAppStart</code>）之一对应用进程进行<code>checkpoint</code>。你可以通过使用<code>podman run</code>的<code>--env</code>选项为你的<code>checkpoint</code>指定一个阶段，将<code>WLP_CHECKPOINT</code>的值设置为可用的<code>checkpoint</code>。在下面例子中，通过运行<code>podman</code>命令，制作一个<code>afterAppStart</code>镜像。</p>
</div>
<div class="paragraph">
<p>在容器中确定一个<code>checkpoint</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>podman run \
--name getting-started-checkpoint-container \
--privileged \
--env WLP_CHECKPOINT=afterAppStart \
getting-started</code></pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>在容器中确定<code>criu</code><code>checkpoint</code>时，需要使用<code>--privileged</code>选项。</p>
</li>
<li>
<p><code>WLP_CHECKPOINT</code>环境变量用于指定<code>checkpoint</code>阶段。对于需要启动快的场景，<code>afterAppStart</code><code>checkpoint</code>阶段将是最好的选择。</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>这将启动在Open Liberty上运行应用程序的容器。在Open Liberty启动后，它会在<code>WLP_CHECKPOINT</code>环境变量指定的阶段执行<code>checkpoint</code>。在容器的进程数据被持久化之后，容器将停止，将产生一个包含<code>checkpoint</code>进程数据的容器文件。输出将看起来像这样：</p>
</div>
<div class="paragraph">
<p>确定<code>checkpoint</code>输出</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>Performing checkpoint --at=afterAppStart


Launching defaultServer (Open Liberty 22.0.0.11-beta/wlp-1.0.69.cl221020220912-1100) on Eclipse OpenJ9 VM, version 17.0.5-
ea+2 (en_US)
CWWKE0953W: This version of Open Liberty is an unsupported early release version.
[AUDIT ] CWWKE0001I: The server defaultServer has been launched.
[AUDIT ] CWWKG0093A: Processing configuration drop-ins resource:
/opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/checkpoint.xml
[AUDIT ] CWWKG0093A: Processing configuration drop-ins resource:
/opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/keystore.xml
[AUDIT ] CWWKG0093A: Processing configuration drop-ins resource:
/opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/open-default-port.xml
[AUDIT ] CWWKZ0058I: Monitoring dropins for applications.
[AUDIT ] CWWKT0016I: Web application available (default_host): http://f5edff273d9c:9080/ibm/api/
[AUDIT ] CWWKT0016I: Web application available (default_host): http://f5edff273d9c:9080/metrics/
[AUDIT ] CWWKT0016I: Web application available (default_host): http://f5edff273d9c:9080/health/
[AUDIT ] CWWKT0016I: Web application available (default_host): http://f5edff273d9c:9080/dev/
[AUDIT ] CWWKZ0001I: Application guide-getting-started started in 0.986 seconds.
[AUDIT ] CWWKC0451I: A server checkpoint was requested. When the checkpoint completes, the server stops.</code></pre>
</div>
</div>
<div class="paragraph">
<p>这个过程目前不能作为podman构建步骤的一部分，因为Podman（和Docker）没有提供一种方法来授予构建容器镜像必要的Linux权限，以便<code>criu</code>确定进程<code>checkpoint</code>。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="checkpoint-image">创建应用程序<code>checkpoint</code>镜像</h2>
<div class="sectionbody">
<div class="paragraph">
<p>到目前为止，我们已经为getting-started应用程序创建了<code>checkpoint</code>进程数据，并将其存储在一个名为<code>getting-started-checkpoint-container</code>的停止的容器中。最后一步是创建一个包含<code>checkpoint</code>进程数据的新容器镜像。当这个容器镜像被启动时，它将从<code>checkpoint</code>被创建的地方开始<code>restore</code>应用进程，从而形成一个InstantOn应用。你可以通过运行下面的<code>podman commit</code>操作来创建新的镜像：</p>
</div>
<div class="paragraph">
<p>将<code>checkpoint</code>提交给一个图像</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>podman commit getting-started-checkpoint-container getting-started-instanton</code></pre>
</div>
</div>
<div class="paragraph">
<p>现在我们有两个应用镜像，分别命名为<code>getting-started</code>和<code>getting-started-instanton</code>。用<code>getting-started-instanton</code>容器镜像启动容器，会显示出比原来的<code>getting-started</code>镜像快得多的启动时间。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="运行instanton应用程序图像">运行InstantOn应用程序图像</h2>
<div class="sectionbody">
<div class="paragraph">
<p>通常情况下，一个应用容器可以通过如下命令从一个应用容器镜像中启动：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>podman run --rm -p 9080:9080 getting-started-instanton</code></pre>
</div>
</div>
<div class="paragraph">
<p>然而，这个命令会失败，因为<code>criu</code>需要一些高级权限，以便能够<code>restore</code>容器中的进程。当Liberty不能<code>restore</code><code>checkpoint</code>进程时，它将通过启动没有<code>checkpoint</code>镜像来<code>restore</code>，并记录以下信息：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>CWWKE0957I: Restoring the checkpoint server process failed. Check the /logs/checkpoint/restore.log log to determine why
the checkpoint process was not restored. Launching the server without using the checkpoint image.</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="使用-特权选项运行">使用-特权选项运行</h2>
<div class="sectionbody">
<div class="paragraph">
<p>为了授予所有可用的所需权限，你可以选择用以下命令来启动一个有特权的容器。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>podman run --rm --privileged -p 9080:9080 getting-started-instanton</code></pre>
</div>
</div>
<div class="paragraph">
<p>如果成功，你将看到如下输出：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>[AUDIT ] CWWKZ0001I: Application guide-getting-started started in 0.059 seconds.
[AUDIT ] CWWKC0452I: The Liberty server process resumed operation from a checkpoint in 0.088 seconds.
[AUDIT ] CWWKF0012I: The server installed the following features: [cdi-3.0, checkpoint-1.0, concurrent-2.0,
distributedMap-1.0, jndi-1.0, json-1.0, jsonb-2.0, jsonp-2.0, monitor-1.0, mpConfig-3.0, mpHealth-4.0, mpMetrics-4.0,
restfulWS-3.0, restfulWSClient-3.0, servlet-5.0, ssl-1.0, transportSecurity-1.0].
[AUDIT ] CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in
0.098 seconds.</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="使用无特权的容器运行">使用无特权的容器运行</h2>
<div class="sectionbody">
<div class="paragraph">
<p>不建议使用root权限来运行容器。最好的做法是设置只有运行容器所需的权限。可以使用下面的命令来授予容器必要的权限，而不需要运行一个完全-特权的容器：</p>
</div>
<div class="paragraph">
<p>podman run with unconfined --security-opt options</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>podman run \
--rm \
--cap-add=CHECKPOINT_RESTORE \
--cap-add=NET_ADMIN \
--cap-add=SYS_PTRACE \
--security-opt seccomp=unconfined \
--security-opt systempaths=unconfined \
--security-opt apparmor=unconfined \
-p 9080:9080 \
getting-started-instanton</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>--cap-add</code> 选项授予容器 <code>criu</code> 所需的三种 Linux 权限。<code>--security-opt</code> 选项授予 <code>criu</code> 访问所需的系统调用和访问主机上的 <code>/proc/sys/kernel/ns_last_pid</code>权限 。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="用一个没有特权及安全性受限的容器运行">用一个没有特权及安全性受限的容器运行</h2>
<div class="sectionbody">
<div class="paragraph">
<p>可以通过减少<code>--security-opt</code>选项来进一步简化<code>checkpoint</code>的制作过程。默认情况下，<code>podman</code>并没有授予criu所需要权限去做系统调用（默认值在<code>/usr/share/containers/seccomp.json</code>文件中）。首先，你需要一个可以设置<code>criu</code>做系统调用需要的权限配置文件，授予<code>criu</code>所需要的所有系统和容器调用的权限。其次，主机需要挂载<code>/proc/sys/kernel/ns_last_pid</code>。可以用下面的命令来完成这两个步骤：</p>
</div>
<div class="paragraph">
<p>podman run with limited --security-opt</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>podman run \
--rm \
--cap-add=CHECKPOINT_RESTORE \
--cap-add=NET_ADMIN \
--cap-add=SYS_PTRACE \
--security-opt seccomp=criuRequiredSysCalls.json \
-v /proc/sys/kernel/ns_last_pid:/proc/sys/kernel/ns_last_pid \
-p 9080:9080 \
getting-started-instanton</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>--security-opt seccomp=</code> 选项指的是一个名为 <code>criuRequiredSysCalls.json</code> 的文件。这个文件是criu所需的系统调用权限。<code>-v</code>选项在主机上挂载<code>/proc/sys/kernel/ns_last_pid</code>，供容器访问。</p>
</div>
<div class="paragraph">
<p>根据你的Linux发行版，Podman可能默认使用<code>runc</code>或<code>crun</code>。要检查你的Podman安装的容器，请运行命令<code>podman info</code>，查看<code>ociRuntime</code>部分。如果使用的是<code>runc</code>，请确保你使用的是1.1.3或更高版本。为了有效，你必须有一个1.1.3或更高版本的<code>runc</code>。</p>
</div>
<div class="paragraph">
<p>根据你的RHEL 8.6或RHEL 9.0安装的最新情况，你可能会发现指定<code>criuRequiredSysCalls.json</code>的<code>--security-opt</code>是不必要的。在写这篇文章的时候，最新版本的RHEL 8.6和RHEL 9.0包括一个Podman，默认授予所需的系统调用给它启动的容器。这个默认值使得指定 <code>--security-opt seccomp=criuRequiredSysCalls.json</code> 不在需要了。</p>
</div>
<div id="sys-calls-json" class="listingblock">
<div class="title">criuRequiredSysCalls.json</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="json">{
        <span class="key"><span class="delimiter">&quot;</span><span class="content">defaultAction</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ERRNO</span><span class="delimiter">&quot;</span></span>,
        <span class="key"><span class="delimiter">&quot;</span><span class="content">defaultErrnoRet</span><span class="delimiter">&quot;</span></span>: <span class="integer">1</span>,
        <span class="key"><span class="delimiter">&quot;</span><span class="content">archMap</span><span class="delimiter">&quot;</span></span>: [
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">architecture</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_X86_64</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">subArchitectures</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_X86</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_X32</span><span class="delimiter">&quot;</span></span>
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">architecture</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_AARCH64</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">subArchitectures</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_ARM</span><span class="delimiter">&quot;</span></span>
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">architecture</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPS64</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">subArchitectures</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPS</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPS64N32</span><span class="delimiter">&quot;</span></span>
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">architecture</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPS64N32</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">subArchitectures</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPS</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPS64</span><span class="delimiter">&quot;</span></span>
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">architecture</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPSEL64</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">subArchitectures</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPSEL</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPSEL64N32</span><span class="delimiter">&quot;</span></span>
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">architecture</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPSEL64N32</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">subArchitectures</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPSEL</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_MIPSEL64</span><span class="delimiter">&quot;</span></span>
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">architecture</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_S390X</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">subArchitectures</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_S390</span><span class="delimiter">&quot;</span></span>
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">architecture</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ARCH_RISCV64</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">subArchitectures</span><span class="delimiter">&quot;</span></span>: <span class="value">null</span>
                }
        ],
        <span class="key"><span class="delimiter">&quot;</span><span class="content">syscalls</span><span class="delimiter">&quot;</span></span>: [
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">accept</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">accept4</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">access</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">adjtimex</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">alarm</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">bind</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">brk</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">capget</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">capset</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">chdir</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">chmod</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">chown</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">chown32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clock_adjtime</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clock_adjtime64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clock_getres</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clock_getres_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clock_gettime</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clock_gettime64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clock_nanosleep</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clock_nanosleep_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">close</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">close_range</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">connect</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">copy_file_range</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">creat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">dup</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">dup2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">dup3</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">epoll_create</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">epoll_create1</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">epoll_ctl</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">epoll_ctl_old</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">epoll_pwait</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">epoll_pwait2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">epoll_wait</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">epoll_wait_old</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">eventfd</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">eventfd2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">execve</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">execveat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">exit</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">exit_group</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">faccessat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">faccessat2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fadvise64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fadvise64_64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fallocate</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fanotify_mark</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fchdir</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fchmod</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fchmodat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fchown</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fchown32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fchownat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fcntl</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fcntl64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fdatasync</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fgetxattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">flistxattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">flock</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fork</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fremovexattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fsetxattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fstat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fstat64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fstatat64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fstatfs</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fstatfs64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fsync</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ftruncate</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ftruncate64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">futex</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">futex_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">futex_waitv</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">futimesat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getcpu</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getcwd</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getdents</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getdents64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getegid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getegid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">geteuid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">geteuid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getgid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getgid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getgroups</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getgroups32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getitimer</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getpeername</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getpgid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getpgrp</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getpid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getppid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getpriority</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getrandom</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getresgid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getresgid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getresuid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getresuid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getrlimit</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">get_robust_list</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getrusage</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getsid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getsockname</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getsockopt</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">get_thread_area</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">gettid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">gettimeofday</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getuid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getuid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">getxattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">inotify_add_watch</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">inotify_init</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">inotify_init1</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">inotify_rm_watch</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">io_cancel</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ioctl</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">io_destroy</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">io_getevents</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">io_pgetevents</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">io_pgetevents_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ioprio_get</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ioprio_set</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">io_setup</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">io_submit</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">io_uring_enter</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">io_uring_register</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">io_uring_setup</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ipc</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">kill</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">landlock_add_rule</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">landlock_create_ruleset</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">landlock_restrict_self</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">lchown</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">lchown32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">lgetxattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">link</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">linkat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">listen</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">listxattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">llistxattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">_llseek</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">lremovexattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">lseek</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">lsetxattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">lstat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">lstat64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">madvise</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">membarrier</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">memfd_create</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">memfd_secret</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mincore</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mkdir</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mkdirat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mknod</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mknodat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mlock</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mlock2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mlockall</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mmap</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mmap2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mprotect</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mq_getsetattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mq_notify</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mq_open</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mq_timedreceive</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mq_timedreceive_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mq_timedsend</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mq_timedsend_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mq_unlink</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mremap</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">msgctl</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">msgget</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">msgrcv</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">msgsnd</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">msync</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">munlock</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">munlockall</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">munmap</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">nanosleep</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">newfstatat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">_newselect</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">open</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">openat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">openat2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pause</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pidfd_open</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pidfd_send_signal</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pipe</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pipe2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">poll</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ppoll</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ppoll_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">prctl</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pread64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">preadv</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">preadv2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">prlimit64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">process_mrelease</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pselect6</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pselect6_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pwrite64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pwritev</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pwritev2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">read</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">readahead</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">readlink</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">readlinkat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">readv</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">recv</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">recvfrom</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">recvmmsg</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">recvmmsg_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">recvmsg</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">remap_file_pages</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">removexattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rename</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">renameat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">renameat2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">restart_syscall</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rmdir</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rseq</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rt_sigaction</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rt_sigpending</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rt_sigprocmask</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rt_sigqueueinfo</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rt_sigreturn</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rt_sigsuspend</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rt_sigtimedwait</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rt_sigtimedwait_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">rt_tgsigqueueinfo</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_getaffinity</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_getattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_getparam</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_get_priority_max</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_get_priority_min</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_getscheduler</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_rr_get_interval</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_rr_get_interval_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_setaffinity</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_setattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_setparam</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_setscheduler</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sched_yield</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">seccomp</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">select</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">semctl</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">semget</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">semop</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">semtimedop</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">semtimedop_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">send</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sendfile</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sendfile64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sendmmsg</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sendmsg</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sendto</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setfsgid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setfsgid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setfsuid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setfsuid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setgid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setgid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setgroups</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setgroups32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setitimer</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setpgid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setpriority</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setregid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setregid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setresgid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setresgid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setresuid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setresuid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setreuid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setreuid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setrlimit</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">set_robust_list</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setsid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setsockopt</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">set_thread_area</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">set_tid_address</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setuid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setuid32</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setxattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">shmat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">shmctl</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">shmdt</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">shmget</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">shutdown</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sigaltstack</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">signalfd</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">signalfd4</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sigprocmask</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sigreturn</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">socket</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">socketcall</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">socketpair</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">splice</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">stat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">stat64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">statfs</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">statfs64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">statx</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">symlink</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">symlinkat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sync</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sync_file_range</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">syncfs</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sysinfo</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">tee</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">tgkill</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">time</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timer_create</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timer_delete</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timer_getoverrun</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timer_gettime</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timer_gettime64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timer_settime</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timer_settime64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timerfd_create</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timerfd_gettime</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timerfd_gettime64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timerfd_settime</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">timerfd_settime64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">times</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">tkill</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">truncate</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">truncate64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ugetrlimit</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">umask</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">uname</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">unlink</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">unlinkat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">utime</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">utimensat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">utimensat_time64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">utimes</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">vfork</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">vmsplice</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">wait4</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">waitid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">waitpid</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">write</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">writev</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">arch_prctl</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">chroot</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clone</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clone3</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fallocate</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fanotify_init</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fsconfig</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fsmount</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fsopen</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">guarded_storage</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">kcmp</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">lseek</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mmap</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mount</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">open</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">open_by_handle_at</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">openat</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pivot_root</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">preadv</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">process_vm_readv</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ptrace</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">readdir</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">s390_runtime_instr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setns</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sigaction</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">signal</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">syscall</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">umount</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">umount2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">unshare</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">userfaultfd</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">wait</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">process_vm_readv</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">process_vm_writev</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ptrace</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">minKernel</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">4.8</span><span class="delimiter">&quot;</span></span>
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">personality</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">args</span><span class="delimiter">&quot;</span></span>: [
                                {
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">index</span><span class="delimiter">&quot;</span></span>: <span class="integer">0</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">value</span><span class="delimiter">&quot;</span></span>: <span class="integer">0</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">op</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_CMP_EQ</span><span class="delimiter">&quot;</span></span>
                                }
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">personality</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">args</span><span class="delimiter">&quot;</span></span>: [
                                {
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">index</span><span class="delimiter">&quot;</span></span>: <span class="integer">0</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">value</span><span class="delimiter">&quot;</span></span>: <span class="integer">8</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">op</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_CMP_EQ</span><span class="delimiter">&quot;</span></span>
                                }
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">personality</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">args</span><span class="delimiter">&quot;</span></span>: [
                                {
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">index</span><span class="delimiter">&quot;</span></span>: <span class="integer">0</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">value</span><span class="delimiter">&quot;</span></span>: <span class="integer">131072</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">op</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_CMP_EQ</span><span class="delimiter">&quot;</span></span>
                                }
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">personality</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">args</span><span class="delimiter">&quot;</span></span>: [
                                {
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">index</span><span class="delimiter">&quot;</span></span>: <span class="integer">0</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">value</span><span class="delimiter">&quot;</span></span>: <span class="integer">131080</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">op</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_CMP_EQ</span><span class="delimiter">&quot;</span></span>
                                }
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">personality</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">args</span><span class="delimiter">&quot;</span></span>: [
                                {
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">index</span><span class="delimiter">&quot;</span></span>: <span class="integer">0</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">value</span><span class="delimiter">&quot;</span></span>: <span class="integer">4294967295</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">op</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_CMP_EQ</span><span class="delimiter">&quot;</span></span>
                                }
                        ]
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sync_file_range2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">swapcontext</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">arches</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">ppc64le</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">arm_fadvise64_64</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">arm_sync_file_range</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sync_file_range2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">breakpoint</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">cacheflush</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">set_tls</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">arches</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">arm</span><span class="delimiter">&quot;</span></span>,
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">arm64</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">arch_prctl</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">arches</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">amd64</span><span class="delimiter">&quot;</span></span>,
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">x32</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">modify_ldt</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">arches</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">amd64</span><span class="delimiter">&quot;</span></span>,
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">x32</span><span class="delimiter">&quot;</span></span>,
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">x86</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">s390_pci_mmio_read</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">s390_pci_mmio_write</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">s390_runtime_instr</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">arches</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">s390</span><span class="delimiter">&quot;</span></span>,
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">s390x</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">riscv_flush_icache</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">arches</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">riscv64</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">open_by_handle_at</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_DAC_READ_SEARCH</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">bpf</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clone</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clone3</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fanotify_init</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fsconfig</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fsmount</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fsopen</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">fspick</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">lookup_dcookie</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mount</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mount_setattr</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">move_mount</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">name_to_handle_at</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">open_tree</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">perf_event_open</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">quotactl</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">quotactl_fd</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setdomainname</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">sethostname</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">setns</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">syslog</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">umount</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">umount2</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">unshare</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_ADMIN</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clone</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">args</span><span class="delimiter">&quot;</span></span>: [
                                {
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">index</span><span class="delimiter">&quot;</span></span>: <span class="integer">0</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">value</span><span class="delimiter">&quot;</span></span>: <span class="integer">2114060288</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">op</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_CMP_MASKED_EQ</span><span class="delimiter">&quot;</span></span>
                                }
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">excludes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_ADMIN</span><span class="delimiter">&quot;</span></span>
                                ],
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">arches</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">s390</span><span class="delimiter">&quot;</span></span>,
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">s390x</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clone</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">args</span><span class="delimiter">&quot;</span></span>: [
                                {
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">index</span><span class="delimiter">&quot;</span></span>: <span class="integer">1</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">value</span><span class="delimiter">&quot;</span></span>: <span class="integer">2114060288</span>,
                                        <span class="key"><span class="delimiter">&quot;</span><span class="content">op</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_CMP_MASKED_EQ</span><span class="delimiter">&quot;</span></span>
                                }
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">comment</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">s390 parameter ordering for clone is different</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">arches</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">s390</span><span class="delimiter">&quot;</span></span>,
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">s390x</span><span class="delimiter">&quot;</span></span>
                                ]
                        },
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">excludes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_ADMIN</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clone3</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ERRNO</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">errnoRet</span><span class="delimiter">&quot;</span></span>: <span class="integer">38</span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">excludes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_ADMIN</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">reboot</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_BOOT</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">chroot</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_CHROOT</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">delete_module</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">init_module</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">finit_module</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_MODULE</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">acct</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_PACCT</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">kcmp</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">pidfd_getfd</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">process_madvise</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">process_vm_readv</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">process_vm_writev</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ptrace</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_PTRACE</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">iopl</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">ioperm</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_RAWIO</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">settimeofday</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">stime</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">clock_settime</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_TIME</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">vhangup</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_TTY_CONFIG</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">get_mempolicy</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">mbind</span><span class="delimiter">&quot;</span></span>,
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">set_mempolicy</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYS_NICE</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                },
                {
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">names</span><span class="delimiter">&quot;</span></span>: [
                                <span class="string"><span class="delimiter">&quot;</span><span class="content">syslog</span><span class="delimiter">&quot;</span></span>
                        ],
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">action</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">SCMP_ACT_ALLOW</span><span class="delimiter">&quot;</span></span>,
                        <span class="key"><span class="delimiter">&quot;</span><span class="content">includes</span><span class="delimiter">&quot;</span></span>: {
                                <span class="key"><span class="delimiter">&quot;</span><span class="content">caps</span><span class="delimiter">&quot;</span></span>: [
                                        <span class="string"><span class="delimiter">&quot;</span><span class="content">CAP_SYSLOG</span><span class="delimiter">&quot;</span></span>
                                ]
                        }
                }
        ]
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="benchmark">有多快</h2>
<div class="sectionbody">
<div class="paragraph">
<p>我们测试了多个应用程序，以显示使用InstantOn如何减少启动时间。</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/HotswapProjects/pingperf-quarkus/">Pingperf</a>是一个非常简单的ping类型的应用程序，涉及一个单一的REST接口。</p>
</li>
<li>
<p><a href="https://github.com/johnaohara/quarkusRestCrudDemo/">Rest crud</a>就比较复杂了，它涉及JPA和一个远程数据库。</p>
</li>
<li>
<p><a href="https://github.com/blueperf/acmeair-mainservice-java#acme-air-main-service---javaliberty/">AcmeAir Microservice Main</a>使用了MicroProfile的功能。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>这些实验是在一个24核的系统上运行的。我使用<code>taskset -c</code>为运行在容器中的Liberty进程分配了4个CPU。InstantOn时间是使用<code>afterAppStart</code><code>checkpoint</code>阶段消耗的时间。基础启动是从启动Liberty服务器到服务器准备接受请求的时间，不包括启动容器本身所需的时间，以<code>messages.log</code>中信息显示“这个&lt;server name&gt;服务器已准备好运行更智能的星球“为准。这些应用程序的InstantOn与正常启动时间在此以毫秒为单位显示。你的结果可能会根据你的环境、你系统上安装的硬件和软件以及其他因素而有所不同。数据显示越低越好：</p>
</div>
<div class="imageblock text-center">
<div class="content">
<img src="/img/blog/instantonperf.png" alt="Startup Performance" width="70%">
</div>
</div>
<div class="paragraph">
<p>InstantOn提供了一个快速启动的能力，根据应用的不同，最高可达90%。所有的应用都是不一样的，所以你可能会看到你的应用有不同的结果。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="接下来将做什么">接下来将做什么？</h2>
<div class="sectionbody">
<div class="paragraph">
<p>这篇帖子描述了使用Open Liberty InstantOn测试版来制作具有InstantOn启动时间的应用程序容器镜像的细节。目前仅在Liberty webProfile-8.0、webProfile-9.1、microProfile-4.1和microProfile-5.0支持该功能。我们希望将其扩展到包括webProfile和microProfile的未来版本，并将支持扩展到Jakarta完整的profile功能（如jakarta-8.0、jakarta-9.1、jakarta-10.0）。</p>
</div>
<div class="paragraph">
<p>通过InstantOn，你可以建立非常快速的启动应用容器，这些容器可以在部署时选择收缩到零。我们期待着未来的一篇博文，描述如何在红帽OpenShift容器平台（OCP）和Kubernetes（k8s）等云环境中部署Open Liberty InstantOn，并采用Knative等能够自动将应用收缩到零的技术。</p>
</div>
</div>
</div>]]></content><author><name>Thomas Watson</name></author><category term="blog" /><category term="announcements" /><category term="microprofile" /><category term="beta" /><category term="docker" /><category term="jakarta-ee" /><category term="kubernetes" /><category term="developer-experience" /><category term="performance-enhancements" /><summary type="html"><![CDATA[翻译：王峰 (亚信安慧)]]></summary></entry><entry><title type="html">构建云原生微服务，我该选择哪种技术路线？</title><link href="https://openliberty.io/zh-Hans/blog/2022/10/16/microprofile-spring-comparison.html" rel="alternate" type="text/html" title="构建云原生微服务，我该选择哪种技术路线？" /><published>2022-10-16T00:00:00+00:00</published><updated>2022-10-16T00:00:00+00:00</updated><id>https://openliberty.io/zh-Hans/blog/2022/10/16/microprofile-spring-comparison</id><content type="html" xml:base="https://openliberty.io/zh-Hans/blog/2022/10/16/microprofile-spring-comparison.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>原出版: Eclipse 基金会2019年9月月报: <a href="https://www.eclipse.org/community/eclipse_newsletter/2019/september/microprofile.php" class="bare">https://www.eclipse.org/community/eclipse_newsletter/2019/september/microprofile.php</a></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="为什么选择云原生微服务">为什么选择云原生微服务？</h2>
<div class="sectionbody">
<div class="paragraph">
<p>云，可见或不可见，无处不在。在这篇文章中，我谈论的是无形的云，云计算。云分为三种类型：私有云、公共云和混合云。越来越多的公司正在致力于应用程序现代化，以便他们可以创建云原生微服务，以节省成本并充分利用云资源。当微服务在云中运行时，它只会在运行时产生费用。根据负载，它可以弹性伸缩。在这种情况下，您只需为使用的内容付费，不会有闲置成本，您无需担心购买任何硬件只是为了偶尔使用，即用即付模式。</p>
</div>
<div class="paragraph">
<p>在应用程序现代化方面，实现目标有不同的途径。对于现有的单体应用程序，是时候考虑如何在云中部署它们了。您可以将它们容器化或将它们分解为微服务。对于新编写的应用程序，最好的选择是构建新型云原生微服务。本文重点介绍如何开发最高效的云原生微服务，可以在云端正常运行。我们先明确一下云原生是什么意思。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="什么是云原生">什么是云原生？</h2>
<div class="sectionbody">
<div class="paragraph">
<p>您可能首先想到的问题是：云原生是什么意思？一般来说，云原生是指为云构建的应用程序。云原生微服务充分利用了云基础设施，形成了一个很好的生态系统。无需重新打包即可轻松配置、具备安全、弹性、可监控、可追溯等特性。我们来总结一下云原生微服务的特点。</p>
</div>
<div class="paragraph">
<p><strong>外部化配置</strong></p>
</div>
<div class="paragraph">
<p>云原生微服务必须是可配置的。更改配置时，不需重新打包微服务。一次构建，到处配置。这也是<a href="https://www.12factor.net/">12因子方法论</a>强烈推荐的。</p>
</div>
<div class="paragraph">
<p><strong>RESTful</strong></p>
</div>
<div class="paragraph">
<p>云原生微服务最好是无状态的。状态应该存储在数据库中，而不是内存中。云原生微服务具有共性，不管几个同时运行，它们都是一模一样的。微服务本身应该被视为牲畜，而不是宠物。在这种情况下，当微服务容器没有响应时，底层云基础设施可以替换它而不会丢失任何信息。</p>
</div>
<div class="paragraph">
<p><strong>容错</strong></p>
</div>
<div class="paragraph">
<p>云原生微服务应该具有弹性。它应该在任何情况下发挥作用。比如，即使它的下游服务宕掉。</p>
</div>
<div class="paragraph">
<p><strong>可发现</strong></p>
</div>
<div class="paragraph">
<p>云原生微服务应该能够对外提供自身功能或能力，以便客户端可以调用服务。</p>
</div>
<div class="paragraph">
<p><strong>安全性</strong></p>
</div>
<div class="paragraph">
<p>安全性在云原生微服务中极为重要。在单体应用程序中，只有一小部分功能被公开，而大部分功能被隐藏。当迁移到云原生时，每一项服务都有一个唯一的身份。您需要确保只有经过身份验证和授权的用户才能调用相关的微服务。例如，如果你部署一个工资查询的微服务，你可能只希望具有“经理”和“所有者”访问权限的调用者访问该服务。</p>
</div>
<div class="paragraph">
<p><strong>可观测性</strong></p>
</div>
<div class="paragraph">
<p>一旦云原生微服务在云中运行，就必须发出一些指标，以便 DevOps
可以对其进行监控，以了解它的响应速度和负载量等。</p>
</div>
<div class="paragraph">
<p><strong>可追溯性</strong></p>
</div>
<div class="paragraph">
<p>云原生微服务主要需要与其他不同的微服务通信，然后再与其他不同的服务通信。如果您尝试绘制一个调用链，您可能会以
a&#8594;b&#8594;d&#8594;f&#8594;e
等结尾。一旦服务无法运行，您需要找出哪个服务出现故障。如果没有可视化调用链的能力，将很难识别出故障服务。为了构建调用链，微服务需要能够传播关联ID。有了这个，ZipKin 或 Jaeger
等一些工具可以构建一个跟踪范围来说明每个服务状态。</p>
</div>
<div class="paragraph">
<p><strong>与云通信的能力</strong></p>
</div>
<div class="paragraph">
<p>云原生微服务需要能够与云基础设施就其健康状态进行通信。它应该能够告诉基础设施它是否准备好接收请求或者它是否仍然存在。如果它不存在，云基础设施（例如 Kubernetes）可以轻松替换它。如果它没有准备好，例如它的数据库连接没有准备好，云基础设施将不会将请求路由到这个服务。</p>
</div>
<div class="paragraph">
<p>读到这里，你可能会感叹，别说你的业务逻辑了，还有很多 QoS
需要担心。如果您管理好所有这些，您可能不得不花费大部分时间来担心上述要求，而花更少的时间做与您的业务相关的事情。实在是太多了。我听到你的困难了。幸运的是，我是来帮助你的。我们继续。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="如何构建云原生微服务">如何构建云原生微服务</h2>
<div class="sectionbody">
<div class="paragraph">
<p>无需从头开始构建，有一些框架可以帮助你；开发云原生微服务最流行的框架是<a href="https://microprofile.io/">MicroProfile</a>和<a href="https://spring.io/">Spring框架</a>。</p>
</div>
<div class="paragraph">
<p>Spring 框架已经发展了几年，因此我不会过多谈论它。MicroProfile
相对较新。它由 IBM、Red Hat、Payara、Tomitribe、LJC 和其他个人于 2016
年年中成立。后来，其他公司，如Microsoft, Oracle等也加入了社区。MicroProfile
的目标是发展用于开发云原生微服务的最佳编程模型。到目前为止，它已经发布了八个以上的版本，不久前发布了
MicroProfile 5.0。最近，它引起了广泛的关注。大多数 Jakarta EE
运行时现在都支持 MicroProfile，例如 Open
Liberty、Quarkus、Payara、TomEE、Helidon、KumuluzEE 等。您可以在 <a href="https://wiki.eclipse.org/MicroProfile/Implementation">此处</a>找到实现细节。</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top"></th>
<th class="tableblock halign-left valign-top">Spring</th>
<th class="tableblock halign-left valign-top">MicroProfile</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>REST APIs</strong></p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">REST Service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spring MVC</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">JAX-RS</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Dependency Injection</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spring IoC &amp; DI</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">CDI</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">API Documentation</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spring REST Docs</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MicroProfile Open API</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">REST Client</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spring MVC Feign</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MicroProfile REST Client</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">JSON Binding/Processing</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Bring Your Own Library<br>
Jackson</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">JSON-B<br>
JSON-P</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">处理多个微服务Handling 100s of Services</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Configuration</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spring Boot Config<br>
Spring Cloud Config</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MicroProfile Config</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Fault Tolerance</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Netflix Hystrix</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MicroProfile Fault Tolerance</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Security</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spring Security<br>
Spring Cloud Security</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Jakarta EE Security<br>
MicroProfile JWT Propagation</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Operation Focus</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Health</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spring Boot Actuator</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MicroProfile Health</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Metrics</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spring Boot Actuator</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MicroProfile Metrics</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Distributed Tracing</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spring Cloud Sleuth</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MicroProfile Open Tracing</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>让我们将进行详细介绍。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="开发云原生微服务">开发云原生微服务</h2>
<div class="sectionbody">
<div class="paragraph">
<p>RESTful API 是一种被广泛采用的开发云原生微服务的方式。让我们关注如何使用
RESTful API 和相关技术来编写松耦合的微服务。</p>
</div>
<div class="sect2">
<h3 id="rest-api"><strong>REST API</strong></h3>
<div class="paragraph">
<p>REST（Representational State Transfer）是一种架构风格，用于定义服务之间的通信标准，使系统之间的通信更容易。MicroProfile 和 Spring 都支持 REST。</p>
</div>
<div class="sect3">
<h4 id="jax-rs"><strong>JAX-RS</strong></h4>
<div class="paragraph">
<p>MicroProfile 使用来自Jakarta EE的JAX-RS。在 JAX-RS中，您需要定义一个应用程序和 JAX-RS
资源。在以下示例中，定义了应用程序 <code>CatalogApplication</code> 和 JAX-RS资源 <code>CatalogService</code>，详细信息如下。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@ApplicationPath(&quot;/rest&quot;)
public class CatalogApplication extends Application {
}
@Path(&quot;/items&quot;)
@Produces(MediaType.APPLICATION_JSON)
public class CatalogService {..}
@GET
public List&lt;Item&gt; getInventory() {...}
@GET
@Path(&quot;{id}&quot;)
public Response getById(@PathParam(&quot;id&quot;) long id) {...}</code></pre>
</div>
</div>
<div class="paragraph">
<p>在上面提到的例子中，一个端点 http://${host}:${port}/rest/items
将被暴露。</p>
</div>
<div class="paragraph">
<p>请参阅<a href="https://openliberty.io/guides/rest-intro.html">此</a>Open Liberty
以了解有关 JAX-RS 的更多信息。</p>
</div>
</div>
<div class="sect3">
<h4 id="spring"><strong>Spring</strong></h4>
<div class="paragraph">
<p>在 Spring 框架中，您将需要创建一个 SpringBootApplication 和
Controller。在以下示例中，<code>Application</code> 并 <code>CatalogController</code> 相应地创建。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@SpringBootApplication
public class Application {
    public static void main(String[] args)
    SpringApplication.run(Application.class, args);}
}

@RestController
public class CatalogController {..}
@RequestMapping(value = &quot;/items&quot;, method = RequestMethod.GET)
@ResponseBody
List&lt;Item&gt; getInventory() {..}
@RequestMapping(value = &quot;/items/{id}&quot;, method = RequestMethod.GET)
ResponseEntity&lt;?&gt; getById(@PathVariable long id) {...}</code></pre>
</div>
</div>
<div class="paragraph">
<p>在上面提到的例子中，一个端点 http://${host}:${port}/rest/items
将被暴露。</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="依赖注入"><strong>依赖注入</strong></h3>
<div class="paragraph">
<p>在设计云原生微服务时，最佳实践是创建松耦合的微服务。MicroProfile 采用
Jakarta EE 的上下文和依赖注入 (CDI)，而 Spring 使用 Spring DI、IoC
来达到相同的效果。</p>
</div>
<div class="sect3">
<h4 id="cdi"><strong>CDI</strong></h4>
<div class="paragraph">
<p>下面展示如何使用CDI进行依赖注入</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@ApplicationPath(&quot;/rest&quot;)
public class JaxrsApplication extends Application {
@Inject
private InventoryRefreshTask refreshTask;</code></pre>
</div>
</div>
<div class="paragraph">
<p>上面的代码片段将注入 <code>InventoryRefreshTask</code> 到一个实例 <code>refreshTask</code>。</p>
</div>
<div class="paragraph">
<p>CDI 是 Jakarta EE 和 MicroProfile 的核心部分。了解 CDI非常重要。请参阅<a href="https://openliberty.io/guides/cdi-intro.html">此</a>Open
Liberty 指南以了解有关 CDI 的一些基础知识。</p>
</div>
</div>
<div class="sect3">
<h4 id="spring-di-和-ioc"><em>Spring DI 和 IoC</em></h4>
<div class="paragraph">
<p>Spring使用依赖注入，控制反转来实现松耦合。以下代码片段说明了如何通过
@Autowired 使用 Spring
DI的一个实例 <code>InventoryRefreshTask</code> 将被注入到变量 <code>refreshTask</code> 中。顺便说一句，Spring
也支持 <code>@Inject</code>，相当于 <code>@Autowired</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@SpringBootApplication
public class Application {
    @Autowired
    private InventoryRefreshTask refreshTask;
    ...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="文档-api"><strong>文档 API</strong></h3>
<div class="paragraph">
<p>微服务需要宣传他们的能力，以便潜在客户可以使用他们的服务。在记录 API
时，MicroProfile 和 Spring 处理的方式不同。</p>
</div>
<div class="sect3">
<h4 id="microprofile-开放-api">MicroProfile 开放 API</h4>
<div class="paragraph">
<p>MicroProfile
使用<a href="https://github.com/eclipse/microprofile-open-api/releases">MicroProfile
Open API</a>来记录 API，它基于 Swagger API。在 MicroProfile Open API
中，任何 JAX-RS 资源都会自动选择生成其 API。它还可以在 META-INF
文件夹下获取文件名为 openapi.yaml 或 openapi.yml 或 openapi.json 的打开
API 的yaml文件。以下是如何记录API响应和操作的示例。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@GET
@Produces(MediaType.APPLICATION_JSON)
@APIResponse(
    responseCode = &quot;200&quot;,
    description = &quot;host:properties pairs stored in the inventory.&quot;,
    content = @Content(mediaType = &quot;application/json&quot;,
    schema = @Schema(type = SchemaType.OBJECT,
    implementation = InventoryList.class)))
@Operation(summary = &quot;List inventory contents.&quot;,
    description = &quot;Returns the stored host:properties pairs.&quot;)
public InventoryList listContents() {
    return manager.list();
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>在上述代码段中，端点 http://{host.name}:${port}/openapi
将通过以下输出公开。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>openapi: 3.0.0
info:
    title: Inventory App
    description: App for storing JVM system properties of various hosts.
license:
    name: Eclipse Public License - v 1.0
    url: https://www.eclipse.org/legal/epl-v10.html
version: &quot;1.0&quot;
    servers: - url: http://localhost:{port} description: Simple Open Liberty.
variables:
    port:
        description: Server HTTP port.
        default: &quot;9080&quot;
paths:
    /inventory/systems:
get:
    summary: List inventory contents.
    description: Returns the currently stored host:properties pairs in the
    inventory.
    operationId: listContents
responses:
    200:
        description: host:properties pairs stored in the inventory.
        content:
        application/json:
        schema:
        $ref: '#/components/schemas/InventoryList'
... .</code></pre>
</div>
</div>
<div class="paragraph">
<p>如果您使用 Open Liberty，端点
http://{host.name}:${port.number}/openapi/ui
也将被公开，这允许最终用户直接调用各个端点。</p>
</div>
<div class="imageblock text-center">
<div class="content">
<img src="/img/blog/MP_OpenAPI_UI.png" alt="OpenAPI UI" width="70%">
</div>
</div>
<div class="paragraph">
<p>如果您熟悉 Swagger API，您会发现这很熟悉。</p>
</div>
<div class="paragraph">
<p>请参阅<a href="https://openliberty.io/guides/microprofile-openapi.html">此</a>Open
Liberty 指南以了解有关 MicroProfile Open API 的更多信息。</p>
</div>
</div>
<div class="sect3">
<h4 id="spring文档">Spring文档</h4>
<div class="paragraph">
<p>Spring 使用测试来记录 API，并能够生成 API
文档作为测试运行的一部分。这是生成 Spring 文档的方法。</p>
</div>
<div class="paragraph">
<p>1.定义依赖</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.restdocs&lt;/groupId&gt;
    &lt;artifactId&gt;spring-restdocs-mockmvc&lt;/artifactId&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.restdocs &lt;/groupId&gt;
    &lt;artifactId&gt;spring-restdocs-core&lt;/artifactId&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>2.定义你的 Rest 服务</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@RestController
public class CatalogController {
    @RequestMapping(&quot;/&quot;)
    public @ResponseBody String index() {
        return &quot;Greetings from Catalog Service!&quot;;
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>3.定义所有必要的测试类</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@RunWith(SpringRunner.class)
@SpringBootTest(classes = CatalogController.class)
@WebAppConfiguration
public class CatalogControllerTest {
    @Rule public JUnitRestDocumentation restDocumentation = new
    JUnitRestDocumentation(&quot;target/generated-snippets&quot;);
    private MockMvc mockMvc;
    @Autowired private WebApplicationContext context;
    @Before public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context)
        .apply(documentationConfiguration(restDocumentation)) .build();

    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>4.<code>alwaysDo()</code>, <code>responseFileds()</code>, <code>requestPayload()</code>, <code>links()</code>, <code>fieldWithPath()</code>, <code>requestParameters()</code>, <code>pathParameters()</code> 用于记录</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Test
public void crudDeleteExample() throws Exception {
    this.mockMvc.perform(delete(&quot;/crud/{id}&quot;,
    10)).andExpect(status().isOk())
    .andDo(document(&quot;crud-delete-example&quot;,
    pathParameters(
    parameterWithName(&quot;id&quot;).description(&quot;The id of the input to delete&quot;)
    )));

}</code></pre>
</div>
</div>
<div class="paragraph">
<p>运行测试时，将生成 API 文档。</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="rest-client"><strong>Rest Client</strong></h3>
<div class="paragraph">
<p>云原生微服务不是独立的。微服务相互交互。一个微服务调用第二个微服务，然后第二个微服务调用第三个微服务，依此类推。通常，它是一种网状结构。例如，在微服务A调用微服务B的场景中，微服务 A 表现为客户端。如何建立从微服务A到微服务B的连接？ Rest client 来解决！</p>
</div>
<div class="sect3">
<h4 id="microprofile-rest-client">MicroProfile Rest Client</h4>
<div class="paragraph">
<p>JAX-RS 客户端可用于进行客户端服务器通信，详述如下。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>Client client = ClientBuilder.newClient();
Response res = client.target(&quot;http://example.org/hello&quot;).request(&quot;text/plain&quot;).get();</code></pre>
</div>
</div>
<div class="paragraph">
<p>但是，它不是类型安全的客户端，因此容易出错。传入错误参数的调用会导致运行时错误，这为时已晚。</p>
</div>
<div class="paragraph">
<p><a href="https://github.com/eclipse/microprofile-rest-client/releases">MicroProfile
Rest Client</a>是一种类型安全的 Rest
Client，它提供了一种更简单的方式来进行客户端服务器通信。它是如何工作的？以下是步骤。</p>
</div>
<div class="paragraph">
<p>步骤 1：注册一个 REST 客户端 API</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Dependent

@RegisterRestClient(baseUri=http://localhost:9080/system)
@RegisterProvider(InventoryResponseExceptionMapper.class)
public interface InventoryServiceClient {
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    List&lt;Item&gt; getAllItems() throws UnknownUrlException,
    ServiceNotReadyException;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>第 2 步：将客户端 API 注入客户端微服务 JAX-RS 资源</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Inject
@RestClient
private InventoryServiceClient invClient;
final List&lt;Item&gt; allItems = invClient.getAllItems();</code></pre>
</div>
</div>
<div class="paragraph">
<p>第3步：重新绑定后端微服务</p>
</div>
<div class="paragraph">
<p>io.openliberty.guides.inventory.client.SystemClient/mp-rest/url=http://otherhost:8080/system</p>
</div>
<div class="paragraph">
<p>使用附加的完全限定类名 <code>/mp-rest/url</code> 作为键，使用后端服务端点作为值。在云端部署此微服务时，后端URL会与其他环境不同。通常，您需要通过 Kubernetes ConfigMap 在客户端的
deployment.yaml 中重新绑定后端服务。</p>
</div>
<div class="paragraph">
<p>请参阅<a href="https://openliberty.io/guides/microprofile-rest-client.html">此</a>Open
Liberty 指南以了解有关 MicroProfile Rest Client 的更多信息。</p>
</div>
</div>
<div class="sect3">
<h4 id="spring-2">Spring</h4>
<div class="paragraph">
<p>Spring 使用了与 MicroProfile Rest Client 类似的方法，并使用了
FeignClient 和 Injection 等相应技术。</p>
</div>
<div class="paragraph">
<p><em>第 1 步：定义客户端</em></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@FeignClient(name=&quot;inventory-service&quot;, url=&quot;${inventoryService.url}&quot;)
public interface InventoryServiceClient {
    @RequestMapping(method=RequestMethod.GET,
    value=&quot;/micro/inventory&quot;, produces={MediaType.APPLICATION_JSON_VALUE})
    List&lt;Item&gt; getAllItems();
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>第2步：启用客户端并注入客户端</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@EnableFeignClients
public class Application {
    @Autowired
    private InventoryServiceClient invClient;
    final List&lt;Item&gt; allItems = invClient.getAllItems();
    ...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="在线负载-json"><strong>在线负载 - JSON</strong></h3>
<div class="paragraph">
<p>JSON 格式是网络上常见的媒体类型。JSON-B 和 JSON-P 是帮助处理 JSON
媒体类型的流行技术。</p>
</div>
<div class="sect3">
<h4 id="json-p-和-json-b">JSON-P 和 JSON-B</h4>
<div class="paragraph">
<p>MicroProfile 2.0 及更高版本同时支持JSON-B和JSON-P，这极大地简化了JSON 对象的序列化和反序列化。下面是使用 JSON-B 序列化 <code>artists</code> 对象的示例。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>public class car {
    private String make;
    private String model;
    private String reg;
    ...
}
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
Car car = new Car(&quot;VW&quot;, &quot;TGUAN&quot;, &quot;HN19MDZ&quot;);
Jsonb jsonb = JsonbBuilder.create();
String json = jsonb.toJson(car);</code></pre>
</div>
</div>
<div class="paragraph">
<p>The toJson () 方法返回序列化的 car对象。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>{
&quot;make&quot;: &quot;VW&quot;,
&quot;model&quot;: &quot;TGUAN&quot;,
&quot;reg&quot;: &quot;HN19MFZ&quot;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>使用 JSON-B 进行反序列化同样简单。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>Car car = Jsonb.fromJson(json, Car.class);</code></pre>
</div>
</div>
<div class="paragraph">
<p>为了在线传输 JSON 对象，您只需定义一个 POJO，例如</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>public class InventoryList {
    private List&lt;SystemData&gt; systems;
    public InventoryList(List&lt;SystemData&gt; systems) {
        this.systems = systems;
    }
    public List&lt;SystemData&gt; getSystems() {
        return systems;
    }

    public int getTotal() {
        return systems.size();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>在 JAX-RS 资源中，您可以直接将此类型作为 JSON 对象返回。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@GET
@Produces(MediaType.APPLICATION_JSON)

public InventoryList listContents() {
    return manager.list();
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>请参阅<a href="https://cloud.ibm.com/docs/java?topic=java-mp-json">本文</a>以了解有关
JSON-B 的更多信息。</p>
</div>
</div>
<div class="sect3">
<h4 id="spring-3">Spring</h4>
<div class="paragraph">
<p>Spring 可以直接使用 Jackson 或 JSON-B。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
final ObjectMapper objMapper = new ObjectMapper();
jsonString = objMapper.writeValueAsString(car);
// or use JSON-B
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
Jsonb jsonb = JsonbBuilder.create();
String result = jsonb.toJson(car);</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="处理-100-个微服务">处理 100 个微服务</h2>
<div class="sectionbody">
<div class="paragraph">
<p>在您的云基础架构中通常有 100 个微服务。在处理
100个服务时，您将需要监控服务、配置服务、对服务进行安全防护等。</p>
</div>
<div class="sect2">
<h3 id="配置微服务"><strong>配置微服务</strong></h3>
<div class="paragraph">
<p>云原生微服务是可配置的，因此它们可以由 DevOps
更新。开发人员不必因为配置值更改而重新打包微服务。设计原则是这些配置可以存储在微服务外部的某个地方，并且这些配置可供微服务使用。这被称为外部化配置，这是<a href="https://12factor.net/">12因素 APP</a>强调的因素之一。下面我们来看看 MicroProfile 和 Spring
是如何帮助我们配置微服务的。</p>
</div>
<div class="sect3">
<h4 id="microprofile配置"><strong>MicroProfile配置</strong></h4>
<div class="paragraph">
<p><a href="https://github.com/eclipse/microprofile-config/releases">MicroProfile
Config</a>通过将配置值放在配置源中来启用外部化配置，然后微服务可以使用注入或以编程方式查找来获取相应的配置值。</p>
</div>
<div class="paragraph">
<p>第 1
步：在配置源中指定配置，可以是系统属性、环境变量、microprofile-config.properties
或自定义配置源。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code># Elasticsearch
elasticsearch_url=http://es-catalog-elasticsearch:9200
elasticsearch_index=micro
elasticsearch_doc_type=items</code></pre>
</div>
</div>
<div class="paragraph">
<p>第 2 步：使用编程查找或注入</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>Config config = ConfigProvider.getConfig();
private String url = config.getValue(&quot;elasticsearch_url&quot;,
String.class);</code></pre>
</div>
</div>
<div class="paragraph">
<p>或者</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Inject @ConfigProperty(name=&quot;elasticsearch_url&quot;) String url;</code></pre>
</div>
</div>
<div class="paragraph">
<p>请参阅<a href="https://openliberty.io/guides/microprofile-config.html">此</a>Open
Liberty 指南以了解有关 MicroProfile Config 的更多信息。</p>
</div>
<div class="paragraph">
<p>让我们看看如何用 Spring 框架做同样的事情。</p>
</div>
</div>
<div class="sect3">
<h4 id="spring配置">Spring配置</h4>
<div class="paragraph">
<p>您可以使用 Spring config 通过以下步骤实现配置外部化。</p>
</div>
<div class="paragraph">
<p>第 1 步：在配置源中定义配置</p>
</div>
</div>
</div>
</div>
</div>
<h1 id="elasticsearch" class="sect0">Elasticsearch</h1>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>elasticsearch:
    url: http://localhost:9200
    user:
    password:
    index: micro
    doc_type: items</code></pre>
</div>
</div>
<div class="paragraph">
<p>第 2 步：将配置属性注入 bean</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Component(&quot;ElasticConfig&quot;)
@ConfigurationProperties(prefix = &quot;elasticsearch&quot;)
public class ElasticsearchConfig {
    // Elasticsearch stuff
    private String url;
    private String user;
    ...
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>第 3 步：将配置 bean 注入其他类</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Autowired
private ElasticsearchConfig config;
String url = config.getUrl();</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="容错"><strong>容错</strong></h3>
<div class="paragraph">
<p>云原生微服务需要容错，因为不确定因素或移动部件太多。MicroProfile和Spring都提供了一个模型来实现容错。</p>
</div>
<div class="sect3">
<h4 id="microprofile-容错">MicroProfile 容错</h4>
<div class="paragraph">
<p><a href="https://github.com/eclipse/microprofile-fault-tolerance/releases">MicroProfile Fault Tolerance</a>通过使用@Timeout、@Retry、@Fallback、@Bulkhead、@CircuitBreaker
的注解提供以下能力：</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p></p>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>超时：定义超时的持续时间</p>
</div>
</blockquote>
</div>
</li>
<li>
<p></p>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>重试：定义何时重试的标准</p>
</div>
</blockquote>
</div>
</li>
<li>
<p></p>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>回退：为失败的执行提供替代解决方案。</p>
</div>
</blockquote>
</div>
</li>
<li>
<p></p>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>故障隔离：隔离部分系统的故障，而系统的其余部分仍能工作。</p>
</div>
</blockquote>
</div>
</li>
<li>
<p></p>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>断路器：通过自动执行失败，提供一种快速故障方式，以防止系统过载和客户端无限期等待或超时。</p>
</div>
</blockquote>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>以下代码片段描述了 <code>getInventory()</code> 2s 后超时的调用。如果操作失败，则在 2s
的总时长内最多重试 2 次。连续 20
次调用，如果发生一半故障，电路将被困开。如果重试后仍然失败，<code>fallbackInventory</code> 将调用回退操作方法。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Timeout(value = 2, unit = ChronoUnit.SECONDS)
@Retry(maxRetries = 2, maxDuration = 2000)
@CircuitBreaker
@Fallback(fallbackMethod = &quot;fallbackInventory&quot;)
@GET
public List&lt;Item&gt; getInventory() {
    return items;
}
public List&lt;Item&gt; fallbackInventory() {
    //Returns a default fallback
    return fallbackitemslist;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>请参阅<a href="https://openliberty.io/guides/retry-timeout.html"><span class="underline">此</span></a>交互式
Open Liberty 指南以了解有关 MicroProfile 容错的更多信息。</p>
</div>
</div>
<div class="sect3">
<h4 id="spring-fault-tolerance">Spring Fault Tolerance</h4>
<div class="paragraph">
<p>Spring 使用 Hysterix 来实现容错，下文详述。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Service
public class AppService {
    @HystrixCommand(fallbackMethod = &quot;fallback&quot;)
    public List&lt;Item&gt; getInventory() {
        return items;
    }
    public List&lt;Item&gt; fallback() {
        //Returns a default fallback
        return fallbackitemslist;
    }
}

import
org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker
@SpringBootApplication
@RestController
@EnableCircuitBreaker
public class Application {
    ...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="microservices安全"><strong>Microservices安全</strong></h3>
<div class="paragraph">
<p>云原生微服务应该是安全的，因为它们是公开的，容易受到攻击。MicroProfile
将 MicroProfile JWT 与 Java EE Security 一起使用，而 Spring 使用 Spring
安全性。</p>
</div>
<div class="sect3">
<h4 id="microprofile-jwt">MicroProfile JWT</h4>
<div class="paragraph">
<p>MicroProfile JWT 构建在 JWT 之上，向 JWT 添加了一些声明以识别用户ID和用户规则。以下代码片段演示了端点 /orders
只能由具有“<code>admin</code>” 角色的人访问。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@DeclareRoles({&quot;Admin&quot;, &quot;User&quot;})
@RequestScoped
@Path(&quot;/orders&quot;)
public class OrderService {
@Inject private JsonWebToken jwt;
@GET
@RolesAllowed({ &quot;admin&quot; })
@Produces(MediaType.APPLICATION_JSON)
public InventoryList listContents() {
    return manager.list();
}
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>请参阅此<a href="https://openliberty.io/guides/microprofile-jwt.html">Open Liberty
指南</a>以了解如何使用 MicroProfile JWT。</p>
</div>
</div>
<div class="sect3">
<h4 id="spring-security">Spring Security</h4>
<div class="paragraph">
<p>您可以通过配置 Spring Security 来保护 Spring 微服务。如果 Spring Security 在类路径上，则 Spring Boot 使用基本身份验证自动保护所有 HTTP端点。</p>
</div>
<div class="paragraph">
<p>首先，您需要指定对 <code>spring-boot-starter-security</code>.<br>
其次，在您的微服务中，指定以下注释 <code>EnableWebSecurity</code> 或 <code>EnableResourceServer</code> 保护微服务。请参见下面的示例</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Configuration
@EnableWebSecurity
@EnableResourceServer
public class OAuth2ResourceServerConfig extends
ResourceServerConfigurerAdapter {
    @Autowired
    Private JWTConfig securityConfig;
    ....
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>微服务性能</p>
</div>
<div class="paragraph">
<p>在云中部署微服务后，DevOps 负责监控微服务的性能。如果出现问题，DevOps需要一些监控数据来识别瓶颈或从指标数据中发现任何警告。智能云原生微服务应该能够与云基础设施就其健康状态进行通信，了解它是否准备好接收流量或服务请求等。让我们看看编程模型在这方面必须提供什么。</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="健康检查"><strong>健康检查</strong></h3>
<div class="paragraph">
<p>云原生微服务应该能够与云基础设施就其健康状态进行通信。MicroProfile和Spring都提供了这种能力。Kubernetes
是最流行的微服务编排器，可以检查容器（正在运行的微服务实例）的就绪或活跃状态。如果微服务不活跃，需要执行pod
重启，比如内存不足。未就绪是指微服务还没有为服务器请求做好准备，比如数据库连接异常等。</p>
</div>
<div class="sect3">
<h4 id="microprofile-health">MicroProfile Health</h4>
<div class="paragraph">
<p>MicroProfile Health 2.0及更高版本提供就绪和在线端点。微服务可以提供 <code>HealthCheck</code> 带有注释的实现 <code>@Readiness</code> 以配置就绪检查过程。所有bean实 <code>HealthCheck</code> 和注解的聚合 <code>@Readiness</code> 配置了/ready的端点。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Readiness
public class HealthEndpoint implements HealthCheck {
    @Override
    public HealthCheckResponse call() {...}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>类似地，微服务可以提供带有注释的 HealthCheck
实现，<code>@Liveness</code> 以配置活动检查过程。<code>HealthCheck</code> 带有注解的所有 bean
实现的聚合 <code>@Liveness</code> 配置了 /live 的端点。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Liveness
public class HealthEndpoint implements HealthCheck {
    @Override
    public HealthCheckResponse call() {...}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Kubernetes 可以根据下面的代码片段在其 liveness 或 readiness或startup探针中相应地查询 /health/live 或 /health/ready 或/health/started端点。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="json"><span class="error">l</span><span class="error">i</span><span class="error">v</span><span class="error">e</span><span class="error">n</span><span class="error">e</span><span class="error">s</span><span class="error">s</span><span class="error">P</span><span class="error">r</span><span class="error">o</span><span class="error">b</span><span class="error">e</span>:
    <span class="error">e</span><span class="error">x</span><span class="error">e</span><span class="error">c</span>:
        <span class="error">c</span><span class="error">o</span><span class="error">m</span><span class="error">m</span><span class="error">a</span><span class="error">n</span><span class="error">d</span>:
            <span class="error">-</span> <span class="error">c</span><span class="error">u</span><span class="error">r</span><span class="error">l</span>
            <span class="error">-</span> <span class="error">-</span><span class="error">f</span>
            <span class="error">-</span> <span class="error">h</span><span class="error">t</span><span class="error">t</span><span class="error">p</span>:<span class="error">/</span><span class="error">/</span><span class="error">l</span><span class="error">o</span><span class="error">c</span><span class="error">a</span><span class="error">l</span><span class="error">h</span><span class="error">o</span><span class="error">s</span><span class="error">t</span>:<span class="integer">9080</span><span class="error">/</span><span class="error">h</span><span class="error">e</span><span class="error">a</span><span class="error">l</span><span class="error">t</span><span class="error">h</span><span class="error">/</span><span class="error">l</span><span class="error">i</span><span class="error">v</span><span class="error">e</span>
    <span class="error">i</span><span class="error">n</span><span class="error">i</span><span class="error">t</span><span class="error">i</span><span class="error">a</span><span class="error">l</span><span class="error">D</span><span class="error">e</span><span class="error">l</span><span class="error">a</span><span class="error">y</span><span class="error">S</span><span class="error">e</span><span class="error">c</span><span class="error">o</span><span class="error">n</span><span class="error">d</span><span class="error">s</span>: <span class="integer">120</span>
    <span class="error">p</span><span class="error">e</span><span class="error">r</span><span class="error">i</span><span class="error">o</span><span class="error">d</span><span class="error">S</span><span class="error">e</span><span class="error">c</span><span class="error">o</span><span class="error">n</span><span class="error">d</span><span class="error">s</span>: <span class="integer">10</span>
<span class="error">r</span><span class="error">e</span><span class="error">a</span><span class="error">d</span><span class="error">i</span><span class="error">n</span><span class="error">e</span><span class="error">s</span><span class="error">s</span><span class="error">P</span><span class="error">r</span><span class="error">o</span><span class="error">b</span><span class="error">e</span>:
    <span class="error">e</span><span class="error">x</span><span class="error">e</span><span class="error">c</span>:
        <span class="error">c</span><span class="error">o</span><span class="error">m</span><span class="error">m</span><span class="error">a</span><span class="error">n</span><span class="error">d</span>:
            <span class="error">-</span> <span class="error">c</span><span class="error">u</span><span class="error">r</span><span class="error">l</span>
            <span class="error">-</span> <span class="error">-</span><span class="error">f</span>
            <span class="error">-</span> <span class="error">h</span><span class="error">t</span><span class="error">t</span><span class="error">p</span>:<span class="error">/</span><span class="error">/</span><span class="error">l</span><span class="error">o</span><span class="error">c</span><span class="error">a</span><span class="error">l</span><span class="error">h</span><span class="error">o</span><span class="error">s</span><span class="error">t</span>:<span class="integer">9080</span><span class="error">/</span><span class="error">h</span><span class="error">e</span><span class="error">a</span><span class="error">l</span><span class="error">t</span><span class="error">h</span><span class="error">/</span><span class="error">r</span><span class="error">e</span><span class="error">a</span><span class="error">d</span><span class="error">y</span>
    <span class="error">i</span><span class="error">n</span><span class="error">i</span><span class="error">t</span><span class="error">i</span><span class="error">a</span><span class="error">l</span><span class="error">D</span><span class="error">e</span><span class="error">l</span><span class="error">a</span><span class="error">y</span><span class="error">S</span><span class="error">e</span><span class="error">c</span><span class="error">o</span><span class="error">n</span><span class="error">d</span><span class="error">s</span>: <span class="integer">120</span>
    <span class="error">p</span><span class="error">e</span><span class="error">r</span><span class="error">i</span><span class="error">o</span><span class="error">d</span><span class="error">S</span><span class="error">e</span><span class="error">c</span><span class="error">o</span><span class="error">n</span><span class="error">d</span><span class="error">s</span>: <span class="integer">10</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>请参阅此<a href="https://openliberty.io/guides/kubernetes-microprofile-health.html">Open Liberty指南</a>以了解如何使用 MicroProfile Health。</p>
</div>
</div>
<div class="sect3">
<h4 id="spring-4">Spring</h4>
<div class="paragraph">
<p>Spring Boot使用Actuator 提供应用程序的健康状态。SpringBoot Actuator</p>
</div>
<div class="paragraph">
<p>暴露 /health
端点来指示正在运行的应用程序的健康状态，例如数据库连接、磁盘空间不足等。应用程序通过 <code>HealthIndicator</code>. 此健康信息是从所有实现 <code><em>HealthIndicator</em></code> 应用程序上下文中配置的接口的bean中收集的。下面是自定义运行状况实施的示例。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Component
public class HealthCheck implements HealthIndicator {
    @Override
    public Health health() {
        int errorCode = check(); // perform some specific health check
        if (errorCode != 0) {
            return Health.down().withDetail(&quot;Error Code&quot;, errorCode).build();
        }
        return Health.up().build();
    }
    public int check() {
        // Our logic to check health
        return 0;
    }
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="metrics"><strong>Metrics</strong></h3>
<div class="paragraph">
<p>对于正在运行的云原生微服务，了解它正在服务的流量、吞吐量是多少以及它可能很快停止工作的任何迹象都是很有用的。Metrics可以帮助解决这个问题。</p>
</div>
<div class="sect3">
<h4 id="microprofile-metrics">MicroProfile Metrics</h4>
<div class="paragraph">
<p><a href="https://github.com/eclipse/microprofile-metrics/releases">MicroProfileMetrics</a>提供了一个端点 <code>/metrics</code> 来公开所有指标信息，包括下划线运行时。<code>/metrics</code>
的端点显示一些基本指标。例如，Open Liberty
提供了以下开箱即用的指标类型。本文省略了每种类型的详细信息。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code># TYPE base:classloader_total_loaded_class_count counter
# TYPE base:gc_global_count counter
# TYPE base:cpu_system_load_average gauge
# TYPE base:thread_count counter
# TYPE base:classloader_current_loaded_class_count counter
# TYPE base:gc_scavenge_time_seconds gauge
# TYPE base:jvm_uptime_seconds gauge
# TYPE base:memory_committed_heap_bytes gauge
# TYPE base:thread_max_count counter
# TYPE base:cpu_available_processors gauge
# TYPE base:thread_daemon_count counter
# TYPE base:gc_scavenge_count counter
# TYPE base:classloader_total_unloaded_class_count counter
# TYPE base:memory_max_heap_bytes gauge
# TYPE base:cpu_process_cpu_load_percent gauge
# TYPE base:memory_used_heap_bytes gauge
# TYPE base:gc_global_time_seconds gauge
...</code></pre>
</div>
</div>
<div class="paragraph">
<p>您可以添加特定于应用程序的指标以收集更多指标。以下是如何收集关联端点的响应时间和调用次数等的示例。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Timed(name = &quot;Inventory.timer&quot;, absolute = true, displayName=&quot;Inventory
Timer&quot;, description = &quot;Time taken by the Inventory&quot;, reusable=true)

@Counted(name=&quot;Inventory&quot;, displayName=&quot;Inventory Call count&quot;,
description=&quot;Number of times the Inventory call happened.&quot;,
monotonic=true, reusable=true)

@Metered(name=&quot;InventoryMeter&quot;, displayName=&quot;Inventory Call Frequency&quot;,
description=&quot;Rate of the calls made to Inventory&quot;, reusable=true)
// Get all rows from database

public List&lt;Item&gt; findAll(){ }</code></pre>
</div>
</div>
<div class="paragraph">
<p>请参阅此<a href="https://openliberty.io/guides/microprofile-metrics.html">Open
Liberty 指南</a>以了解如何使用 MicroProfile Metrics。</p>
</div>
</div>
<div class="sect3">
<h4 id="spring-actuator">Spring Actuator</h4>
<div class="paragraph">
<p>Spring 通过 Spring Actuator 提供度量指标。Spring Actuator公开一个端点 <code>/metrics</code> 以显示应用程序指标。在以下代码片段中，<code>/metrics</code> 显示有效列表的数量和无效列表的计数。下面是自定义
Metrics 实现的示例。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>@Service
public class LoginServiceImpl {
    private final CounterService counterService;
    public List&lt;Item&gt; findAll (CounterService counterService) {
        this.counterService = counterService;
        if(list.size()&gt;1)
            counterService.increment(&quot;counter.list.valid &quot;);
        else
            counterService.increment(&quot;counter.list.invalid&quot;);
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="分布式跟踪"><strong>分布式跟踪</strong></h3>
<div class="paragraph">
<p>在微服务架构中，一个微服务调用另一个微服务是很常见的。对于
DevOps，查看调用链很重要。当出现问题时，应立即将故障服务固定下来。为了支持这一点，我们需要一种方法来创建调用链。幸运的是，这就是分布式跟踪发挥作用的地方。分布式跟踪的实现细节是将关联
id 沿调用链传播，以便 Zipkin 或 Jaeger 可以使用此公共关联 id
形成一条链。MicroProfile 和 Spring 都具有分布式跟踪支持。</p>
</div>
<div class="sect3">
<h4 id="microprofile-open-tracing">MicroProfile Open Tracing</h4>
<div class="paragraph">
<p><a href="https://github.com/eclipse/microprofile-opentracing/releases"><span class="underline">MicroProfile Open Tracing</span></a>定义了用于访问 JAX-RS 应用程序中符合 OpenTracing的Tracer对象的行为和 API。这些行为指定传入和传出请求将如何自动创建OpenTracing Span。</p>
</div>
<div class="paragraph">
<p>当从被跟踪的客户端发送请求时，会创建一个新的 Span，并将其 SpanContext注入到出站请求中以向下游传播。如果存在活动 Span，则新 Span 将是活动 Span
的孩子。当出站请求完成时，新的 Span 将完成。所有 JAX-RS 和 Rest Client调用都会自动传播相关 ID。</p>
</div>
<div class="paragraph">
<p>您可以指定非JAX-RS操作以通过传播相关ID <code>@Traced</code>，详情如下。</p>
</div>
<div class="paragraph">
<p>自定义跟踪实现</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>import org.eclipse.microprofile.opentracing.Traced;
import io.opentracing.ActiveSpan;
import io.opentracing.Tracer;
@Traced(value = true, operationName =&quot;getCatalog.list&quot;)
public List&lt;Item&gt; getInventory() {
    try (ActiveSpan childSpan = tracer.buildSpan(&quot;Grabbing messages from Messaging System&quot;).startActive()) {...}

}</code></pre>
</div>
</div>
<div class="paragraph">
<p>访问此 Open Liberty <a href="https://openliberty.io/guides/microprofile-opentracing.html">指南</a>，了解有关
MicroProfile Open Tracing 的更多信息。</p>
</div>
</div>
<div class="sect3">
<h4 id="spring-tracing">Spring Tracing</h4>
<div class="paragraph">
<p>Spring 使用 Spring Cloud Sleuth来提供分布式跟踪支持。如果在类路径中配置了Spring cloud sleuth，则会自动生成trace信息。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-starter-sleuth&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>至此，您应该对 MicroProfile 和 Spring
的功能有了一些了解，让我们开始创建您的云原生微服务。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="入门">入门</h2>
<div class="sectionbody">
<div class="paragraph">
<p>MicroProfile和Spring 都有一个起始页。</p>
</div>
<div class="sect2">
<h3 id="microprofile-入门">MicroProfile 入门</h3>
<div class="paragraph">
<p>MicroProfile starter ( <a href="https://start.microprofile.io/ " class="bare">https://start.microprofile.io/ </a>)
为您提供了一种使用 MicroProfile
创建微服务的好方法，您可以选择自己喜欢的运行容器，例如<a href="https://openliberty.io/">Open
Liberty</a>、<a href="https://thorntail.io/">Thorntail</a>、<a href="https://www.payara.fish/">Payara</a>、<a href="https://tomee.apache.org/">TomEE</a>、<a href="https://ee.kumuluz.com/">KumuluzEE</a>、<a href="https://helidon.io/">Helidon</a>等.</p>
</div>
<div class="imageblock text-center">
<div class="content">
<img src="/img/blog/MP_starter.png" alt="MicroProfile Starter" width="70%">
</div>
</div>
<div class="paragraph">
<p>您还可以使用命令行使用 MicroProfile
创建微服务。有关如何使用命令行工具，请参阅<a href="https://microprofile.io/2019/07/08/command-line-interface-for-microprofile-starter-is-available-now/">Karm
的博客</a>我们提供 VS Code 和 Intellij扩展插件，以允许您直接从您的 IDE
创建微服务。我们计划为其他 IDE 创建扩展，例如Eclipse IDE 等。敬请期待！</p>
</div>
</div>
<div class="sect2">
<h3 id="spring-starter">Spring Starter</h3>
<div class="paragraph">
<p>Spring 有一个起始页面 ( <a href="https://start.spring.io/ " class="bare">https://start.spring.io/ </a>) 可帮助您创建 Spring
Boot 应用程序。</p>
</div>
<div class="imageblock text-center">
<div class="content">
<img src="/img/blog/spring_starter.png" alt="SpringBoot starter" width="70%">
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="差异">差异</h2>
<div class="sectionbody">
<div class="paragraph">
<p>从功能的角度来看，MicroProfile 和 Spring
具有可比性。但是，它们确实存在差异，总结如下。</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top"></th>
<th class="tableblock halign-left valign-top"><strong>Spring</strong></th>
<th class="tableblock halign-left valign-top"><strong>MicroProfile</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>APIs</strong></p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>开源</p>
</div>
<div class="paragraph">
<p>WMware 驱动<br>
Spring 定义</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">开源<br>
社区驱动<br>
开放标准，符合规范行为</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">代码行</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>多代码</p>
</div>
<div class="paragraph">
<p>做你想做/需要的事情</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>少代码</p>
</div>
<div class="paragraph">
<p>自定义服务器配置</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">库/依赖项</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>查找、混合和匹配您喜欢的内容</p>
</div>
<div class="paragraph">
<p>管理您自己的依赖项</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">服务器提供每个规范所需的内容</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">应用程序包装</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Fat JARs</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Thin/Skinny JARs<br>
注意：Liberty 已优化对容器中的 Spring Boot 应用程序的支持</p></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect1">
<h2 id="总结">总结</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Spring 和 Eclipse MicroProfile
都为开发人员提供了构建下一代云原生微服务的工具，并具有以下观察结果。它们有相似之处，也有不同之处（有时是重要的）</p>
</div>
<div class="paragraph">
<p>Spring已经存在了好几年，并获得了很多人气。MicroProfile 和 Jakarta
EE作为社区驱动和基于标准的企业 Java
微服务和云原生应用程序开发工作正在迅速发展（并获得动力）。</p>
</div>
<div class="paragraph">
<p>开发人员现在可以选择他们喜欢的东西，这很棒。公司应该为开发人员提供能够实现创新和灵活性并为企业和生产做好准备的平台。Open
Liberty ( <a href="https://openliberty.io/ " class="bare">https://openliberty.io/ </a>)
是一个快速、小型和轻量级的运行时，同时支持MicroProfile/Jakarta EE 和
Spring。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="致谢">致谢</h2>
<div class="sectionbody">
<div class="paragraph">
<p>本文深受将 IBM BlueCompute 微服务从 Spring 迁移到 Eclipse MicroProfile
实践的影响。可以在<a href="https://www.ibm.com/cloud/blog/migrate-java-microservices-from-spring-to-microprofile-p1">此处</a>找到描述迁移的系列博客。非常感谢我的同事
YK Chang 对本文的贡献。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="参考">参考</h2>
<div class="sectionbody">
<div class="olist arabic">
<ol class="arabic">
<li>
<p><a href="https://www.ibm.com/blogs/bluemix/2018/09/migrate-java-microservices-from-spring-to-microprofile-p1/">将
Bluecompte 应用程序从 Spring 迁移到 MicroProfile 博客</a></p>
</li>
<li>
<p><a href="https://microprofile.io/">MicroProfile 网站</a></p>
</li>
<li>
<p><a href="https://wiki.eclipse.org/MicroProfile/Implementation">MicroProfile
实现运行时</a></p>
</li>
<li>
<p><a href="https://start.microprofile.io/">MicroProfile 起始页</a></p>
</li>
<li>
<p><a href="https://microprofile.io/blog/">MicroProfile 博客</a></p>
</li>
<li>
<p><a href="https://openliberty.io/">Open Liberty网站</a></p>
</li>
<li>
<p><a href="https://www.eclipse.org/community/eclipse_newsletter/2018/september/MicroProfile_istio.php">MicroProfile
和 Istio 生态系统</a></p>
</li>
<li>
<p><a href="https://github.com/IBM/cloud-native-starter">带有 MicroProfile 和 Istio
的 Cloud Native Starter</a></p>
</li>
</ol>
</div>
</div>
</div>]]></content><author><name>Emily Jiang</name></author><category term="blog" /><summary type="html"><![CDATA[原出版: Eclipse 基金会2019年9月月报: https://www.eclipse.org/community/eclipse_newsletter/2019/september/microprofile.php]]></summary></entry></feed>