1. Overview
1.概述
In this tutorial, we’ll understand the basic need for a container orchestration system.
在本教程中,我们将了解对容器编排系统的基本需求。
We’ll evaluate the desired characteristic of such a system. From that, we’ll try to compare two of the most popular container orchestration systems in use today, Apache Mesos and Kubernetes.
我们将评估这样一个系统的理想特征。由此,我们将尝试比较当今最流行的两个容器编排系统,即Apache Mesos和Kubernetes。
2. Container Orchestration
2.容器编排
Before we begin comparing Mesos and Kubernetes, let’s spend some time in understanding what containers are and why we need container orchestration after all.
在我们开始比较Mesos和Kubernetes之前,让我们花一些时间来了解什么是容器,以及为什么我们需要容器编排。
2.1. Containers
2.1.容器
A container is a standardized unit of software that packages code and all its required dependencies.
一个容器是一个标准化的软件单位,它将代码及其所有必要的依赖性打包。
Hence, it provides platform independence and operational simplicity. Docker is one of the most popular container platforms in use.
因此,它提供了平台独立性和操作简单性。Docker是正在使用的最流行的容器平台之一。
Docker leverages Linux kernel features like CGroups and namespaces to provide isolation of different processes. Therefore, multiple containers can run independently and securely.
Docker利用Linux内核的特性(如CG组和命名空间)来提供不同进程之间的隔离。因此,多个容器可以独立和安全地运行。
It’s quite trivial to create docker images, all we need is a Dockerfile:
创建docker镜像非常简单,我们所需要的只是一个Docker文件。
FROM openjdk:8-jdk-alpine
VOLUME /tmp
COPY target/hello-world-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
EXPOSE 9001
So, these few lines are good enough to create a Docker image of a Spring Boot application using the Docker CLI:
因此,这几行字足以使用Docker CLI创建一个Spring Boot应用程序的Docker镜像。
docker build -t hello_world .
2.2. Container Orchestration
2.2.容器编排
So, we’ve seen how containers can make application deployment reliable and repeatable. But why do we need container orchestration?
所以,我们已经看到了容器如何使应用程序的部署变得可靠和可重复。但为什么我们需要容器协调呢?
Now, while we’ve got a few containers to manage, we’re fine with Docker CLI. We can automate some of the simple chores as well. But what happens when we’ve to manage hundreds of containers?
现在,虽然我们有一些容器需要管理,但我们用Docker CLI就可以了。我们也可以将一些简单的杂事自动化。但是当我们要管理数以百计的容器时,会发生什么?
For instance, think of architecture with several microservices, all with distinct scalability and availability requirements.
例如,想想有几个微服务的架构,都有不同的可扩展性和可用性要求。
Consequently, things can quickly get out of control, and that’s where the benefits of a container orchestration system realize. A container orchestration system treats a cluster of machines with a multi-container application as a single deployment entity. It provides automation from initial deployment, scheduling, updates to other features like monitoring, scaling, and failover.
因此,事情会很快失去控制,而这正是容器协调系统的好处所在。一个容器协调系统将具有多容器应用程序的机器集群视为一个单一的部署实体。它提供了从初始部署、调度、更新到其他功能的自动化,如监控、扩展和故障转移。
3. Brief Overview of Mesos
3.Mesos的简要概述
Apache Mesos is an open-source cluster manager developed originally at UC Berkeley. It provides applications with APIs for resource management and scheduling across the cluster. Mesos gives us the flexibility to run both containerized and non-containerized workload in a distributed manner.
Apache Mesos是最初由UC Berkeley开发的开源集群管理器。它为应用程序提供了用于整个集群的资源管理和调度的API。Mesos使我们能够灵活地以分布式方式运行容器化和非容器化的工作负载。
3.1. Architecture
3.1.建筑
Mesos architecture consists of Mesos Master, Mesos Agent, and Application Frameworks:
Mesos架构由Mesos Master、Mesos Agent和应用框架组成。
Let’s understand the components of architecture here:
让我们在这里了解一下架构的组成部分。
- Frameworks: These are the actual applications that require distributed execution of tasks or workload. Typical examples are Hadoop or Storm. Frameworks in Mesos comprise of two primary components:
- Scheduler: This is responsible for registering with the Master Node such that the master can start offering resources
- Executor: This is the process which gets launched on the agent nodes to run the framework’s tasks
- Mesos Agents: These are responsible for actually running the tasks. Each agent publishes its available resources like CPU and memory to the master. On receiving tasks from the master, they allocate required resources to the framework’s executor.
- Mesos Master: This is responsible for scheduling tasks received from the Frameworks on one of the available agent nodes. Master makes resource offers to Frameworks. Framework’s scheduler can choose to run tasks on these available resources.
3.2. Marathon
3.2.马拉松
As we just saw, Mesos is quite flexible and allows frameworks to schedule and execute tasks through well defined APIs. However, it’s not convenient to implement these primitives directly, especially when we want to schedule custom applications. For instance, orchestrating applications packaged as containers.
正如我们刚刚看到的,Mesos相当灵活,允许框架通过定义好的API来安排和执行任务。然而,直接实现这些基元并不方便,特别是当我们想要调度自定义应用程序时。例如,协调打包成容器的应用程序。
This is where a framework like Marathon can help us. Marathon is a container orchestration framework which runs on Mesos. In this regard, Marathon acts as a framework for the Mesos cluster. Marathon provides several benefits which we typically expect from an orchestration platform like service discovery, load balancing, metrics, and container management APIs.
这时,像马拉松这样的框架可以帮助我们。马拉松是一个在Mesos上运行的容器编排框架。在这方面,马拉松充当了Mesos集群的框架。马拉松提供了一些我们通常期望从协调平台获得的好处,如服务发现、负载平衡、度量和容器管理API。
Marathon treats a long-running service as an application and an application instance as a task. A typical scenario can have multiple applications with dependencies forming what is called Application Groups.
Marathon 将一个长期运行的服务视为一个应用程序,将一个应用程序实例视为一个任务。一个典型的场景可能有多个具有依赖关系的应用程序,形成所谓的应用程序组。
3.3. Example
3.3.例子
So, let’s see how we can use Marathon to deploy our simple Docker image we created earlier. Note that installing a Mesos cluster can be little involved and hence we can use a more straightforward solution like Mesos Mini. Mesos Mini enables us to spin up a local Mesos cluster in a Docker environment. It includes a Mesos Master, single Mesos Agent, and Marathon.
因此,让我们看看如何使用马拉松来部署我们之前创建的简单Docker镜像。请注意,安装一个Mesos集群可能会有一些麻烦,因此我们可以使用一个更直接的解决方案,如Mesos Mini。Mesos Mini使我们能够在Docker环境中启动一个本地Mesos集群。它包括一个Mesos主站、单个Mesos代理和马拉松。
Once we’ve Mesos cluster with Marathon up and running, we can deploy our container as a long-running application service. All we need a small JSON application definition:
一旦我们的Mesos集群与马拉松启动并运行,我们就可以将我们的容器部署为一个长期运行的应用服务。我们所需要的只是一个小型的JSON应用定义。
#hello-marathon.json
{
"id": "marathon-demo-application",
"cpus": 1,
"mem": 128,
"disk": 0,
"instances": 1,
"container": {
"type": "DOCKER",
"docker": {
"image": "hello_world:latest",
"portMappings": [
{ "containerPort": 9001, "hostPort": 0 }
]
}
},
"networks": [
{
"mode": "host"
}
]
}
Let’s understand what exactly is happening here:
让我们了解一下这里到底发生了什么。
- We have provided an id for our application
- Then, we defined the resource requirements for our application
- We also defined how many instances we’d like to run
- Then, we’ve provided the container details to launch an app from
- Finally, we’ve defined the network mode for us to be able to access the application
We can launch this application using the REST APIs provided by Marathon:
我们可以使用马拉松提供的REST APIs来启动这个应用程序。
curl -X POST \
http://localhost:8080/v2/apps \
-d @hello-marathon.json \
-H "Content-type: application/json"
4. Brief Overview of Kubernetes
4.Kubernetes的简要概述
Kubernetes is an open-source container orchestration system initially developed by Google. It’s now part of Cloud Native Computing Foundation (CNCF). It provides a platform for automating deployment, scaling, and operations of application container across a cluster of hosts.
Kubernetes是一个开源的容器编排系统,最初由Google开发。它现在是云原生计算基金会(CNCF)的一部分。它提供了一个平台,用于自动部署、扩展和操作跨主机集群的应用容器。
4.1. Architecture
4.1.建筑
Kubernetes architecture consists of a Kubernetes Master and Kubernetes Nodes:
Kubernetes架构由Kubernetes Master和Kubernetes Nodes组成。
Let’s go through the major parts of this high-level architecture:
让我们来看看这个高层架构的主要部分。
- Kubernetes Master: The master is responsible for maintaining the desired state of the cluster. It manages all nodes in the cluster. As we can see, the master is a collection of three processes:
- kube-apiserver: This is the service that manages the entire cluster, including processing REST operations, validating and updating Kubernetes objects, performing authentication and authorization
- kube-controller-manager: This is the daemon that embeds the core control loop shipped with Kubernetes, making the necessary changes to match the current state to the desired state of the cluster
- kube-scheduler: This service watches for unscheduled pods and binds them to nodes depending upon requested resources and other constraints
- Kubernetes Nodes: The nodes in a Kubernetes cluster are the machines that run our containers. Each node contains the necessary services to run the containers:
- kubelet: This is the primary node agent which ensures that the containers described in PodSpecs provided by kube-apiserver are running and healthy
- kube-proxy: This is the network proxy running on each node and performs simple TCP, UDP, SCTP stream forwarding or round-robin forwarding across a set of backends
- container runtime: This is the runtime where container inside the pods are run, there are several possible container runtimes for Kubernetes including the most widely used, Docker runtime
4.2. Kubernetes Objects
4.2 Kubernetes对象
In the last section, we saw several Kubernetes objects which are persistent entities in the Kubernetes system. They reflect the state of the cluster at any point in time.
在上一节中,我们看到了几个Kubernetes对象,它们是Kubernetes系统中的持久性实体。它们反映了集群在任何时间点上的状态。
Let’s discuss some of the commonly used Kubernetes objects:
让我们来讨论一些常用的Kubernetes对象。
- Pods: Pod is a basic unit of execution in Kubernetes and can consist of one or more containers, the containers inside a Pod are deployed on the same host
- Deployment: Deployment is the recommended way to deploy pods in Kubernetes, it provides features like continuously reconciling the current state of pods with the desired state
- Services: Services in Kubernetes provide an abstract way to expose a group of pods, where the grouping is based on selectors targetting pod labels
There are several other Kubernetes objects which serve the purpose of running containers in a distributed manner effectively.
还有其他几个Kubernetes对象,可以有效地以分布式方式运行容器。
4.3. Example
4.3.例子
So, now we can try to launch our Docker container into the Kubernetes cluster. Kubernetes provides Minikube, a tool that runs single-node Kubernetes cluster on a Virtual Machine. We’d also need kubectl, the Kubernetes Command Line Interface to work with the Kubernetes cluster.
因此,现在我们可以尝试将我们的Docker容器启动到Kubernetes集群中。Kubernetes提供了Minikube,这是一个可以在虚拟机上运行单节点Kubernetes集群的工具。我们还需要kubectl,即Kubernetes命令行界面,以便与Kubernetes集群一起工作。
After we’ve kubectl and Minikube installed, we can deploy our container on the single-node Kubernetes cluster within Minikube. We need to define the basic Kubernetes objects in a YAML file:
在我们安装了kubectl和Minikube之后,我们可以在Minikube内的单节点Kubernetes集群上部署我们的容器。我们需要在YAML文件中定义基本的Kubernetes对象。
# hello-kubernetes.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 1
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: hello-world:latest
ports:
- containerPort: 9001
---
apiVersion: v1
kind: Service
metadata:
name: hello-world-service
spec:
selector:
app: hello-world
type: LoadBalancer
ports:
- port: 9001
targetPort: 9001
A detailed analysis of this definition file is not possible here, but let’s go through the highlights:
这里不可能对这个定义文件进行详细分析,但让我们来看看其中的要点。
- We have defined a Deployment with labels in the selector
- We define the number of replicas we need for this deployment
- Also, we’ve provided the container image details as a template for the deployment
- We’ve also defined a Service with appropriate selector
- We’ve defined the nature of the service as LoadBalancer
Finally, we can deploy the container and create all defined Kubernetes objects through kubectl:
最后,我们可以通过kubectl部署容器并创建所有定义的Kubernetes对象。
kubectl apply -f yaml/hello-kubernetes.yaml
5. Mesos vs. Kubernetes
5.Mesos vs Kubernetes
Now, we’ve gone through enough context and also performed basic deployment on both Marathon and Kubernetes. We can attempt to understand where do they stand compared to each other.
现在,我们已经经历了足够的背景,也在马拉松和Kubernetes上进行了基本部署。我们可以尝试了解它们彼此之间的关系。
Just a caveat though, it’s not entirely fair to compare Kubernetes with Mesos directly. Most of the container orchestration features that we seek are provided by one of the Mesos frameworks like Marathon. Hence, to keep things in the right perspective, we’ll attempt to compare Kubernetes with Marathon and not directly Mesos.
不过需要注意的是,直接将Kubernetes与Mesos进行比较并不完全公平。我们所寻求的大多数容器编排功能都是由Mesos框架之一提供的,如Marathon。因此,为了保持正确的视角,我们将尝试将Kubernetes与Marathon进行比较,而不是直接与Mesos进行比较。
We’ll compare these orchestration systems based on some of the desired properties of such a system.
我们将根据这种系统的一些理想属性来比较这些协调系统。
5.1. Supported Workloads
5.1.支持的工作负载
Mesos is designed to handle diverse types of workloads which can be containerized or even non-containerised. It depends upon the framework we use. As we’ve seen, it’s quite easy to support containerized workloads in Mesos using a framework like Marathon.
Mesos旨在处理不同类型的工作负载,可以是容器化的,甚至是非容器化的。这取决于我们使用的框架。正如我们所看到的,使用Marathon这样的框架在Mesos中支持容器化工作负载是非常容易的。
Kubernetes, on the other hand, works exclusively with the containerized workload. Most widely, we use it with Docker containers, but it has support for other container runtimes like Rkt. In the future, Kubernetes may support more types of workloads.
另一方面,Kubernetes专门针对容器化工作负载工作。最广泛的是,我们将它与Docker容器一起使用,但它也支持其他容器运行机制,如Rkt。在未来,Kubernetes可能会支持更多类型的工作负载。
5.2. Support for Scalability
5.2.对可扩展性的支持
Marathon supports scaling through the application definition or the user interface. Autoscaling is also supported in Marathon. We can also scale Application Groups which automatically scales all the dependencies.
马拉松支持通过应用程序定义或用户界面进行扩展。马拉松也支持自动缩放。我们还可以扩展应用程序组,它可以自动扩展所有的依赖关系。
As we saw earlier, Pod is the fundamental unit of execution in Kubernetes. Pods can be scaled when managed by Deployment, this is the reason pods are invariably defined as a deployment. The scaling can be manual or automated.
正如我们之前看到的,Pod是Kubernetes的基本执行单位。Pod在由部署管理时可以进行扩展,这就是Pod无一例外地被定义为部署的原因。缩放可以是手动或自动的。
5.3. Handling High Availability
5.3.处理高可用性
Application instances in Marathon are distributed across Mesos agents providing high availability. Typically a Mesos cluster consists of multiple agents. Additionally, ZooKeeper provides high availability to the Mesos cluster through quorum and leader election.
Marathon中的应用实例是分布在Mesos代理中,提供高可用性。通常,一个Mesos集群由多个代理组成。此外,ZooKeeper通过法定人数和领导者选举为Mesos集群提供高可用性。
Similarly, pods in Kubernetes are replicated across multiple nodes providing high availability. Typically a Kubernetes cluster consists of multiple worker nodes. Moreover, the cluster can also have multiple masters. Hence, Kubernetes cluster is capable of providing high availability to containers.
同样,Kubernetes中的pod是在多个节点上复制的,提供高可用性。通常,一个Kubernetes集群由多个工作节点组成。此外,该集群也可以有多个主控器。因此,Kubernetes集群能够为容器提供高可用性。
5.4. Service Discovery and Load Balancing
5.4.服务发现和负载平衡
Mesos-DNS can provide service discovery and a basic load balancing for applications. Mesos-DNS generates an SRV record for each Mesos task and translates them to the IP address and port of the machine running the task. For Marathon applications, we can also use Marathon-lb to provide port-based discovery using HAProxy.
Mesos-DNS可以为应用程序提供服务发现和基本的负载平衡。Mesos-DNS为每个Mesos任务生成一个SRV记录,并将它们翻译成运行该任务的机器的IP地址和端口。对于马拉松应用,我们也可以使用Marathon-lb来提供基于端口的发现,使用HAProxy。
Deployment in Kubernetes creates and destroys pods dynamically. Hence, we generally expose pods in Kubernetes through Service, which provides service discovery. Service in Kubernetes acts as a dispatcher to the pods and hence provide load balancing as well.
Kubernetes中的部署会动态地创建和销毁pod。因此,我们通常通过Service在Kubernetes中暴露pod,它提供服务发现。 Kubernetes中的服务作为pod的调度器,因此也提供了负载平衡。
5.5. Performing Upgrades and Rollback
5.5.执行升级和回滚
Changes to application definitions in Marathon is handled as deployment. Deployment supports start, stop, upgrade, or scale of applications. Marathon also supports rolling starts to deploy newer versions of the applications. However, rolling back is as straight forward and typically requires the deployment of an updated definition.
对马拉松中的应用定义的改变是作为部署来处理的。部署支持应用程序的启动、停止、升级或扩展。马拉松还支持滚动启动以部署较新版本的应用程序。然而,回滚是直接的,通常需要部署一个更新的定义。
Deployment in Kubernetes supports upgrade as well as rollback. We can provide the strategy for Deployment to be taken while relacing old pods with new ones. Typical strategies are Recreate or Rolling Update. Deployment’s rollout history is maintained by default in Kubernetes, which makes it trivial to roll back to a previous revision.
Kubernetes中的部署支持升级和回滚。我们可以为部署提供策略,以便在用新荚替换旧荚时采取。典型的策略是重新创建或滚动更新。在Kubernetes中,部署的推出历史被默认维护,这使得回滚到之前的修订版非常简单。
5.6. Logging and Monitoring
5.6.记录和监测
Mesos has a diagnostic utility which scans all the cluster components and makes available data related to health and other metrics. The data can be queried and aggregated through available APIs. Much of this data we can collect using an external tool like Prometheus.
Mesos有一个诊断工具,它扫描所有的集群组件,并提供与健康和其他指标有关的可用数据。这些数据可以通过可用的API进行查询和汇总。这些数据中的大部分我们可以使用像Prometheus这样的外部工具来收集。
Kubernetes publish detailed information related to different objects as resource metrics or full metrics pipelines. Typical practice is to deploy an external tool like ELK or Prometheus+Grafana on the Kubernetes cluster. Such tools can ingest cluster metrics and present them in a much user-friendly way.
Kubernetes 发布与不同对象相关的详细信息作为资源度量或完整的度量管道。典型的做法是在Kubernetes集群上部署一个外部工具,如ELK或Prometheus+Grafana。这类工具可以摄取集群指标,并以更友好的方式呈现。
5.7. Storage
5.7 储存
Mesos has persistent local volumes for stateful applications. We can only create persistent volumes from the reserved resources. It can also support external storage with some limitations. Mesos has experimental support for Container Storage Interface (CSI), a common set of APIs between storage vendors and container orchestration platform.
Mesos为有状态的应用程序提供了持久的本地卷。我们只能从保留的资源中创建持久的卷。它还可以支持有一些限制的外部存储。Mesos具有对容器存储接口(CSI)的实验性支持,这是存储供应商和容器编排平台之间的一套通用API。
Kubernetes offers multiple types of persistent volume for stateful containers. This includes storage like iSCSI, NFS. Moreover, it supports external storage like AWS, GCP as well. The Volume object in Kubernetes supports this concept and comes in a variety of types, including CSI.
Kubernetes为有状态容器提供了多种类型的持久化卷。这包括iSCSI、NFS等存储。此外,它也支持AWS、GCP等外部存储。Kubernetes中的卷对象支持这一概念,有多种类型,包括CSI。
5.8. Networking
5.8.联网
Container runtime in Mesos offers two types of networking support, IP-per-container, and network-port-mapping. Mesos defines a common interface to specify and retrieve networking information for a container. Marathon applications can define a network in host mode or bridge mode.
Mesos中的容器运行时间提供了两种类型的网络支持,IP-per-container和网络端口映射。Mesos定义了一个通用接口,用于指定和检索容器的网络信息。马拉松应用程序可以在主机模式或桥接模式下定义网络。
Networking in Kubernetes assigns a unique IP to each pod. This negates the need to map container ports to the host port. It further defines how these pods can talk to each other across nodes. This is implemented in Kubernetes by Network Plugins like Cilium, Contiv.
Kubernetes中的网络为每个pod分配一个唯一的IP。这就否定了将容器端口映射到主机端口的必要性。它进一步定义了这些pod如何在节点间相互对话。这在Kubernetes中是由Cilium、Contiv等网络插件实现的。
6. When to Use What?
6.什么时候使用什么?
Finally, in comparison, we usually expect a clear verdict! However, it’s not entirely fair to declare one technology better than another, regardless. As we’ve seen, both Kubernetes and Mesos are powerful systems and offers quite competing features.
最后,在比较中,我们通常期望有一个明确的判决!然而,无论如何,宣布一种技术比另一种技术好,并不完全公平。正如我们所看到的,Kubernetes和Mesos都是强大的系统,并提供了相当有竞争力的功能。
Performance, however, is quite a crucial aspect. A Kubernetes cluster can scale to 5000-nodes while Marathon on Mesos cluster is known to support up to 10,000 agents. In most practical cases, we’ll not be dealing with such large clusters.
然而,性能是一个相当关键的方面。一个Kubernetes集群可以扩展到5000个节点,而Mesos集群上的马拉松则可以支持多达10000个代理。在大多数实际情况下,我们不会处理这么大的集群。
Finally, it boils down to the flexibility and types of workloads that we’ve. If we’re starting afresh and we only plan to use containerized workloads, Kubernetes can offer a quicker solution. However, if we’ve existing workloads, which are a mix of containers and non-containers, Mesos with Marathon can be a better choice.
最后,它归结为我们的灵活性和工作负载的类型。如果我们重新开始,并且我们只计划使用容器化的工作负载,Kubernetes可以提供一个更快速的解决方案。然而,如果我们现有的工作负载是容器和非容器的混合体,那么带有马拉松的Mesos可能是一个更好的选择。
7. Other Alternatives
7.其他替代品
Kubernetes and Apache Mesos are quite powerful, but they are not the only systems in this space. There are quite several promising alternatives available to us. While we’ll not go into their details, let’s quickly list a few of them:
Kubernetes和Apache Mesos相当强大,但它们并不是这个领域的唯一系统。有相当多的有前途的替代方案可供我们选择。虽然我们不会去研究它们的细节,但让我们快速列出其中的几个。
- Docker Swarm: Docker Swarm is an open-source clustering and scheduling tool for Docker containers. It comes with a command-line utility to manage a cluster of Docker hosts. It’s restricted to Docker containers, unlike Kubernetes and Mesos.
- Nomad: Nomad is a flexible workload orchestrator from HashiCorp to manage any containerized or non-containerised application. Nomad enables declarative infrastructure-as-code for deploying applications like Docker container.
- OpenShift: OpenShift is a container platform from Red Hat, orchestrated and managed by Kubernetes underneath. OpenShift offers many features on top of what Kubernetes provide like integrated image registry, a source-to-image build, a native networking solution, to name a few.
8. Conclusion
8.结语
To sum up, in this tutorial, we discussed containers and container orchestration systems. We briefly went through two of the most widely used container orchestration systems, Kubernetes and Apache Mesos. We also compared these system based on several features. Finally, we saw some of the other alternatives in this space.
总而言之,在本教程中,我们讨论了容器和容器编排系统。我们简要介绍了两个使用最广泛的容器编排系统,即Kubernetes和Apache Mesos。我们还根据几个特点对这些系统进行了比较。最后,我们看到了这个领域中的一些其他替代方案。
Before closing, we must understand that the purpose of such a comparison is to provide data and facts. This is in no way to declare one better than others, and that normally depends on the use-case. So, we must apply the context of our problem in determining the best solution for us.
在结束之前,我们必须明白,这种比较的目的是提供数据和事实。这绝不是要宣布一个比另一个更好,这通常取决于使用情况。因此,我们必须应用我们问题的背景来确定对我们来说最好的解决方案。