Disclosure of Invention
The embodiment of the application provides a message queue and consumer dynamic creation method and system, and solves the problem that in a multi-tenant SaaS system architecture in the prior art, when the service processing capacity of some tenants is too large, the service data of other tenants cannot be processed in time.
In a first aspect, an embodiment of the present application provides a method for dynamically creating a message queue and a consumer, including:
s1: in a multi-tenant SaaS system, establishing an MQ dynamic configuration rule between each service project and each tenant, and automatically creating an exclusive message queue and a consumer of each tenant for each service project by self-defining a message queue annotation on a sendDatak method body;
s2: monitoring a subject message of a new tenant created by the SaaS system according to a consumer monitoring class preset by each service project; according to the MQ dynamic configuration rule and the monitored subject message, scanning a consumer method of a user-defined message queue annotation used by the business project, and creating an exclusive message queue and a consumer for a newly added tenant in each business project;
s3: when a newly added service project is initialized and started, a consumer method for automatically capturing the annotation of the used self-defined message queue by using a configuration class is utilized according to an MQ dynamic configuration rule, and an exclusive message queue and a consumer are generated for each tenant in the newly added service project; the consumer method annotated by the used custom message queue is captured in all methods under all classes in all the service items obtained by scanning; the user-defined message queue annotation carries a queue name and a RouteKey; simulating the process of registering the consumer to a Spring container by the RabbitMq by acquiring the queue name and the RouteKey carried in the annotation, and splicing the unique identification Code of the tenant in front of the queue name and the RouteKey so as to generate a special consumer for each tenant in the newly added service project; the unique identification Code is determined and obtained based on the subject message of the new tenant created in the SaaS system.
Further, in the step S2, when a subject message for creating a new tenant is received, a create consumer interface is called, and the custom message queue is used for annotation on a consuming method of a consumer class.
Further, in the subject message of the new tenant created by the SaaS system, the subject message carries the unique identification Code of the new tenant, and the subject message is pushed into the queue to notify each service item of creating the exclusive message queue of the new tenant and the consumer.
Further, in the step S2, each service item creates a consumer interface by writing, simulates a process of registering a consumer to a Spring container by a RabbitMq, and splices the unique identification Code of the new tenant in front of the queue name and RouteKey, so as to generate an exclusive message queue and a consumer for the new tenant.
Further, in the step S3, the method for automatically capturing the customer annotated by using the custom message queue using the configuration class includes using the custom message queue annotation on a consumption method in the customer class of the newly added service item, and querying the unique identification codes Code of all tenants in the SaaS system through the configuration class of the SpringBoot framework.
In a second aspect, an embodiment of the present application provides a message queue and consumer dynamic creation system, where the method in the first aspect is adopted, and includes: the system comprises a rule configuration module, a first creation module and a second creation module, wherein the rule configuration module is respectively connected with the first creation module and the second creation module;
the rule configuration module is configured to construct MQ dynamic configuration rules for each service project and each tenant in a multi-tenant SaaS system, and automatically create an exclusive message queue and a consumer of each tenant for each service project by self-defining a message queue annotation on a sendDatak method body;
the first creation module is configured to monitor a subject message of a new tenant created by the SaaS system according to a consumer monitoring class preset by each service project; according to the MQ dynamic configuration rule and the monitored subject message, scanning a consumer method of a user-defined message queue annotation used by the business project, and creating an exclusive message queue and a consumer for a newly added tenant in each business project;
and the second establishing module is configured to generate an exclusive message queue and a consumer for each tenant in the newly added service project by utilizing a consumer method for automatically capturing the annotation of the user-defined message queue by using a configuration class according to an MQ dynamic configuration rule when the newly added service project is initialized and started.
Further, the system also comprises a tenant adding module, and the tenant adding module is connected with the first creating module; the tenant adding module is configured to create a new tenant in the SaaS system, and push a theme message of the added tenant to the first creating module.
Further, the system also comprises a service adding module, wherein the service adding module is connected with the second establishing module; and the service adding module is configured to create a new service item in the RabbitMq message queue and push the new service item to the second creating module for configuration.
In a third aspect, an embodiment of the present disclosure provides an electronic device, including a memory and a processor; wherein the memory is configured to store one or more computer instructions, wherein the one or more computer instructions are executed by the processor to implement the method steps of the first aspect.
In a fourth aspect, the disclosed embodiments provide a computer-readable storage medium for storing computer instructions for a message-passing apparatus of a message-middleware, which contains computer instructions for executing the message-passing method of the message-middleware in the first aspect.
The technical scheme provided in the embodiment of the application has at least the following technical effects:
(1) The problem of throughput blocking of the SaaS system in the traditional message queue design is solved, the message queue MQ technology is utilized, the exclusive message queue and the consumers are dynamically established for each tenant in the multi-tenant SaaS system, data isolation among different tenants is guaranteed, and meanwhile reliability of consumer service is improved and throughput of the consumer service is improved.
(2) After the MQ dynamic configuration rule in the technical scheme is utilized, developers do not need to write codes for all tenants respectively, only need to set the MQ dynamic configuration rule, and directly create an exclusive message queue and consumers of the tenants corresponding to the service project when the tenants or the service project is newly added, so that a solution for data isolation in the message queue is provided by using a simple configuration rule on the premise of reducing the workload of the developers.
It is to be understood that both the foregoing general description and the following detailed description are exemplary and explanatory only and are not restrictive of the disclosure.
Detailed Description
In order to better understand the technical solution, the technical solution will be described in detail with reference to the drawings and the specific embodiments.
The scientific and technical terms involved in the invention are explained as follows:
SaaS: software is a service; MQ: a message queue; rabbitMQ: message queue middleware; spring: a Spring frame; routeKey: routing matching keywords; code: a unique identification code of the tenant; spring boot: spring boot frame.
The embodiment of the application provides a message queue and consumer dynamic creation method and system, and solves the problem that in a multi-tenant SaaS system architecture in the prior art, when the service processing capacity of some tenants is too large, the service data of other tenants cannot be processed in time. In order to make those skilled in the art better understand the technical solutions in the present application, the technical solutions in the embodiments of the present application will be clearly and completely described below with reference to the drawings in the embodiments of the present application, and it is obvious that the described embodiments are only a part of the embodiments of the present application, and not all the embodiments. All other embodiments obtained by a person of ordinary skill in the art based on the embodiments in the present application without making any creative effort shall fall within the protection scope of the present application.
Example 1
Referring to fig. 1, a flowchart of a method for dynamically creating a message queue and a consumer according to an embodiment of the present application is shown.
Step S1: in a multi-tenant SaaS system, MQ dynamic configuration rules are constructed for each service project and each tenant, and a message queue annotation is customized on a sendTask method body, so that a dedicated message queue and a consumer of each tenant are automatically established for each service project.
The embodiment utilizes a message queue technology and improves a data transmission mode based on a multi-tenant system. Referring to fig. 2, an architecture diagram applicable to the multi-tenant SaaS system is shown. And the data is transmitted to a database by a plurality of tenants through a Web Server to be stored for service. The embodiment is based on the improvement and optimization of data transmission and throughput in a multi-tenant SaaS system. Referring to fig. 3-5, the connection relationship between the multi-tenant and the business project, which is applicable to the embodiment of the present application, is shown.
sendTask Fang Fati represents sending task, when any one of the business project and the tenant has dynamic change, according to the self-defined message queue annotation, automatically creating the exclusive message queue and the consumer of each tenant for each business project. Referring to fig. 4 and 5, when a tenant is newly added, a dedicated message queue and a consumer of the newly added tenant are created for each service item, and when a service item is newly added, a dedicated message queue and a consumer of all tenants in the newly added service item are created for the newly added service item.
Step S2: monitoring a subject message of a new tenant created by the SaaS system according to a consumer monitoring class preset by each service project; and according to the MQ dynamic configuration rule and the monitored subject message, scanning a consumer method of the user-defined message queue annotation used by the service project, and creating an exclusive message queue and a consumer for the newly added tenant in each service project.
In this embodiment, the theme message of the new tenant created by the SaaS system carries the unique identification Code of the new tenant, and notifies each service item to create the exclusive message queue of the new tenant and the consumer by pushing the unique identification Code into the queue. Certainly, the message queue and the consumer bound by the existing tenant also carry the displacement identification Code of the tenant.
In step S2, when a subject message for creating a new tenant is received, invoking a create consumer interface, and annotating with a custom message queue on a consuming method of a consumer class. I.e. MQ dynamic configuration rules are set in the consumer-like consumption method.
In step S2, each service project creates a consumer interface by writing, simulates a process of registering a consumer to a Spring container by the RabbitMq, and splices a unique identification Code of the new tenant in front of the queue name and RouteKey, so as to generate an exclusive message queue and the consumer for the new tenant. Furthermore, an interface for creating a consumer is compiled in the step, the process that a message queue middleware RabbitMq registers the consumer to a Spring frame container is simulated, and a unique identification Code of the tenant is spliced before a queue name and a route are matched with a keyword RouteKey, so that an exclusive message queue and the consumer are created for the newly added tenant in each service item.
The step S2 is mainly expressed in that, when a tenant is newly added, a connection relationship with the newly added tenant is actively created in each service item according to the MQ dynamic configuration rule, that is, an exclusive message queue and a consumer are created for the newly added tenant, so that when the information of the newly added tenant is accessed through the SaaS system, the corresponding service item can be quickly processed directly through the exclusive message queue and the consumer.
Further, the step of proactively creating tenant-specific message queues and consumers may include:
s21: and writing a custom message queue annotation, wherein the annotation carries a queue name and a RouteKey for later establishing a queue and a consumer.
S22: when a new tenant is added, a theme message for creating the new tenant is pushed to the queue, the message carries the unique identification Code of the new tenant, and each service project creation consumer is informed. The codes are as follows:
public void initMessageListenerContainerForCreateTenant(String tenantCode){try{ConnectionFactory connectionFactory=getRabbitConnectionFactory();RabbitAdmin rabbitAdmin=getRabbitAdmin();AbstractRabbitListenerContainerFactory simpleRabbitListenerContainerFactory=getRabbitListenerContainerFactory(connectionFactory);
RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry=new RabbitListenerEndpointRegistry();rabbitListenerEndpointRegistry.start();
RabbitListenerEndpointRegistrar rabbitListenerEndpointRegistrar=new RabbitListenerEndpointRegistrar();
Set<String>queueNameSet=new HashSet<>();
Method[]declaredMethods=null;CustomRabbitListener customRabbitListener=null;RabbitListenerEnum rabbitListenerConfig=null;String className=null;String methodName=null;Object bean=null;String queueName=null;String routeKey=null;
String simpleRabbitListenerEndpointId=null;Queue queue=null;SimpleRabbitListenerEndpointsimpleRabbitListenerEndpoint=null;Set<Class<?>>classSet=ClassUtil.scanPackage("com.ibaiqiu");
……
s23: and compiling a monitoring consumer in each business project for monitoring the message for creating a new tenant, calling an interface for creating the consumer when receiving the message, and annotating by using a self-defined message queue on a consumption method in a consumer class.
S24: writing an interface for creating a consumer, simulating the process of registering the consumer to a Spring container by the RabbitMq, and splicing a unique identification Code of the tenant in front of the queue name and the RouteKey to generate a special consumer for the new tenant.
And creating a new tenant in the SaaS, wherein the new tenant comprises a plurality of tenant information including a unique identification code, a name, an abbreviation, a state and a function authority of the new tenant, and the function authority comprises a platform, content, commodities, marketing, orders and the like used by the tenant. After the creation is completed, the SaaS system automatically pushes the subject message for creating the new tenant to all queues, after the queues receive the message, an interface for creating the consumer is called, a process that a RabbitMq (message queue middleware) registers the consumer to a Spring frame container is simulated, a unique identification Code of the tenant is spliced in front of a queue name and a routeKey (route matching keyword), a dedicated consumer is generated for the new tenant, and all data of the test merchant 1 are pushed to the queues with the prefixes of the unique identification codes.
And step S3: when the newly added service project is initialized and started, a consumer method for automatically capturing the annotation of the used self-defined message queue by using the configuration class is utilized according to the dynamic configuration rule of the MQ, and a dedicated message queue and consumers are generated for each tenant in the newly added service project.
In step S3, the method for automatically capturing a customer annotated by using a custom message queue using a configuration class includes using the custom message queue annotation on a consuming method in a customer class of a newly added service item, and querying unique identification codes of all tenants in the SaaS system through the configuration class of the SpringBoot framework.
Step S3, further comprising scanning all methods under all classes in all business projects, finding out a consumer method annotated by using a custom message queue, and acquiring a queue name and a RouteKey carried in the annotation; simulating the process of registering the consumer to a Spring container by the RabbitMq, and splicing the unique identification Code of the tenant in front of the queue name and the RouteKey so as to generate a special consumer for each tenant in a newly added service project.
Step S3 in this embodiment is a message queue and consumer passive creation process, which may include the following steps.
S31: writing a custom message queue annotation, using the custom message queue annotation on a consumption method in a consumer class, wherein the annotation carries a queue name and a RouteKey and is used for creating a message queue and a consumer later.
The following code represents the use of custom message queue annotation on a consuming method in the consumer class.
@Component
public class UserLoginLogSaveListener{
private static final String IP_ADDRESS_ANALYSIS_URL="http://whois.pconline.com.cn/ipJson.jspjson=true&ip=";
private static final String IP_ADDRESS_AREA="addr";
private static String UNKNOWN _ IP _ ADDRESS _ AREA = "UNKNOWN";
@Autowired
private UserLoginLogDao userLoginLogDao;
@ManualAck(requeue=false)
@CustomRabbitListener(rabbitListenerConfig=RabbitListenerEnum.USER_LOGIN_LOG_SAVE_LISTENER)
public void saveUserLoginLog(Message message,Channel channel)throws Exception{
UserLoginLog userLoginLog=JSONObject.parseObject(message.getBody(),UserLoginLog.class);
String ipAddress=userLoginLog.getIpAddress();
AssertUtil.fastAssert(ReturnCode.USER_IP_ADDRESS_IS_NULL,ipAddress);
Map<String,String>resultMap=HttpClientUtils.getResult(IP_ADDRESS_ANALYSIS_URL+ipAddress,newTypeReference<Map<String,String>>(){});
if(AssertUtil.isNull(resultMap)||AssertUtil.isNull(resultMap.get(IP_ADDRESS_AREA)))
{userLoginLog.setIpAddressArea(UNKNOWN_IP_ADDRESS_AREA);}else
{userLoginLog.setIpAddressArea(resultMap.get(IP_ADDRESS_AREA));}userLoginLogDao.insertSelective(userLoginLog)}}
s32: writing a Springboot configuration class, and inquiring the unique identification codes of all tenants in the SaaS system.
Writing Springboot configuration the code for a class is as follows:
“@Component@Order(value=2)private class InitMessageListenerContainer implements CommandLineRunner{@Overridepublic void run(String...args)throws Exception{try{ConnectionFactory connectionFactory=getRabbitConnectionFactory();RabbitAdmin rabbitAdmin=getRabbitAdmin();AbstractRabbitListenerContainerFactorysimpleRabbitListenerContainerFactory=getRabbitListenerContainerFactory(connectionFactory);
RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry=newRabbitListenerEndpointRegistry();rabbitListenerEndpointRegistry.start();RabbitListenerEndpointRegistrarrabbitListenerEndpointRegistrar=newRabbitListenerEndpointRegistrar();DynamicDataSource.setDataSource(Constant.DataSource.PLATFORM_DATASOURCE);
List<String>tenantCodeList=tenantDao.getTenantCodeList();”。
s33: all methods under all classes in the business project are scanned, a consumer method using the user-defined message queue annotation is found, and the queue name and RouteKey carried in the annotation are obtained.
In the multi-data source mode, whether the multi-data source mode is turned on is determined, such as "if" (rabbitlistenerenum. Multiple data source mode. On = = rabbitlistenerconfig. Getmultiple data source mode () ".
Further, a multi-data-source mode is started, all tenants are traversed, tenant codes are spliced in front of queue names and routing keys to generate corresponding consumers for each tenant, and Code analysis is as follows:
“for(String tenantCode:tenantCodeList){queueName=(rabbitListenerConfig.getMultipleNodeMode()?ipAddressPrefix:StrUtil.EMPTY)+tenantCode+StrUtil.DOT+rabbitListenerConfig.getQueue();routeKey=tenantCode+StrUtil.DOT+rabbitListenerConfig.getRouteKey();simpleRabbitListenerEndpointId=(rabbitListenerConfig.getMultipleNodeMode()?ipAddressPrefix:StrUtil.EMPTY)+tenantCode+StrUtil.DOT+className+StrUtil.DOT+methodName;registerListenerContainer(queueNameSet,queueName,queue,rabbitAdmin,rabbitListenerConfig,routeKey,simpleRabbitListenerEndpoint,simpleRabbitListenerEndpointId,method,bean,simpleRabbitListenerContainerFactory,rabbitListenerEndpointRegistry);}”。
aiming at a mode without opening multiple data sources, no splicing is carried out, consumers are directly generated, and code analysis is as follows:
“queueName=(rabbitListenerConfig.getMultipleNodeMode()?ipAddressPrefix:StrUtil.EMPTY)+rabbitListenerConfig.getQueue();routeKey=rabbitListenerConfig.getRouteKey();simpleRabbitListenerEndpointId=(rabbitListenerConfig.getMultipleNodeMode()?ipAddressPrefix:StrUtil.EMPTY)+className+StrUtil.DOT+methodName;registerListenerContainer(queueNameSet,queueName,queue,rabbitAdmin,rabbitListenerConfig,routeKey,simpleRabbitListenerEndpoint,simpleRabbitListenerEndpointId,method,bean,simpleRabbitListenerContainerFactory,rabbitListenerEndpointRegistry);”。
s34: simulating the process of registering the consumer to a Spring container by the RabbitMq, and splicing the unique identification Code of the tenant in front of the queue name and the RouteKey so as to generate a special consumer for each tenant.
Example 2
Referring to fig. 6, an embodiment of the present application provides a message queue and consumer dynamic creation system, which employs the method as in embodiment 1, and includes a rule configuration module 100, a first creation module 200, and a second creation module 300, where the rule configuration module 100 is connected to the first creation module 200 and the second creation module 300, respectively.
The rule configuration module 100 is configured to construct MQ dynamic configuration rules for each service project and each tenant in the multi-tenant SaaS system, and automatically create an exclusive message queue and a consumer for each service project by self-defining a message queue annotation on the sendTask method body.
The first creation module 200 is configured to monitor a subject message of a new tenant created by the SaaS system according to a consumer monitoring class preset for each service project; and according to the MQ dynamic configuration rule and the monitored subject message, scanning a consumer method of self-defined message queue annotation used by the service project, and creating a special message queue and a consumer for the newly added tenant in each service project.
The second creating module 300 is configured to generate a dedicated message queue and a consumer for each tenant in the newly added service project by using a consumer method for automatically capturing the used custom message queue annotation by using a configuration class according to the MQ dynamic configuration rule when the newly added service project is initialized and started.
The embodiment further includes a tenant adding module 400, and the tenant adding module 400 is connected to the first creating module 200; the tenant adding module 400 is configured to create a new tenant in the SaaS system, and push a theme message of the new tenant to the first creating module 200.
The embodiment further includes a service adding module 500, where the service adding module 500 is connected to the second creating module 300; the service adding module 500 is configured to create a new service item in the RabbitMq message queue, and push the new service item to the second creating module 300 for configuration.
Example 3
The embodiment provides an electronic device, comprising a memory and a processor; wherein the memory is configured to store one or more computer instructions, wherein the one or more computer instructions are executed by the processor to implement the method steps of embodiment 1.
The present embodiment provides a computer readable storage medium having stored thereon computer instructions which, when executed by a processor, implement the method steps of embodiment 1.
Improvements to a technology can clearly be distinguished between hardware improvements (e.g. improvements to the circuit structure of diodes, transistors, switches, etc.) and software improvements (improvements to the process flow). However, as technology advances, many of today's process flow improvements have been seen as direct improvements in hardware circuit architecture. Designers almost always obtain the corresponding hardware circuit structure by programming an improved method flow into the hardware circuit. Thus, it cannot be said that an improvement in the process flow cannot be realized by hardware physical modules. For example, a Programmable Logic Device (PLD), such as a Field Programmable Gate Array (FPGA), is an integrated circuit whose Logic functions are determined by programming the Device by a user. A digital system is "integrated" on a PLD by the designer's own programming without requiring the chip manufacturer to design and fabricate application-specific integrated circuit chips. Furthermore, nowadays, instead of manually manufacturing an Integrated Circuit chip, such Programming is often implemented by "logic compiler" software, which is similar to a software compiler used in program development and writing, but the original code before compiling is also written by a specific Programming Language, which is called Hardware Description Language (HDL), and HDL is not only one but many, such as ABEL (Advanced Boolean Expression Language), AHDL (alternate Hardware Description Language), traffic, CUPL (core universal Programming Language), HDCal, jhddl (Java Hardware Description Language), lava, lola, HDL, PALASM, rhyd (Hardware Description Language), and vhjh-Language (Hardware Description Language), which is currently used by Hardware compiler-Language-2. It will also be apparent to those skilled in the art that hardware circuitry that implements the logical method flows can be readily obtained by merely slightly programming the method flows into an integrated circuit using the hardware description languages described above.
The controller may be implemented in any suitable manner, for example, the controller may take the form of, for example, a microprocessor or processor and a computer-readable medium storing computer-readable program code (e.g., software or firmware) executable by the (micro) processor, logic gates, switches, an Application Specific Integrated Circuit (ASIC), a programmable logic controller, and an embedded microcontroller, examples of which include, but are not limited to, the following microcontrollers: ARC 625D, atmel AT91SAM, microchip PIC18F26K20, and Silicone Labs C8051F320, the memory controller may also be implemented as part of the control logic for the memory. Those skilled in the art will also appreciate that, in addition to implementing the controller as pure computer readable program code, the same functionality can be implemented by logically programming method steps such that the controller is in the form of logic gates, switches, application specific integrated circuits, programmable logic controllers, embedded microcontrollers and the like. Such a controller may thus be considered a hardware component, and the means included therein for performing the various functions may also be considered as a structure within the hardware component. Or even means for performing the functions may be regarded as being both a software module for performing the method and a structure within a hardware component.
The systems, apparatuses, modules or units described in the above embodiments may be specifically implemented by a computer chip or an entity, or implemented by a product with certain functions.
For convenience of description, the above devices are described as being divided into various units by function, and are described separately. Of course, the functionality of the units may be implemented in one or more software and/or hardware when implementing the present application.
As will be appreciated by one skilled in the art, embodiments of the present invention may be provided as a method, system, or computer program product. Accordingly, the present invention may take the form of an entirely hardware embodiment, an entirely software embodiment or an embodiment combining software and hardware aspects. Furthermore, the present invention may take the form of a computer program product embodied on one or more computer-usable storage media (including, but not limited to, disk storage, CD-ROM, optical storage, and the like) having computer-usable program code embodied therein.
The present invention is described with reference to flowchart illustrations and/or block diagrams of methods, apparatus (systems), and computer program products according to embodiments of the invention. It will be understood that each flow and/or block of the flow diagrams and/or block diagrams, and combinations of flows and/or blocks in the flow diagrams and/or block diagrams, can be implemented by computer program instructions. These computer program instructions may be provided to a processor of a general purpose computer, special purpose computer, embedded processor, or other programmable data processing apparatus to produce a machine, such that the instructions, which execute via the processor of the computer or other programmable data processing apparatus, create means for implementing the functions specified in the flowchart flow or flows and/or block diagram block or blocks.
These computer program instructions may also be stored in a computer-readable memory that can direct a computer or other programmable data processing apparatus to function in a particular manner, such that the instructions stored in the computer-readable memory produce an article of manufacture including instruction means which implement the function specified in the flowchart flow or flows and/or block diagram block or blocks.
These computer program instructions may also be loaded onto a computer or other programmable data processing apparatus to cause a series of operational steps to be performed on the computer or other programmable apparatus to produce a computer implemented process such that the instructions which execute on the computer or other programmable apparatus provide steps for implementing the functions specified in the flowchart flow or flows and/or block diagram block or blocks.
In a typical configuration, a computing device includes one or more processors (CPUs), input/output interfaces, network interfaces, and memory.
The memory may include forms of volatile memory in a computer readable medium, random Access Memory (RAM) and/or non-volatile memory, such as Read Only Memory (ROM) or flash memory (flash RAM). Memory is an example of a computer-readable medium.
Computer-readable media, including both non-transitory and non-transitory, removable and non-removable media, may implement information storage by any method or technology. The information may be computer readable instructions, data structures, modules of a program, or other data. Examples of computer storage media include, but are not limited to, phase change memory (PRAM), static Random Access Memory (SRAM), dynamic Random Access Memory (DRAM), other types of Random Access Memory (RAM), read Only Memory (ROM), electrically Erasable Programmable Read Only Memory (EEPROM), flash memory or other memory technology, compact disc read only memory (CD-ROM), digital Versatile Discs (DVD) or other optical storage, magnetic cassettes, magnetic tape magnetic disk storage or other magnetic storage devices, or any other non-transmission medium that can be used to store information that can be accessed by a computing device. As defined herein, a computer readable medium does not include a transitory computer readable medium such as a modulated data signal and a carrier wave.
It should also be noted that the terms "comprises," "comprising," or any other variation thereof, are intended to cover a non-exclusive inclusion, such that a process, method, article, or apparatus that comprises a list of elements does not include only those elements but may include other elements not expressly listed or inherent to such process, method, article, or apparatus. Without further limitation, an element defined by the phrase "comprising a … …" does not exclude the presence of another identical element in a process, method, article, or apparatus that comprises the element.
All the embodiments in the present specification are described in a progressive manner, and the same and similar parts among the embodiments are referred to each other, and each embodiment focuses on the differences from other embodiments. In particular, for the system embodiment, since it is substantially similar to the method embodiment, the description is simple, and for the relevant points, reference may be made to the partial description of the method embodiment.
The above are merely examples of the present application and are not intended to limit the present application. Various modifications and changes may occur to those skilled in the art. Any modification, equivalent replacement, improvement, etc. made within the spirit and principle of the present application should be included in the scope of the claims of the present application.