API架构的选择,RESTful、GraphQL还是gRPC

hi,我是熵减,见字如面。

image

在现代的软件工程中,微服务或在客户端与服务端之间的信息传递的方式,比较常见的有三种架构设计的风格:RESTful、GraphQL和gRPC。

每一种模式,都有其特点和合适的使用场景,今天,我们主要来对三种风格做一个深入的理解和对比,以方便我们在做技术选型时,能够做出有效的决策。

RESTful

什么是RESTful?

RESTful是一种软件架构风格和设计模式,它是一种轻量级的Web服务实现模式。

REST(Representational State Transfer)代表着“表现层状态转移”,它强调使用HTTP协议的GET、POST、PUT、DELETE等动词来实现资源的增、删、改、查操作。

image

RESTful是一种基于资源的设计理念,强调在分布式系统中以统一的接口来访问和操作资源。

RESTful架构风格的特点:是客户端和服务器之间的通信采用无状态协议,每个请求包含足够的信息,使得服务器不需要保留客户端的任何上下文信息,从而可以实现高度的可伸缩性和可靠性。

REST风格的API设计通常具有简单、轻量级、易于缓存和扩展等特点。

RESTful架构的原则

Restful架构风格遵循以下几个原则:

  • 资源(Resource):将应用程序的功能和数据抽象为资源,每个资源都有一个唯一的标识符(URL)来访问和操作。

  • 统一接口(Uniform Interface):使用统一的接口来对资源进行操作,包括标准的HTTP方法(GET、POST、PUT、DELETE等)和状态码(如200、404、500等)。

  • 无状态(Stateless):客户端请求中应包含足够的信息,服务端不保存客户端的状态信息,每个请求都是独立的,这样可以实现可伸缩性和可靠性。

  • 按需响应(Cacheable):服务端可以通过设置响应头中的缓存策略,使得客户端可以缓存响应,减少对服务端的请求,提高性能和效率。

  • 分层系统(Layered System):客户端与服务端之间可以存在多个中间层(如代理服务器、负载均衡器等),以实现更高级别的可扩展性和安全性。

通过遵循RESTful的原则,可以实现简单、可扩展、易于理解和集成的API设计,促进不同系统之间的互操作性,并支持跨平台和跨语言的通信。

image

在现实中,RESTful API已成为构建Web服务和分布式系统的非常常见的实践。

RESTful的适用场景

RESTful架构风格,适用于各种不同的场景和应用程序类型。

以下是一些RESTful的经典适用场景:

  • Web应用程序开发:RESTful非常适合构建Web应用程序,通过使用HTTP协议的标准方法和状态码来操作资源,实现前后端分离、松耦合的架构。

  • 移动应用程序开发:RESTful API提供了移动应用程序与后端服务器进行通信的标准化接口,使得移动应用能够方便地获取和操作数据。

  • 云服务和微服务架构:RESTful API是构建云服务和微服务架构的常见方式,不同的服务通过RESTful接口进行通信和协作。

  • 物联网(IoT)应用程序:RESTful API可以用于物联网设备之间的通信和控制,使得设备能够通过HTTP请求与云平台进行交互。

  • 开放数据接口(Open API):RESTful API可以提供开放的数据接口,供第三方开发者进行集成和构建应用程序。

总的来说,RESTful架构风格非常通用且适用于各种不同的应用场景,特别是在需要构建分布式系统、提供开放接口和实现松耦合架构的应用程序中表现出色。

RESTful的优点

RESTful架构,具有以下优点:

  • 简单性:Restful架构使用基于HTTP的标准方法和状态码,易于理解和学习。它采用了简洁的URL和资源的概念,使得API的设计和使用变得简单明了。

  • 可伸缩性:Restful架构的无状态特性使得服务端可以水平扩展,每个请求都是独立的,不依赖于特定的服务器状态,从而提高系统的可伸缩性和性能。

  • 可移植性:Restful API是基于标准的HTTP协议和数据格式(如JSON、XML),可以被不同的平台和编程语言轻松支持,促进了跨平台和跨语言的互操作性。

  • 可见性:Restful API使用明确的URL来表示资源和操作,使得API的结构和功能对开发者和用户来说更加可见和可理解,降低了学习和使用的难度。

  • 缓存支持:Restful API支持HTTP的缓存机制,可以使用缓存来减少对服务器的请求,提高性能和效率。

  • 独立性:Restful架构支持前后端分离,使得前端可以独立演化和开发,后端服务可以以独立的方式进行部署和维护。

RESTful的缺点

然而,RESTful架构也有一些缺点:

  • 语义限制:RESTful架构对资源的操作只使用了HTTP的标准方法(GET、POST、PUT、DELETE等),有时可能无法满足某些复杂的操作需求,需要通过扩展HTTP方法或引入自定义操作。

  • 高耦合性:RESTful架构中,客户端需要对服务端的资源结构有一定的了解,资源的结构和URI的设计需要提前约定好,这会带来一定的耦合性。

  • 安全性:RESTful架构对于安全性的支持相对较弱,需要额外的安全措施(如HTTPS、身份验证、授权等)来保护API的安全性。

  • 性能问题:当资源的层级结构较深、关联关系复杂时,可能需要进行多次请求来获取完整的数据,增加了网络开销和响应时间。

