应用架构演变过程、rpc及Dubbo简介

一、应用架构演变历史:

        单一应用架构 -> 垂直应用架构 -> 分布式服务架构 -> 微服务架构。

单一应用架构

        当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。 此时,用于简化增删改查工作量的 数据访问框架(ORM) 是关键。

        缺点:单一的系统架构,使得在开发过程中,占用的资源越来越多,而且随着流量的增加越来越难以维护。

垂直应用架构

        当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,垂直应用架构就出现了,垂直应用架构将应用拆成互不相干的几个应用,解决了单一应用架构所面临的扩容问题,流量能够分散到各个子系统当中,且系统的体积可控,一定程度上降低了开发人员之间协同以及维护的成本,提升了开发效率。

        缺点:但是在垂直架构中相同逻辑代码需要不断的复制,不能复用。

分布式服务架构

soa

        随着业务的发展,垂直应用越来越多,应用之间的交互不可避免,并且这些应用之间的调用和依赖关系也会越来越复杂,为了解决这个问题,同时为了解决多个垂直应用间的代码重复性问题,我们就不得不再次对这些垂直应用做水平拆分了,soa时代也就来临了,soa是面向服务的架构,它允许我们将核心业务和公共功能从多个垂直应用中拆分出来,作为单独的服务进行独立的部署,逐渐形成了稳定的服务中心,使前端应用能更快速的响应多变的市场需求。这个时期也衍生出了一系列服务于soa的技术,如对服务提供、服务调用、连接处理、通信协议、序列化方式、服务发现、服务路由、日志输出等行为进行封装的服务框架。

        从部署的角度来看,soa其实就是分布式服务:将垂直架构中的各个子系统再进行水平拆分,将多个子系统中的共同功能拆分为独立的服务,将这些服务部署在不同的主机上,通过网络通信技术来实现服务之间的调用,并通过服务路由、负载均衡等技术来优化服务间的调用过程,提高整体服务效率。

微服务架构

        微服务是对于分布式服务进行的更小粒度的拆分,因为分布式服务架构中依然有多个具有调用关系的模块存在于同一个应用中,当被调用的模块出现了异常时,这个异常会被传播到调用它的模块中,也就是模块间具有代码级别的强依赖,耦合度太高了,为了解决这个问题,我们对分布式服务进行了更小粒度的拆分,也就是按照模块拆分服务。微服务架构就是将应用按照业务模块拆分成一个一个的微服务,每个微服务运行在独立的进程中,并使用轻量级的机制进行通信,通常是http restful api,这些服务可以使用不同的编程语言来实现,也可以连接不同的数据库,以保证最低限度的集中式管理,微服务也可以进行集群化部署,以提高服务应对高并发的能力。随着微服务架构出现的是微服务框架,一种用于进行服务治理的框架,微服务框架自成生态,提供了用于治理微服务架构各方面的组件,包括服务的自动注册与发现、服务网关路由、负载均衡、服务调用、服务容错、服务链路追踪、配置的动态管理等。常用的微服务框架如Spring Cloud。

二、rpc

        在soa时代出现了用于实现远程过程调用的rpc协议,远程过程调用其实是一种思想,它想要实现的目标为:在分布式系统中,能够像调用本地方法一样调用远程接口,使我们无需进行网络编程,也无需了解网络通信技术,就能通过网络从远程计算机程序上请求服务。

rpc的传输协议

        rpc可以使用http作为传输协议,也可以直接使用tcp协议,使用不同的协议一般也是为了适应不同的场景。那么http协议和tcp协议有什么区别呢?

        http是应用层协议,应用层的任务是通过应用进程间的交互来实现特定的网络应用。http属于应用层协议。http协议工作于C-S架构之上,客户端基于http协议向web服务端发送请求,服务端处理接收到的请求后,向客户端发送响应信息。http协议建立在tcp协议之上,它会基于TCP/IP通信协议来进行数据的传递(HTML 文件, 图片文件, 查询结果等)。

        tcp是传输层协议,传输层的主要任务就是负责为两台主机进程之间的通信提供通用的数据传输服务。tcp是传输层协议,主要解决数据如何在网络中传输。tcp提供的是面向连接的,可靠的数据传输服务。