综上所述,Restful架构具有简单性、可伸缩性和可移植性等优点,但在语义限制、高耦合性和安全性方面存在一些限制和挑战。在设计和选择API架构时,需要根据具体的应用需求权衡各种因素。

GraphQL

什么是GraphQL?

GraphQL是一种用于API的查询语言和运行时环境。它于2015年由Facebook开发并开源,并在业界逐渐得到广泛应用。

GraphQL的主要目标是提供一种灵活、高效和强大的方式来获取客户端所需的数据。

image

与传统的RESTful API不同,GraphQL允许客户端通过发送一个包含所需数据结构的查询来精确获取数据,而不需要多次请求不同的端点。

GraphQL的核心是一个查询语言,通过该语言可以精细地描述需要获取哪些数据以及数据之间的关系。客户端通过GraphQL查询语句向服务端发送请求,服务端根据查询语句返回数据。GraphQL的查询语句可以嵌套、组合和重用,从而实现了更加灵活和高效的数据获取。

image

GraphQL的原则

GraphQL架构风格的原则,主要包括以下几点:

  • 单一入口(Single Entry Point):GraphQL的核心思想是通过一个单一的入口点来获取数据。客户端可以使用一个GraphQL查询来获取所需的所有数据,而不需要多次请求。这样可以减少网络往返次数,提高效率。

  • 客户端驱动(Client-Driven):GraphQL采用客户端驱动的数据查询方式,客户端可以灵活地指定需要的数据字段和关联关系,从而避免了传统RESTful接口中的过度获取或不足获取的问题。客户端决定需要的数据,服务器只提供相应的数据。

  • 强类型(Strongly Typed):GraphQL使用强类型系统来定义数据模型和查询。通过定义明确的类型和字段,可以在编译时进行类型检查,减少运行时错误。这有助于提高开发效率和代码质量。

  • 可组合性(Composability):GraphQL具有高度的可组合性,可以通过组合现有的类型和字段来构建复杂的查询和数据模型。这种组合性使得GraphQL非常灵活,可以满足各种不同的数据需求。

  • 实时更新(Real-Time Updates):GraphQL支持实时数据更新和订阅功能,允许客户端订阅数据的变化并接收实时更新。这使得实时应用程序开发更加简单和高效。

  • 自文档化(Self-Documenting):GraphQL的查询语言具有自我描述性,即查询本身就包含了数据模型的描述信息。这使得客户端可以直接查询可用的数据字段和关联关系,减少了对文档的依赖。

  • 批量操作(Batching):GraphQL支持批量操作,可以将多个相关的请求合并为一个请求发送到服务器。这样可以减少网络往返次数,提高效率。

  • 数据加载(Data Fetching):GraphQL支持通过数据加载器(Data Loader)来优化数据的获取和处理。数据加载器可以对数据进行批量加载和缓存,提高数据获取的效率和性能。

以上这些原则,有助于设计和构建具有高度灵活性、可组合性和效率的GraphQL架构。通过遵循这些原则,可以实现更好的数据查询和交互体验,同时提高开发效率和代码质量。

GraphQL的适用场景

GraphQL适用于各种场景和应用程序,特别适用于以下几类经典场景:

  • 多平台应用程序:当应用程序需要为多个平台(例如Web、移动和IoT设备)提供数据服务时,GraphQL非常有用。通过GraphQL,客户端可以精确地获取它们需要的数据,而不需要多个API端点和不必要的数据传输。

  • 复杂的数据需求:对于需要获取和展示复杂数据结构的应用程序,GraphQL是一个理想的选择。它允许客户端根据其需要来精确定义所需的数据字段和关联关系,减少了数据冗余和不必要的查询。

  • 快速迭代和前后端解耦:GraphQL适用于快速迭代和开发过程中的前后端解耦。前端开发人员可以根据需要灵活地获取数据,而无需等待后端开发人员提供新的API端点或数据结构的更改。

  • 微服务架构:对于采用微服务架构的应用程序,每个微服务通常有其专门的数据需求。GraphQL可以作为一个统一的数据层,聚合来自多个微服务的数据,并将其以一种一致的方式暴露给客户端。

  • 实时数据需求:如果应用程序需要实时数据推送和订阅功能,例如聊天应用程序或实时监控系统,GraphQL提供了订阅查询的机制,可以实现实时数据的推送和更新。

  • 个性化数据需求:对于需要根据用户个性化需求提供定制数据的应用程序,GraphQL是一个理想的选择。客户端可以根据用户的偏好和需求定义查询,获取个性化的数据结果。

总之,GraphQL适用于各种不同类型的应用程序和场景,特别适合那些需要灵活、精确和高效获取数据的场景。它提供了强大的查询语言和灵活的数据查询能力,使得客户端能够更好地控制所需的数据,从而提供更好的用户体验和性能。

GraphQL的优点