rpc的实现需要解决的问题

        rpc实现的是远程调用,肯定是需要跨网络而非本机调用,所以需要网络编程才能实现,这就带来了以下几个问题:

        1、网络通讯问题:主要是通过在客户端和服务器之间建立tcp连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。
        rpc在大多数情况下,是应用于一个高并发的调用场景,根据系统内核的支持、编程语言的支持以及IO模型本身的特点,在rpc框架的实现中,在网络通信的处理上,大多数会选择 IO多路复用的方式。

        2、寻址问题:A服务器上的应用需要告诉底层的rpc框架,要请求的B服务器的ip地址及端口号是多少,接口名称是什么,rpc框架只有得到这些信息才能完成调用。

        在本机的函数调用中,函数体是直接通过函数指针来指定的,当函数调用时,编译器会自动调用相应的函数指针。但是在远程调用中,因为是跨服务器的,两个进程的地址空间是完全不一样的。所以,在rpc中,所有的函数都必须有一个自己的Call id,这个Call id在所有的进程中都是唯一确定的,具有全局唯一性。客户端在远程调用时,需要带上这个Call id。同时我们需要在客户端和服务端分别维护一个{ 函数 <-> Call id}的映射表。当客户端需要远程调用的时候,就需要查一下此表,查询出对应的Call id , 将这个Call id带在请求中,服务端在处理请求的时候,也先查询映射表,来确定客户端需要调用的函数是哪个,最终执行相应的函数代码。

        3、序列化和反序列化:网络传输的数据必须是二进制数据,但是调用方的请求的参数都是对象,对象是不能直接在网络中传输的,所以必须把它转换成可传输的二进制数据,这个过程就叫做序列化。服务端也要将收到的二进制数据还原为对象,这个过程叫做反序列化。在rpc调用中,对输入参数对象与返回值对象进行的序列化和反序列化是一个必须的过程。

rpc架构

一个基本的rpc架构应该至少包含以下 4 个组件
        客户端::服务调用方,即服务消费者;
        客户端存根: 存放服务端地址信息,将客户端的请求参数数据打包成网络消息,再通过网络传输发送给服务端;
        服务端存根: 接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理;
        服务端: 服务的真正提供者。

一次具体的rpc调用过程:

        1、服务消费者通过调用本地服务的方式调用需要消费的服务;
        2、客户端存根接收到调用请求后负责将方法Call id、入参等信息序列化,组装成能够进行网络传输的消息体;
        3、客户端存根找到远程的服务地址,并且将消息通过网络发送给服务端;
        4、服务端存根收到消息后进行解码(反序列化操作),并根据解码结果调用本地方法进行相关处理;
        5、服务端方法执行完毕后将处理结果返回给服务端存根;
        6、服务端存根将相应结果序列化,打包成消息并通过网络发送至消费方;
        7、客户端存根接收到消息,并进行解码(反序列化),将反序列化以后的结果返回给客户端。

rpc框架

        除了rpc的基本功能,一个成熟的rpc框架还应该提供其他的用于治理服务的功能,如:服务的自动注册与发现、负载均衡、集群容错机制等等,下面简单介绍一个经典的rpc框架:Dubbo

Dubbo简介

        Dubbo是阿里巴巴开源的一款基于Java的高性能rpc分布式服务框架,致力于提供高性能和透明化的rpc远程服务调用方案,以及soa服务治理方案。

为什么使用dubbo?

        使用Dubbo可以将核心业务抽取出来,作为独立的服务,形成稳定的服务中心,可提高业务复用性,使前端应用能更快速的响应多变的市场需求。并且rpc支持的分布式架构可以承受更大规模的并发流量。

dubbo的核心功能包括三方面

        1、远程通讯:提供基于接口方法的透明化的远程过程调用,包括多协议支持,dubbo内部对多种基于长连接的NIO框架进行了封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
        2、负载均衡与集群容错:提供了对于多种负载均衡策略及集群容错策略的支持。
        3、服务的自动注册与发现:基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使服务方地址透明,并支持服务提供方动态地增加或减少机器。