GraphQL架构,其具有以下优点:

  • 灵活性和精确性:GraphQL允许客户端精确地指定需要的数据字段,避免了传统RESTful API中的过度获取和传输不必要的数据。这种灵活性使得客户端能够更好地控制所需的数据,减少了网络传输和数据冗余。

  • 单一端点:与RESTful API相比,GraphQL只需要一个端点,客户端可以发送复杂的查询请求,并获得所需的数据结果。这样简化了API的维护和管理,减少了网络请求的次数。

  • 强大的类型系统:GraphQL拥有丰富的类型系统,可以定义自定义类型、接口和枚举等。这使得客户端和服务端之间的数据交互更加明确和可靠,减少了因数据格式不匹配而引发的错误。

  • 关联和嵌套查询:GraphQL支持在一个查询中指定多个资源之间的关联关系,并支持嵌套查询。这样可以一次性获取多个相关资源,减少了多次请求的需求,提高了数据获取的效率。

  • 缓存控制:GraphQL具有内置的缓存控制机制,允许客户端在查询中指定所需数据的缓存策略。这可以提高数据访问的性能和效率,并减少对服务器的请求。

  • 实时数据推送:GraphQL支持实时数据推送和订阅功能,客户端可以通过订阅查询来获取实时数据更新。这对于需要实时通知和推送的应用程序非常有用,如聊天应用程序或实时监控系统。

GraphQL的缺点

尽管GraphQL架构具有许多优点,但也存在一些缺点:

  • 学习曲线高:相对于传统的RESTful API,GraphQL具有更复杂的概念和语法。因此,学习和理解GraphQL的概念和工作原理需要一定的时间和精力。

  • 过度获取数据:由于GraphQL的灵活性,客户端可能会过度获取数据,导致查询结果过于庞大,增加了网络传输和数据处理的负担。

  • 缺乏标准化:与RESTful API相比,GraphQL缺乏一致的标准化规范。这导致不同的实现之间可能存在差异,开发人员需要根据具体的实现来进行学习和开发。

  • 缓存管理复杂:由于GraphQL的灵活性和精确性,缓存管理变得更为复杂。开发人员需要考虑缓存数据的一致性和更新策略,以确保数据的准确性和实时性。

  • 安全性考虑:由于GraphQL允许客户端灵活地定义查询,服务端需要特别关注安全性方面的考虑。例如,客户端可能通过查询来获取敏感数据或进行恶意操作。因此,服务端需要实施适当的安全措施,如认证、授权和输入验证,以保护数据和系统的安全。

  • 性能问题:尽管GraphQL可以减少网络请求的次数,但对于复杂的查询和大规模数据集,GraphQL可能面临性能问题。查询的复杂性和数据加载的成本可能导致响应时间的延迟。因此,开发人员需要仔细考虑和优化GraphQL的查询性能。

  • 缺无状态特性:与RESTful API相比,GraphQL没有内置的无状态特性。这意味着服务端需要维护客户端的查询状态,以便正确处理查询和返回一致的结果。这可能增加服务端的复杂性和开发的复杂性。

gRPC

什么是gRPC

gRPC是一种高性能、开源和通用的远程过程调用(RPC)框架,由Google开发。

gRPC支持多种编程语言和平台,并使用Protocol Buffers作为默认的消息编码协议,可以在不同的应用程序之间实现高效的通信。

image

gRPC框架基于HTTP/2协议,它支持全双工的流式传输、多路复用、头部压缩等特性,可以提供更高效的网络性能和更好的扩展性。同时,gRPC也支持多种负载均衡算法、认证和授权机制,可以保障通信的安全性和可靠性。

gRPC可以简化应用程序之间的通信过程,开发者只需要定义一份IDL(接口定义语言)文件,然后使用gRPC框架自动生成客户端和服务端的代码。

另外,gRPC默认使用Protocol Buffers作为消息编码协议,所以通信数据的大小比传统的文本协议(例如JSON)更小,可以提高网络性能。

gRPC的应用场景

gRPC具有广泛的应用场景,常见的使用场景包括:

  • 微服务架构:gRPC适用于构建微服务架构中的服务间通信。由于其高效的序列化和跨语言支持,可以实现不同微服务之间的快速、可靠的通信。

  • 分布式系统:gRPC可以在分布式系统中作为通信框架使用,用于不同节点之间的数据传输和远程调用。它提供了高效的远程过程调用机制,适用于大规模分布式系统的通信需求。

  • API后端服务:gRPC可以用作构建API后端服务的通信协议。它提供了强类型和接口定义语言,使得客户端和服务器之间可以共享和交流接口定义,方便开发和维护。

  • 实时流式数据传输:gRPC支持双向流式通信,适用于需要实时传输和处理流式数据的场景。例如,实时聊天应用、实时数据分析和实时监控系统等。

  • 高性能计算:由于gRPC使用了高效的序列化和传输协议,可以在需要进行高性能计算的场景中使用。例如,分布式计算、机器学习模型的训练和推理等。

  • IoT(物联网)应用:gRPC可以在物联网应用中作为设备和后端服务器之间的通信协议。它的轻量级和高效性能使得它适用于连接大量设备的场景。

gRPC适用于许多不同的应用场景,特别是在分布式系统、微服务架构和实时通信方面具有显著的优势。它提供了高效、可靠和灵活的通信机制,使得开发人员可以更轻松地构建复杂的分布式应用程序。

gRPC的优点