服务的发布-订阅-调用过程:

        1、服务容器在启动时加载、启动、运行服务提供者。
        2、服务提供者在启动时,向注册中心注册自己提供的服务并对外暴露自己的接口,接口的发布支持多协议。
        3、服务消费者在启动时,向注册中心订阅自己所需的服务。
        4、注册中心返回服务提供者地址列表给消费者,如果服务提供者列表有变更,注册中心将基于长连接推送变更数据给消费者,服务消费者会将服务提供者地址列表保存在本地。
        5、服务消费者,从本地保存的提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,会基于提供者设置的容错策略去调用另外一台服务或者直接返回。
        6、服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

Dubbo的配置说明(以xml配置方式举例)

服务提供者端的dubbo配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd"><!--当前项目在整个分布式架构里面的唯一名称,计算依赖关系的标签--><dubbo:application name="provider" owner="sihai"><dubbo:parameter key="qos.enable" value="true"/><dubbo:parameter key="qos.accept.foreign.ip" value="false"/><dubbo:parameter key="qos.port" value="55555"/></dubbo:application><dubbo:monitor protocol="registry"/><!--dubbo这个服务所要暴露的服务地址所对应的注册中心--><!--<dubbo:registry address="N/A"/>--><dubbo:registry address="zookeeper://localhost:2181" check="false"/><!--当前服务发布所依赖的协议;webservice、Thrift、Hessain、http--><dubbo:protocol name="dubbo" port="20880"/><!--服务发布的配置,需要暴露的服务接口--><dubbo:serviceinterface="com.sihai.dubbo.provider.service.ProviderService"ref="providerService"/><!--Bean bean定义--><bean id="providerService" class="com.sihai.dubbo.provider.service.ProviderServiceImpl"/></beans>

配置说明:

        1、dubbo是基于spring来开发的,使用类似于spring的配置文件进行配置;
        2、节点:dubbo:application配置的是应用在分布式架构中的唯一名称,可以在name属性中配置,另外还可以配置owner字段,表示属于谁。
        3、节点:dubbo:monitor是监控中心配置, 用于配置连接监控中心相关信息,可以不配置,不是必须的参数。
        4、节点:dubbo:registry配置注册中心的信息,比如,这里我们可以配置 zookeeper 作为我们的注册中心。address 是注册中心的地址,dubbo支持使用zk集群作为注册中心,当注册中心是zk集群时,要配置dubbo:registry节点的protocol属性的值为zookeeper,address属性的值为多个节点的地址,多个地址用英文逗号隔开。
        5、节点:dubbo:protocol用于定义协议,dubbo可以依赖这些协议进行服务的发布,同一个接口也可以使用多个协议进行发布,在dubbo:service节点中可以用protocol属性指向dubbo:protocol节点定义的某个协议,dubbo:protocol可配置的协议类型有dubbo、http、webservice。
        6、节点:dubbo:service这个节点就是我们的重点了,我们就是通过这个配置将服务提供者的服务发布出去的。interface 是接口的包路径,ref指向第 ⑦ 点配置的接口的 bean。
        7、最后,我们需要像配置spring的接口一样,配置接口的bean,也就是所发布服务的具体实现。

服务的接口的发布

        服务的可以通过启动spring容器将接口发布出去:

package com.sihai.dubbo.provider;import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import com.alibaba.dubbo.container.Main;
import com.sihai.dubbo.provider.service.ProviderService;
import com.sihai.dubbo.provider.service.ProviderServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;import java.io.IOException;/*** xml方式启动**/
public class App 
{public static void main( String[] args ) throws IOException {//加载xml配置文件启动ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/provider.xml");context.start();System.in.read(); // 按任意键退出}
}

        因为dubbo底层就是依赖spring的,所以我们通过spring容器加载dubbo配置然后启动spring容器就将服务发布出去了。

消费者端的dubbo配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd"><!--当前项目在整个分布式架构里面的唯一名称,计算依赖关系的标签--><dubbo:application name="consumer" owner="sihai"/><!--dubbo这个服务所要暴露的服务地址所对应的注册中心--><!--点对点的方式--><!--<dubbo:registry address="N/A" />--><dubbo:registry address="zookeeper://localhost:2181" check="false"/><!--生成一个远程服务的调用代理--><!--点对点方式--><!--<dubbo:reference id="providerService"interface="com.sihai.dubbo.provider.service.ProviderService"url="dubbo://192.168.234.1:20880/com.sihai.dubbo.provider.service.ProviderService"/>--><dubbo:reference id="providerService"interface="com.sihai.dubbo.provider.service.ProviderService"/></beans>