gRPC架构的关键特点,主要包括以下几点:

  • 高效的远程过程调用(RPC):gRPC使用高效的远程过程调用协议,基于Protocol Buffers(protobuf)进行数据序列化和通信。通过使用二进制协议和高性能的序列化机制,gRPC可以实现快速、高效的跨网络通信。

  • 强类型和接口定义语言(IDL):gRPC使用接口定义语言(IDL)来定义服务接口和消息格式。IDL提供了一种规范和标准,可以在客户端和服务器之间共享和交流。通过IDL,可以明确地定义服务接口和消息类型,提高跨平台和多语言的互操作性。

  • 支持多种传输协议:gRPC支持多种传输协议,包括基于HTTP/2的传输和传统的TCP传输。HTTP/2作为底层协议,提供了多路复用、流控制和头部压缩等优点,可以提高性能和效率。

  • 支持多种编程语言:gRPC支持多种编程语言,包括Java、C++、Python、Go等,可以满足不同语言和技术栈的需求。这使得开发人员可以使用自己熟悉的编程语言来实现和使用gRPC服务。

  • 双向流式通信(Bidirectional Streaming):gRPC支持双向流式通信,即客户端和服务器可以同时发送和接收数据流。这使得实时的流式数据传输和通信成为可能,例如聊天应用、实时监控等场景。

  • 拦截器和中间件(Interceptors and Middleware):gRPC提供拦截器和中间件的机制,可以在请求和响应的处理过程中插入自定义的逻辑。这样可以实现日志记录、认证授权、错误处理等通用的功能,提高代码复用性和可维护性。

  • 可扩展性和服务发现:gRPC支持服务发现和负载均衡机制,可以根据需要动态地扩展服务。通过使用服务发现机制,可以自动发现和管理可用的服务实例,以实现高可用性和负载均衡。

  • 自动生成的客户端和服务器代码:使用gRPC的IDL和相关工具,可以自动生成客户端和服务器的代码。这样可以简化开发过程,减少手动编写重复性代码的工作量。

这些原则使得gRPC成为一个强大、高效和灵活的RPC框架。通过遵循这些原则,可以实现快速、可靠的跨网络通信,并提供丰富的功能和特性,满足不同应用场景的需求。

gRPC的缺点

尽管gRPC具有许多优点,但也存在一些缺点:

  • 学习曲线较陡:相对于传统的RESTful API和其他通信协议,gRPC具有一定的学习曲线。使用gRPC需要了解Protobuf和IDL的概念,并学习如何定义服务接口和消息类型。这可能对于新手或非熟悉这些概念的开发人员来说,需要一定的时间和学习成本。

  • 不适用于所有场景:尽管gRPC在许多场景下表现优异,但并不是适用于所有应用场景。例如,如果你的应用程序需要对公共网络进行通信,而网络环境受到限制(如防火墙),则可能需要配置特殊的设置来支持gRPC的通信。

  • 难以调试和跟踪:由于gRPC使用二进制协议和高效的序列化机制,数据在传输过程中进行了编码和压缩,使得调试和跟踪变得更加困难。在排查问题时,可能需要额外的工具和技术来解析和查看数据。

  • 不适用于所有语言和平台:尽管gRPC支持多种编程语言和平台,但并不是所有语言和平台都得到了广泛的支持。某些语言和平台的gRPC实现可能不如其他语言和平台成熟和稳定。

  • 依赖于网络和服务发现:gRPC是基于网络的通信协议,因此在使用gRPC时需要稳定的网络连接。此外,使用gRPC时需要合适的服务发现机制来管理和调度服务实例,这可能需要额外的配置和维护。

总的来说,尽管gRPC具有许多优点,但在选择使用它时也需要考虑到其可能存在的一些限制和挑战。根据具体的应用需求和技术环境,需要综合评估是否适合采用gRPC作为通信协议。

三者之间的比较

诸如以上内容所述,现在对这三种API的架构设计和实现方式,都有了一个深入的理解,对他们的特性,优点和缺点也有初步的了解。

image

下面,是对三个实现方案的一些关键特性的一个综合对比如下:

image

最后

RESTful、GraphQL和gRPC是三种常见的API架构设计和实现模式,它们在设计理念、数据传输方式和使用场景上都存在这一定的差异:

  • RESTful是基于HTTP协议的传统API架构,使用简单、易于理解,适用于传统的API开发和数据交互场景。

  • GraphQL是一种灵活的数据查询语言和API查询协议,客户端可以灵活地指定需要的数据,并避免了"过度获取"的问题,适用于需要动态数据获取和灵活数据查询的场景。

  • gRPC是一种高性能的跨语言的远程过程调用协议,使用基于二进制的通信协议和强类型接口定义,适用于分布式系统、微服务架构和实时通信等场景。

我们在做API实现方案的选型时,要结合具体的应用需求、开发团队的技术能力和技术栈,以及可扩展性等实际需求,来选择适合的方案。要记住的至关重要的一点是:最新的、最流行的不一定是最好的选择。

另外,无论选择哪种架构和协议,重要的是理解其特点、原则和使用方式,并根据具体情况进行合理的设计和优化,以提供高效、可扩展和可靠的API服务。

关注 熵减黑客 ,一起学习成长


熵减黑客
本文转载于网络 如有侵权请联系删除

相关文章

  • 信念网络中信念影响的测量

    有影响力的信仰对于我们理解人们如何思考政治问题和做出政治决策至关重要。本研究基于心理测量网络方法和网络影响研究的进展,提出了一种在更大的信仰系统网络背景下测量政治信仰影响的新方法。利用最新一轮的欧洲社会调查数据,我们在一个信仰网络上展示了这一方法,该网络表达了29个欧洲国家对政权的支持,并捕获了与支持政权表现、原则、制度和政治行为者相关的信仰。我们的研究结果表明,信念的平均影响可能与信念网络的一致性和连通性有关,特定信念(如民主满意度)对国家层面的影响与来自同一领域的外部指标(如自由民主指数)显著负相关,这表明极具影响力的信仰与紧迫的政治问题有关。这些发现表明,根据大规模调查数据估计的基于网络的信念影响指标可以作为比较政治研究的一种新型指标,为将心理测量网络分析方法整合到政治学方法中开辟了新的途径。原文题目:MEASURINGTHEINFLUENCEOFBELIEFSINBELIEFNETWORKS原文:Influentialbeliefsarecrucialforourunderstandingofhowpeoplereasonaboutpoliticalissuesandmakep

  • 数据挖掘提分三板斧!

    内容概括 数据挖掘提分三板斧: 1.金斧-数据清洗和特征工程2.银斧-模型参数调节3.铜斧-模型集成PPT下载:后台回复“210406”可获取视频地址:https://www.bilibili.com/video/BV1MU4y1h75G数据清洗和特征工程一、关于数据清洗1.缺失值处理: 2.异常值处理:数据清洗-数据分桶3.数据分桶: 4.数据标准化:在不同的问题中,标准化的意义不同(1)在回归预测中,标准化是为了让特征值有均等的权重;(2)在训练神经网络的过程中,通过将数据标准化,能够加速权重参数的收敛;(3)主成分分析中,需要对数据进行标准化处理;默认指标间权重相等,不考虑指标间差异和相互影响。数据清洗的示例: 二、关于特征工程1.特征构造:2.特征选择:特征工程的示例:模型参数调节 一、关于建模调参1.理解模型 2.性能验证 3.模型调参模型集成一、关于模型集成1.加权融合2.Boosting/Bagging3.Stacking/Blending模型集成示例:本文作者王茂霖,Datawhale重要贡献成员,Datawhale&天池数据挖掘学习赛开源内容发起人,全网阅读超

  • JAVA进阶2 深入理解面向对象

    参考链接:为什么Java不是纯粹的面向对象语言JAVA进阶2深入理解面向对象 一、结构化程序设计与面向对象1.概述2.结构化程序设计简介2.面向对象程序设计 二、类的定义与修饰符1.定义类2.修饰符3.final修饰符2.3.1final成员变量2.3.2final局部变量2.3.3final修饰基本类型变量和引用类型变量的区别2.3.4可执行“宏替换”的final变量2.3.5final方法2.3.6final类2.3.7不可变类(immutable)2.3.8缓存实例的不可变类 三、深入理解java的面向对象1.一切皆对象,包装类2.类成员3.类的结构关系4.面向对象的基本特征3.4.1封装(Encapsulation)3.4.2继承(Inheritance)3.4.3多态(Polymorphism)3.4.4抽象3.4.5其它功能  5.抽象类3.5.1抽象类的特性3.5.2接口3.5.3接口的定义3.5.4接口的继承3.5.5使用接口3.5.6接口和抽象类比较相同点差别  3.5.7面向接口编程  6.内部类3.6.1非静态内部类3.6.2静态内部类3.6.3局部内部类3.6.

  • OpenCV实现图像转换为素描效果

    OpenCV图像转素描我们在一些相机APP的功能里会看到有把照片转换为素描效果的,看起来就很高大上的感觉,今天我们也用OpenCV实现一下这个效果。实现效果先上一张经典的Lena的图片转换为素描效果的图片,左边是原图的效果,右边就是我们通过OpenCV的几行代码实现的一个素描的效果。实现流程微卡智享图像转为素描的流程其实也挺简单的,一共就是四步即可实现。#实现流程1图像去色(转为灰度图)2图像取反3将取反后的图像进行高斯模糊4去色后的图像(灰度图)和取反模糊后的图像以混合模式为颜色减淡进行融合代码实现微卡智享新建一个opencvsrctosumiao的项目,配置参见《VS2017配置OpenCV通用属性》 01图像去色02图像取反实现图像取反可以有三种方式: 遍历像素值直接用255去减 gray_inverse=Scalar(255,255,255)-gray;复制使用subtract函数 subtract(Scalar(255,255,255),gray,gray_inverse);复制通地位运算直接取反gray_inverse=~gray;复制取反后的效果03将取反后的图像进行高斯

  • which命令

    which命令which命令用于标识在终端提示符下键入可执行文件名称或命令时执行的给定可执行文件的位置,该命令在PATH环境变量中列出的目录中搜索作为参数指定的可执行文件。语法which[options]COMMAND复制参数--version,-[vV]:输出版本信息。--help:输出帮助信息。--skip-dot:跳过PATH中以.开头的目录。--skip-tilde:跳过PATH中以~开头的目录。--show-dot:不要在输出中将.扩展到当前目录。--show-tilde:为非root用户输出HOME目录的波浪号。--tty-only:如果不在tty上,则停止处理右侧的选项。--all,-a:打印PATH中的所有匹配项,而不仅仅是第一个。--read-alias,-i:从标准输入中读取别名列表。--skip-alias:忽略选项--read-alias,不要读标准输入。--read-functions:从标准输入读取shell函数。--skip-functions:忽略选项--read-functions,不要读标准输入。示例查看指令bash的绝对路径。whichbash #

  • 图深度学习入门教程(四)——训练模型的原理

    摘要:深度学习还没学完,怎么图深度学习又来了?别怕,这里有份系统教程,可以将0基础的你直接送到图深度学习。还会定期更新哦。本教程是一个系列免费教程,争取每月更新2到4篇。主要是基于图深度学习的入门内容。讲述最基本的基础知识,其中包括深度学习、数学、图神经网络等相关内容。该教程由代码医生工作室出版的全部书籍混编节选而成。偏重完整的知识体系和学习指南。在实践方面不会涉及太多基础内容(实践和经验方面的内容,请参看原书)。文章涉及使用到的框架以PyTorch和TensorFlow为主。默认读者已经掌握Python和TensorFlow基础。如有涉及到PyTorch的部分,会顺带介绍相关的入门使用。本教程主要针对的人群:已经掌握TensorFlow基础应用,并想系统学习的学者。PyTorch学习者。正在从TensorFlow转型到PyTroch的学习者已经掌握Python,并开始学习人工智能的学者。本篇文章主要介绍训练模型的原理。在训练模型中,图神经网络所使用的技术是与深度学习是完全一样的。本篇文章以介绍深度学习中训练模型的原理为主,顺便介绍一下PyTorch基础中与梯度计算相关的接口。1训练模

  • Spring Boot2 系列教程(三十四)Spring Security 添加验证码

    登录添加验证码是一个非常常见的需求,网上也有非常成熟的解决方案,其实,要是自己自定义登录实现这个并不难,但是如果需要在SpringSecurity框架中实现这个功能,还得稍费一点功夫,本文就和小伙伴来分享下在SpringSecurity框架中如何添加验证码。关于SpringSecurity基本配置,这里就不再多说,小伙伴有不懂的可以参考http://springboot.javaboy.org/,本文主要来看如何加入验证码功能。准备验证码要有验证码,首先得先准备好验证码,本文采用Java自画的验证码,代码如下:/** *生成验证码的工具类 */ publicclassVerifyCode{ privateintwidth=100;//生成验证码图片的宽度 privateintheight=50;//生成验证码图片的高度 privateString[]fontNames={"宋体","楷体","隶书","微软雅黑"}; privateColorbgColor=newColor(255,255,255

  • ZetCode 教程翻译计划正式启动 | ApacheCN

    版权声明:本文为博主原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/wizardforcel/article/details/102645443原文:ZetCode 协议:CCBY-NC-SA4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远。 ApacheCN学习资源贡献指南本项目需要校对,欢迎大家提交PullRequest。目录数据库图形GUIJavaJavaScriptKotlin语言PHPPythonServletSpringSpringBootSymfonyVaadinWeb联系方式负责人飞龙:562826179其他在我们的apachecn/zetcode-zhgithub上提issue.发邮件到Email:apachecn@163.com.在我们的组织学习交流群中联系群主/管理员即可.

  • 【IoT迷你赛】TencentOS_tiny 初体验

    简述平时工作太忙,只能周末抽时间体验下,windows程序员一枚,对硬件不是很懂,主要是想分析下TencentOS_tiny的代码,物联网操作系统包括AliosThings,FreeRTOS等,相比较于现代PC上的操作系统,因为没有MMU,所以不存在虚拟内存管理,也没有用户模式和内核模式之分,所有任务都在一个地址空间运行,通过时钟中断来调度不同的任务,再加上实现的物联网协议中间件及接云平台SDK,基本就包括了物联网操作系统的所有东西了。启动流程分析1.cpu复位后首先执行的是startup_stm32l431xx.s里面的Reset_Handler2.Reset_Handler调用main函数3.main函数实现位于BSP/Src/main.c中board_init:主要是外设初始化,包括UART,GPIO,OLED等osKernelInitialize:内核初始化,包括任务队列初始化,堆初始化,创建idle任务,定时器初始化等osThreadCreate:创建一个任务,任务入口为application_entry,也就是example目录下各个demo的入口点osKernelStar

  • CORS跨域

    当一个资源从与该资源本身所在的服务器不同的域或端口请求一个资源时,资源会发起一个跨域HTTP请求。比如,站点http://domain-a.com的某HTML页面通过<img>的src请求http://domain-b.com/image.jpg。网络上的许多页面都会加载来自不同域的CSS样式表,图像和脚本等资源。出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。例如,XMLHttpRequest和FetchAPI遵循同源策略。这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非使用CORS头文件,,其实跨域并非不一定是浏览器限制了发起跨站请求,而也可能是跨站请求可以正常发起,但是返回结果被浏览器拦截了。最好的例子是CSRF跨站攻击原理,请求是发送到了后端服务器无论是否跨域!注意:有些浏览器不允许从HTTPS的域跨域访问HTTP,比如Chrome和Firefox,这些浏览器在请求还未发出的时候就会拦截请求,这是一个特例。跨域资源共享(CORS)机制允许Web应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。浏览器支持在AP

  • PixelAI : 手淘客户端上的实时视觉算法应用

    基于PixelAI上层视频业务可以快速搭建符合自身业务特色的实时交互视觉特效。在LiveVideoStackCon2019上海大会中,淘宝高级算法专家李晓波详细介绍了手淘在实现客户端上基于深度学习的视觉算法应用时如何在资源受限的情况下达到性能与效果之间的平衡。文/李晓波整理/LiveVideoStack大家好,我是李晓波(篱悠),目前在淘宝任职高级算法专家。本次分享将从设计原则与整体架构、基础算法和上层应用三个部分来介绍手淘视频业务在客户端上实时视觉算法领域的探索。1.设计原则与整体架构1.1手淘多媒体算法整体链路手淘多媒体算法分为视频生产和用户消费两部分,上图左半部环更多是由广告和搜索团队进行收集,算法团队主要负责右半部环中视频智能生产、内容感知及内容理解部分,当算法能够解决高级语义理解和结构化信息时,就可以结合左半部环内容结合起来做视频的个性化分发。1.2手淘多媒体算法面临的挑战手淘多媒体算法目前面临业务、技术和业界进展变化(环境)三方面的挑战,应对这些挑战手淘分别在效率、体验和成本三个方面做出控制和改变。1.3手淘客户端上实时视觉算法库1.3.1模型设计与压缩在端上做算法面临计算

  • C++中的万能引用和完美转发

    C++中的万能引用和完美转发阅读这篇博文需要了解C++中的左值(lvalue)和右值(rvalue)的概念,详情参见我的另外一篇博文:C++移动语义及拷贝优化万能引用和完美转发多涉及到模板的使用,如若不是自己写模板,则可不用关心万能引用(UniversalReference)首先,我们来看一个例子:#include<iostream> usingstd::cout; usingstd::endl; template<typenameT> voidfunc(T&param){ cout<<param<<endl; } intmain(){ intnum=2019; func(num); return0; }复制这样例子的编译输出都没有什么问题,但是如果我们修改成下面的调用方式呢?intmain(){ func(2019); return0; }复制则会得到一个大大的编译错误。因为上面的模板函数只能接受左值或者左值引用(左值一般是有名字的变量,可以取到地址的),我们当然可以重载一个接受右值的模板函数,如下也可以达到效果。te

  • 开发|如何用深度学习推荐电影?手把手教你

    简介几乎所有人都喜欢与家人、朋友一起观看电影度过闲暇时光。大家可能都有过这样的体验:本想在接下来的两个小时里看一个电影,却坐在沙发上坐了20分钟不知道看什么,选择困难症又犯了,结果好心情也变得沮丧。所以,我们很需要一个电脑代理,在做挑选电影的时候提供推荐。现在,电影智能推荐系统已经成为日常生活中的一部分。DataScienceCentral曾表示:“虽然硬数据很难获得,但知情人士估计,对亚马逊和Netflix这样的大型电商平台,推荐系统为它们带来高达10%至25%的收入增长”。在这个项目中,我研究了一些针对电影推荐的基本算法,并尝试将深度学习融入到电影推荐系统中。把娱乐与视觉艺术相结合,电影是一个很好的例子。电影海报可以直接、快速地把电影信息传达给观众。DesignMantic表示:“不论上映前后,电影海报都是创造噱头的主要因素。多半的人(目标观众)都根据海报来决定买不买票,看不看电影。”我们甚至可以仅仅根据海报字体,来推测这个电影的情绪。这听起来有点像魔术——但看一眼海报就预测出电影的类型,的确是可能的。就拿我来说,瞟一眼海报就知道我想不想看这个电影了。举个例子,我不是卡通迷,一看到

  • git 命令怎么删除远程分支文件_git删除远程仓库分支

    查看所有分支查看项目的远程分支:gitbranch-r复制删除远程分支比如我们要删除远程分支origin/SLT_table_reportgitpushorigin-d分支名复制我们执行:gitpushorigin-dSLT_table_report复制删除成功注意这里不能写成origin/SLT_table_report,不然会报错:具体请参考【git删除远程分支报错error:unabletodelete‘origin/xxx‘:remoterefdoesnotexist】 版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至举报,一经查实,本站将立刻删除。发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/181406.html原文链接:https://javaforall.cn

  • HCIA VLAN间通信与三层交换

    一、前言 前面我们讲了用路由器实现VLAN间通信,分了单臂路由和多臂路由,路由器的作用其实也就是为了实现跨网段的交互,对于同VLAN的网络,网段不同的设备也还是需要使用路由器来交互其数据。而这个事情的巧合就在于,一般我们将同一个VLAN的子网配置成同一个网段,所以路由器是恰好实现了VLAN间通信,但本质上路由器还是用于子网间(不同网段)的互通。 对于交换机组成的网络,如果路由器只是用于跨VLAN(跨网段)的通信感觉还是有点浪费,所以就有了所谓的三层交换,也就是在交换机内部实现类似路由器的功能,但毕竟还是与真实路由器有一些不一样的地方。 二、三层交换 如下图所示的网络,PC1与PC2,PC3与PC4可以互通,但PC1与PC3是不能通的。原因除了有VLAN的限制,他们本来也就不在一个网段无法通信的。对于PC1来说当其目标IP不在其网段,它只能求助与网关,也就是把数据丢给网关。所以三层交换就是在交换机上开一个网关即可,这个网关可以接收PC1的数据并将其转发给目标网段的网关2,网关2收到数据后再转发给目标IP。这个过程与路由器是一样一样的。       我们可以在

  • Linux Shell 批量重命名的方法

    1、删除所有的.bak后缀:rename's/\.bak$//'*.bak 2、把.jpe文件后缀修改为.jpg:rename's/\.jpe$/\.jpg/'*.jpe 3、把所有文件的文件名改为小写:rename'y/A-Z/a-z/'* 4、将abcd.jpg重命名为abcd_efg.jpg:forvarin*.jpg;domv"$var""${var%.jpg}_efg.jpg";done 其中,此处涉及到shell的字符串匹配操作: 1){variable#pattern} 如果pattern匹配variable的开始部分,从variable的开始处删除字符直到第一个匹配的位置,包括匹配部分,返回剩余部分。 2){variable##pattern}如果pattern匹配variable的开始部分,从variable的开始处删除字符直到最后一个匹配的位置,包括匹配部分,返回剩余部分。 3){variable%pattern} 如果pattern匹配variable的结尾部分,从variable的结尾处删除字符直到第一个匹配的位置,包括匹配部分,返回剩余

  • git 配置 SSH 流程

    https://www.csdn.net/tags/Mtjacg5sMDA4MzQtYmxvZwO0O0OO0O0O.html

  • WPF 札记

    今天在工程中发现了一个非常消耗CPU资源的过程---一个创建Popup并根据绑定的Collection填充ListBox的过程。通过VS的性能诊断,最终确定的耗时过程锁定在了Popup.isOpen=true这一语句上。该句导致了Listbox的创建。然而,VS的诊断无法再继续深入了。这个句子导致用户输入必须等候Popup弹窗完成,造成了十分尴尬的体验。我曾试图通过线程等方式去解决它,效果并不好。最终的解决方法却有些让我意外。在主管的帮助下(我实在太拖拉了。。。),我们去看了这个空间的Datatemplate定义,试图通过简化它来提高效率。然而即使简化到只剩一个TextBox,效率仍旧不高。这个时候,一个无心(或者经验?)的尝试,让我们发现了突破口。我们试图取消不通过绑定,而是使用固定的数据来显示ListBox,并随手替换为TextBlock,耗时直接变为五分之一。接下来又尝试了几次,结果发现,导致效率差别的其实是TextBox和TextBlock两个控件。我们选择控件时,应该尽量使用能满足条件的最简单的。来自为知笔记(Wiz)

  • Ubuntu环境下手动配置ant

    配置ant 1.下载ant(http://ant.apache.org/bindownload.cgi) 例如我下载的是:apache-ant-1.9.4-bin.tar.gz 解压ant,将文件夹名称改为apache_ant,并移动到/home目录下   2.设置环境变量 sudogedit/etc/profile 复制  在打开的profile文件末尾加入: #setant exportANT_HOME=/home/apache_ant exportPATH=/home/apache_ant/bin:$PATH 复制   3.测试 ant 复制  shell中应该会返回以下信息,表示安装成功 Buildfile:build.xmldoesnotexist!Buildfailed 原因:因为ant不带任何参数,会在当前日志下搜索build.xml文件。如果找到了就以该文件作为默认的生成文件,并执行默认的target。   keepmoving...

  • 编程珠玑学习笔记

    编程珠玑学习笔记 1.在整数的存储方面有时候可以采取位图和位向量来表示。例如我们可以将集合{1,2,3,5,8,13}存储在下面的这个字符串中:01110100100001000000.集合中表示数字的各个位设置为1,而其他的位全部设为0.给定了表示文件中整数集合的位图数据结构后,我们可以将编写程序的过程分为3个自然阶段。第一个阶段关闭所有的位,将集合初始化为空集。第二个阶段读取文件中的每个整数,并打开相应的位,建立该集合。第三个阶段检查每个位,如果某个位是1,就写出相应的整数,从而创建已排序的输出文件。这样输出的文件就已排好序。 2.将n个元素旋转i个位置。例如n=8,i=3,那么向量abcdefgh旋转后得到向量defghabc。第一种方法是将x[0]放到临时变量t中,然后将x[i]放x[0],x[2i]放x[i]……abcdefghijklmnopq012345678910111213141516fghijklmnopqcdeab第二种方法是ab要想转为ba则可以把b中前i个字符和a换。变为abrbi->bibramnopqfghijklabcdehijklfgmnopqa

  • QT QUICK和C++结合编程

    QTQUICK和C++结合编程 一、注册C++类为qml可以使用的类型 qtquick优先使用这种方式编程。做qtquick,使用.qml文件编译生成的应用程序。 在qtquick中没有现成可用的qml类型的情况下,需要使用C++自己编写相关的类注册为qml可使用的类型。 注册完成后和qtquick自带的类型没有任何区别,也是qml可扩展性的体现。qtquick官方的类型也都是用C++编写注册的。 QTQUICK的应用程序优先采用这种方式,在设计模式中符合工厂模式和功能单一模式。注册的类型也可以注册为单例类。主体代码界面逻辑都用qml写,没有支持的类型再用C++写,这样类型可扩展,也符合设计模式中的开闭原则。耦合度低便于软件分工 主要流程参考《QtQuick核心编程》一书,本文基本和书里示例一致。 1、定义可以导出的C++类 前提:必须是Q_Object类的派生类,才可以注册到QT的元对象系统。 使用Q_OBJECT宏 classscreenRecorder:publicQObject { Q_OBJECT } 复制 2、一个类的成员函数用Q_INVOKABLE修饰就可以在qml中

相关推荐

推荐阅读