 配置说明:

        与服务提供者端的dubbo配置主要就是dubbo:reference这个节点的不同,在消费端用dubbo:reference这个节点来配置消费端要调用的远程接口信息,它的必填属性interface要指向所要引用的接口类型。

远程调用的发起方式

package com.sihai.dubbo.consumer;import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.sihai.dubbo.provider.service.ProviderService;
import org.springframework.context.support.ClassPathXmlApplicationContext;import java.io.IOException;/*** xml的方式调用**/
public class App 
{public static void main( String[] args ) throws IOException {ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("consumer.xml");context.start();ProviderService providerService = (ProviderService) context.getBean("providerService");String str = providerService.SayHello("hello");System.out.println(str);System.in.read();}
}

        通过spring容器的getBean方法,以调用本地bean的方式去调用远程服务。

dubbo的多种配置方式

        dubbo支持多种配置方式:xml配置、api配置、注解配置。dubbo官方推荐的是xml方式,不过在spring的演进过程中一直在去xml化,所以注解配置也是常用的一种配置方式。

 注解配置方式:

        主要就是服务端的@Service注解和消费端的@Reference注解,注解中都提供了与xml配置相对应的各个配置属性,只不过在使用注解方式时需要注意,要在配置类中用@EnableDubbo注解来开启对于dubbo的支持,并且通过它的scanBasePackages属性来配置容器扫描dubbo服务的包路径,即@Service注解的类所在的包路径。

api配置方式:

        api配置方式也是提供了与xml配置相对应的各个api组件,包括与<dubbo:application>对应的ApplicationConfig、与<dubbo:registry>对应的RegistryConfig、与<dubbo:service>对应的ServiceConfig、与<dubbo:reference>对应的ReferenceConfig等等,调用这些api的方法可以对dubbo进行配置。

dubbo的集群容错策略

集群模式说明使用方法
failover失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。cluster="xxx" xxx:集群模式名称 ,例如cluster="failover"
failfast快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
failsafe失败安全,出现异常时,直接忽略。
failback失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
forking并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。
broadcast广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。

        默认的方案是 failover,也就是重试机制。我们可以在发布服务或者引用服务的时候设置,也就是为<dubbo:service>或者<dubbo:reference>节点设置cluster属性。

dubbo的负载均衡策略

负载均衡模式说明使用方法
random随机 按权重设置随机概率<dubbo:service loadbalance="xxx"/> xxx:负载均衡方法
roundRobin轮询 按公约后的权重设置轮询比率。
leastActive最少活跃调用数 相同活跃数的随机,活跃数指调用前后计数差。
consistentHash一致性 Hash 相同参数的请求总是发到同一提供者。 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

dubbo的多协议支持

        在前面我们使用的协议都是 dubbo 协议,但是 dubbo除了支持这种协议外还支持其他的协议,比如,http、rmi、hessian等,另外,还可以用多种协议同时暴露一种服务。 

先声明多种协议:

 <!--当前服务发布所依赖的协议;webserovice、Thrift、Hessain、http--><dubbo:protocol name="dubbo" port="20880"/><dubbo:protocol name="rmi" port="1099" />

在发布接口时,指定多个协议,多个协议之间用英文逗号隔开:

<!--服务发布的配置,需要暴露的服务接口--><dubbo:service cluster="failover" retries="2"interface="com.sihai.dubbo.provider.service.ProviderService"ref="providerService"/><dubbo:service cluster="failover" retries="2"interface="com.sihai.dubbo.provider.service.ProviderService"ref="providerService" protocol="rmi"/>

dubbo的多注册中心支持

        dubbo支持同一服务向多注册中心同时注册,或者不同服务分别注册到不同的注册中心上去,甚至可以同时引用注册在不同注册中心上的同名服务。 

先声明多个注册中心

<!--多注册中心--><dubbo:registry protocol="zookeeper" id="reg1" timeout="10000" address="localhost:2181"/><dubbo:registry protocol="zookeeper" id="reg2" timeout="10000" address="localhost:2182"/><dubbo:registry protocol="zookeeper" id="reg3" timeout="10000" address="localhost:2183"/>

发布服务:

<!--服务发布的配置,需要暴露的服务接口--><dubbo:service cluster="failover" retries="2"interface="com.sihai.dubbo.provider.service.ProviderService"ref="providerService" registry="reg1"/><dubbo:service cluster="failover" retries="2"interface="com.sihai.dubbo.provider.service.ProviderService"ref="providerService" protocol="rmi" registry="reg1,reg2"/>

        对于dubbo的一些属性配置,如负载均衡、容错策略等,虽然在服务端和消费端都支持配置,但是dubbo的用户手册推荐的是,尽量在服务端多设置,因为服务端更了解自己所提供服务的特性。不过,如果我们在消费端进行了这些设置,那么在服务调用时,就以消费端的设置为准,即:消费端的设置具有更高优先级。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/625923.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32 CubeIDE 使用 CMSIS-DAP烧录 (方法2--外部小工具)

前言&#xff1a; 本篇所用方法&#xff0c;需要借助一个外部的工具小软件。 优点&#xff1a;烧录更稳定; 缺点&#xff1a;不能在线仿真调试。 下面链接&#xff0c;是另一种方法&#xff1a;修改CubeIDE调试文件。能在CubeIDE直接烧录、仿真&#xff0c;但不稳定。…

Bazel

简介&#xff1a; Bazel 是 google 研发的一款开源构建和测试工具,也是一种简单、易读的构建工具。 Bazel 支持多种编程语言的项目&#xff0c;并针对多个平台构建输出。 高级构建语言&#xff1a;Bazel 使用一种抽象的、人类可读的语言在高语义级别上描述项目的构建属性。与其…

uniapp 简易自定义日历

1、组件代码 gy-calendar-self.vue <template><view class"calendar"><view class"selsct-date">请选择预约日期</view><!-- 日历头部&#xff0c;显示星期 --><view class"weekdays"><view v-for"…

Linux常用命令大全(三)

系统权限 用户组 1. 创建组groupadd 组名 2. 删除组groupdel 组名 3. 查找系统中的组cat /etc/group | grep -n “组名”说明&#xff1a;系统每个组信息都会被存放在/etc/group的文件中1. 创建用户useradd -g 组名 用户名 2. 设置密码passwd 用户名 3. 查找系统账户说明&am…

蓝桥杯java基础

2. AB问题II 时间限制&#xff1a;1.000S 空间限制&#xff1a;32MB 题目描述 计算ab&#xff0c;但输入方式有所改变。 输入描述 第一行是一个整数N&#xff0c;表示后面会有N行a和b&#xff0c;通过空格隔开。 输出描述 对于输入的每对a和b&#xff0c;你需要在相应的…

openssl快速生成自签名证书

系统&#xff1a;Centos 7.6 确保已安装openssl openssl version生成私钥文件 private.key &#xff08;文件名自定义&#xff09; openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048-out private.key&#xff1a;生成的私钥文件-algorithm RS…

探索设计模式的魅力:工厂方法模式

工厂方法模式是一种创建型设计模式&#xff0c;它提供了一种创建对象的接口&#xff0c;但将具体实例化对象的工作推迟到子类中完成。这样做的目的是创建对象时不用依赖于具体的类&#xff0c;而是依赖于抽象&#xff0c;这提高了系统的灵活性和可扩展性。 以下是工厂方法模式的…

MySQL 8.0中移除的功能(二)

PROCEDURE ANALYSE()​ 语法已被移除。客户端的 ​--ssl​ 和 ​--ssl-verify-server-cert​ 选项已被移除。使用 ​--ssl-modeREQUIRED​ 代替 ​--ssl1​ 或 ​--enable-ssl​。使用 ​--ssl-modeDISABLED​ 代替 ​--ssl0​、​--skip-ssl​ 或 ​--disable-ssl​。使用 ​-…

chatgpt的基本技术及其原理

ChatGPT是一种基于生成式预训练的语言模型&#xff0c;它的基本技术包括预训练和微调。下面我将为你解释这些技术及其原理。 1. 预训练&#xff08;Pre-training&#xff09;: ChatGPT的预训练阶段是在大规模的文本数据上进行的。模型通过对大量的互联网文本进行自监督学习来学…

学习视频一些杂乱的东西

文章目录 ref获取dom元素监听深层的某个属性? 可选链操作符 和 ?? 双问号表达式v-slot 语法糖作用域插槽动态插槽 初始化数组骚操作数字滚动 -> gsapstyle妙招新奇的原型链 object.createB站笔记链接JS相关设计模式ajaxsvgvue3scsswebpack内存泄漏 ref获取dom元素 直接给…

基于深度学习的实例分割的Web应用

基于深度学习的实例分割的Web应用 1. 项目简介1.1 模型部署1.2 Web应用 2. Web前端开发3. Web后端开发4. 总结 1. 项目简介 这是一个基于深度学习的实例分割Web应用的项目介绍。该项目使用PaddlePaddle框架&#xff0c;并以PaddleSeg训练的图像分割模型为例。 1.1 模型部署 …

【iOS】数据存储方式总结(持久化)沙盒结构

在iOS开发中&#xff0c;我们经常性地需要存储一些状态和数据&#xff0c;比如用户对于App的相关设置、需要在本地缓存的数据等等&#xff0c;本篇文章将介绍六个主要的数据存储方式 iOS中数据存储方式&#xff08;数据持久化&#xff09; 根据要存储的数据大小、存储数据以及…

案例:应用内字体大小调节

文章目录 介绍相关概念完整实例 代码结构解读保存默认大小获取字体大小修改字体大小 介绍 本篇Codelab将介绍如何使用基础组件Slider&#xff0c;通过拖动滑块调节应用内字体大小。要求完成以下功能&#xff1a; 实现两个页面的UX&#xff1a;主页面和字体大小调节页面。拖动…

算法训练营第34天|● 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果

文档讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;代码随想录的个人空间-代码随想录个人主页-哔哩哔哩视频 (bilibili.com) LeetCode 1005.K次取反后最大化的数组和 题目链接&#xff1a;1005. K 次取反后最大化的数组和 - 力扣&#xff08;LeetCode…

基于物联网设计的智能储物柜(4G+华为云IOT+微信小程序)

一、项目介绍 在游乐场、商场、景区等人流量较大的地方&#xff0c;往往存在用户需要临时存放物品的情况&#xff0c;例如行李箱、外套、购物袋等。为了满足用户的储物需求&#xff0c;并提供更加便捷的服务体验&#xff0c;当前设计了一款物联网智能储物柜。 该智能储物柜通…

git提交报错:remote: Please remove the file from history and try again.

1. 报错信息 remote: error: File: fba7046b22fd74b77425aa3e4eae0ea992d44998 500.28 MB, exceeds 100.00 MB. remote: Please remove the file from history and try again. git rev-list --objects --all | grep fba7046b22fd74b77425aa3e4eae0ea992d44998 2. 分析原因 e…

打架识别摄像机

随着社会治安问题的增加&#xff0c;打架事件在公共场所频繁发生&#xff0c;给社会治安带来了一定程度的威胁。因此&#xff0c;为了提高公共场所的安全性&#xff0c;可以利用现代科技&#xff0c;如人工智能和摄像技术&#xff0c;开发一种打架识别摄像机。 这种摄像机可以通…

基于 IDEA 进行 Maven 工程构建

一、构建概念和构建过程 项目构建是指将源代码、依赖库和资源文件等转换成可执行或可部署的应用程序的过程&#xff0c;在这个过程中包括编译源代码、链接依赖库、打包和部署等多个步骤。 项目构建是软件开发过程中至关重要的一部分&#xff0c;它能够大大提高软件开发效率&…

【Docker】CentOS stream 上安装 Docker 环境详细指南

文章目录 1. 定义2. 优势3. 安装1&#xff09;Linux 上安装&#xff08;强烈推荐&#xff09;2&#xff09;Windows 和 MAC 上安装 4. 验证1&#xff09;查看版本2&#xff09;运行 Hello World 总结 Docker 是一种轻量级的容器化技术&#xff0c;提供了一种在不同环境中快速、…

Maven普通工程和web工程创建

文章目录 创建项目前设置maven工程前设置工作创建项目前--》设置utf-8配置maven参数Maven普通工程和web工程创建Maven简单工程第一步&#xff1a;File–New–Project 第二步&#xff1a;选择maven然后下一步&#xff1a;填写后询选择finish初始化maven工程目录简介maven简单工程…