Connected Reactive Publisher for Use in Microservices or Other Computing Environments
A concatenated reactive publisher with a constant memory footprint addresses the ABA problem in microservices architectures by using an atomic request counter for state management, ensuring efficient pipeline construction and high concurrency.
Patent Information
- Application Number
- JP2023526211
- Authority / Receiving Office
- JP · JP
- Patent Type
- Patents
- Current Assignee / Owner
- Priority Date
- 2021-10-27
- Filing Date
- 2021-10-28
- Publication Date
- 2025-07-17
- Estimated Expiration
- 2041-10-28
AI Technical Summary
In reactive computing environments, particularly in microservices architectures, the ABA problem arises from the reuse of values or objects, leading to issues with state management and concurrency, which complicates the construction of pipelines with a constant memory footprint.
A concatenated reactive publisher system is implemented with a constant memory footprint, using an atomic request counter to manage state transitions and handle error conditions, ensuring efficient concatenation of publisher outputs while minimizing memory usage and buffering.
The system effectively maintains a constant memory footprint, addresses the ABA problem, and ensures high concurrency without blocking operations, enabling seamless pipeline construction and efficient resource utilization.
Smart Images

Figure 0007710041000001 
Figure 0007710041000002 
Figure 0007710041000003
Abstract
Description
Technical Field
[0001] Copyright Notice Part of the disclosure of this patent document contains subject matter that is subject to copyright protection. The copyright owner has no objection to the reproduction by anyone of the patent document or patent disclosure as it appears in the patent files or records of the Patent and Trademark Office, but otherwise reserves all copyrights.
[0002] Priority Claim This application claims the benefit of priority based on U.S. Provisional Application No. 63 / 108,143, filed on October 30, 2020, entitled "CONSTANT MEMORY FOOTPRINT CONCATENATING REACTIVE PUBLISHER FOR USE WITH A MICROSERVICES OR OTHER COMPUTING ENVIRONMENT", and U.S. Patent Application No. 17 / 512,319, filed on October 27, 2021, entitled "CONCATENATING REACTIVE PUBLISHER FOR USE WITH A MICROSERVICES OR OTHER COMPUTING ENVIRONMENT", and each of the above applications and their contents are incorporated herein by reference.
[0003] Technical Field The embodiments described herein generally relate to cloud computing and other computing environments, software development, microservices architecture, and reactive computing, and more particularly to systems and methods for providing a concatenating reactive publisher with a constant memory footprint in such environments.
Background Art
[0004] Background A microservices environment can present a software application as a collection of loosely coupled services that are independently deployable and communicate with each other over a network. Using the microservices approach, for example, a software application provided as a cloud service in a cloud computing environment can be developed. In such an environment, microservices can be used to provide elasticity and use computing resources efficiently.
[0005] A reactive computing environment generally supports the use of publishers and subscribers that use onComplete signals. In such an environment, developers can control the progress of computations without relying on blocking operations, so pipelines can be constructed declaratively and high concurrency can be achieved with a small number of threads. However, care needs to be taken to address the ABA problem caused by the reuse of values or objects in a concurrent setting. In the ABA problem, a value may change from A to B and then back to A, and the update may not notice this change. SUMMARY OF THE INVENTION MEANS FOR SOLVING THE PROBLEM
[0006] Summary According to an embodiment, a system and method for providing a concatenated reactive publisher with a certain memory footprint for use in a microservices or reactive programming environment are described herein.
[0007] According to one embodiment, the publisher provides a subscription to the subscriber that supports requests for an amount up to a specific value (Long.MAX_VALUE). The publisher can track the number of requested items. When concatenating the outputs from multiple publishers, the switch between the output of one publisher and the output of the next publisher is not atomic and may involve tracking a new state, for example, when one publisher stops generating items and the next publisher has not yet started generating items.
[0008] The amount of state and the adjustments between transitions are not trivial and may include error conditions and cancellations. The described approach supports the requirement to maintain requests for an amount up to Long.MAX_VALUE by enabling the system to extend the range down to negative values and by using an atomic request counter to maintain the necessary state and delivering requests as soon as they are issued by the subscriber that owns the subscription according to the backpressure (this reduces the need for buffering).
Brief Description of the Drawings
[0009]
Figure 1
Figure 2
Figure 3
Figure 4
Figure 5
Figure 6
Figure 7
Figure 8
Figure 9
Figure 10
Figure 11
Figure 12
Figure 13
Figure 14
Figure 15
Figure 16
[0010] Detailed Description As described above, the microservices architecture can present a software application as a collection of loosely coupled services that are independently deployable and communicate with each other over a network. Using the microservices approach, for example, a software application provided as a cloud service in a cloud computing environment can be developed. In such an environment, microservices can be used to provide elasticity and efficiently utilize computing resources.
[0011] Software development frameworks such as Helidon assist in the development of microservices. For example, Helidon provides SE (Standard Edition) and MP (MicroProfile) programming models or environments, each of which includes a collection of software libraries that support features such as configuration, security, or web server functionality, providing a foundation for software developers to create microservices.
[0012] In summary, Helidon reduces the need for software developers to program according to specific tooling or deployment models and enables the execution of microservices without the need for an application server. The Helidon libraries are interoperable with other software development, deployment, and / or monitoring tools such as Docker, Kubernetes, Prometheus, or OpenTracing.
[0013] Microservices Environment (Helidon) FIG. 1 shows an example of a microservices environment that provides a software development framework according to an embodiment.
[0014] As shown in FIG. 1, according to an embodiment, the Helidon microservices environment 100 provides both SE (Standard Edition) and MP (MicroProfile) programming models or environments.
[0015] According to an embodiment, the Helidon SE environment 110 can include various libraries, APIs, or other components, such as a reactive web server 111 that provides asynchronous and reactive APIs for creating web applications, a configuration API 112 that provides a Java (registered trademark) API for loading and processing configuration properties in key / value format into a configuration object that the application can later use to retrieve configuration data, and a security component 113 that provides authentication, authorization, and outbound security. It can also include metrics 114, health checks 115, and traces 116 or other components.
[0016] According to an embodiment, the Helidon MP environment 120 can include various libraries, APIs, or other components, such as components like JAX-RS 122, JSON-P 126, CDI 124, metrics 128, health checks 130, fault tolerance 132, MicroProfile Configuration 134, and JWT authentication 136. According to an embodiment, the web server can be provided by a non-blocking client / server / web framework 118 such as Netty. The microservices environment can also enable interaction with a cloud, database, or other system or service 140.
[0017] FIG. 2 shows an example of a Helidon SE microservices environment according to an embodiment.
[0018] As shown in Figure 2, according to an embodiment, the Helidon SE environment supports a functional programming style that directly uses web servers, security, and configuration components, provides transparency and control to software developers, and supports Java features such as reactive streams and asynchronous functional programming. The Helidon SE environment provides a framework that allows software developers to build lightweight reactive microservices.
[0019] Figure 3 shows an example of a Helidon MP microservices environment according to an embodiment.
[0020] As shown in Figure 3, according to an embodiment, the Helidon MP environment supports a declarative programming style by using a family of MicroProfile APIs built on top of the Helidon libraries. Application portability can be supported across multiple MicroProfile runtimes using MicroProfile definitions (specified, for example, by the Eclipse MicroProfile project).
[0021] According to an embodiment, a microservices environment can present a software application as a collection of loosely coupled services that are independently deployable and communicate with each other over a network. For example, the Helidon microservices environment can support the use of a remote procedure call (e.g., gRPC) framework or component, which enables (client and / or server) applications to communicate within the microservices environment to build connected systems.
[0022] Figure 4 shows communication in a microservices environment according to an embodiment. The example shown and described in FIG. 4 is provided for the purpose of showing one type of communication supported by a microservices environment, and other types of communication may be supported according to other embodiments and examples.
[0023] As shown in FIG. 4, according to one embodiment, a remote procedure call framework enables the definition of services and methods that can be called remotely. A server or service can handle calls from a client through a local object (stub) in the client that enables the client application to call directly on methods on the server application as if they were local objects. The server / service can handle client calls, including decoding incoming requests, executing service methods, and encoding service responses, by implementing the methods. The local object (stub) implements the same methods as the service and wraps the parameters for the call into an appropriate protocol buffer message type. These parameters are then provided to the server as a request.
[0024] According to one embodiment, a microservices library enables access by a client application to communicate with microservices, or to interact with a cloud, database, or other systems or services, for the purpose of accessing data, processing transactions, or performing other operations related to those systems or services.
[0025] Reactive environment In a traditional message-driven environment, a producer sends a message to a consumer when the message becomes available, but if the consumer cannot process the message in real time, the received message is stored in a buffer, which can lead to performance issues.
[0026] According to one embodiment, the microservices environment can provide a reactive environment, such as a reactive engine or reactive messaging API, for use with activities such as transaction processing, asynchronous messaging channels, or reactive streams.
[0027] FIG. 5 shows the use of a reactive environment in a microservices environment according to one embodiment.
[0028] The example shown and described in FIG. 5 is provided for the purpose of showing an example of one type or usage of a reactive environment supported by the microservices environment, and other types and usages of reactive environments may be provided according to other embodiments and examples.
[0029] As shown in FIG. 5, according to one embodiment, the reactive environment 200 enables a client application 220 to communicate reactively with services as publishers and subscribers within the microservices environment. The connector 212 can be used to provide access to the reactive messaging channel for publishers and subscribers, or support for the use of reactive messaging with Kafka, JMS, or other types of messaging, message queuing, or stream processing environments can be provided. The reactive environment enables asynchronous stream processing with a non-blocking backpressure. That is, the subscriber notifies the publisher of the amount of data it can process, and the publisher sends an appropriate amount of data in response to the subscriber's request.
[0030] FIG. 6 further shows the use of a reactive environment according to one embodiment. As shown in FIG. 6, in accordance with an embodiment, a publisher 231 (referred to as Publisher in some examples herein) operates as a producer of data in accordance with requests made by its subscribers. A subscriber 232 (referred to as Subscriber in some examples herein) operates as a consumer of data generated by the publisher. A subscription 234 (referred to as Subscription in some examples herein) defines the relationship by which a subscriber subscribes to a publisher and provides a mechanism by which a subscriber can request more data (from the publisher). In accordance with an embodiment, a processor (referred to as Processor in some examples herein) may be provided that operates as a message / data processing stage and as both a subscriber and a publisher via a subscription.
[0031] FIG. 7 further shows the use of a reactive environment, according to an embodiment. As shown in Figure 7, according to an embodiment, when a subscriber is passed to a publisher, the subscriber receives a call to the method onSubscribe(Subscription), but does not immediately start receiving data items or other events. Data items are received by the subscriber only when the subscriber calls the method request(long) within its subscription to notify the publisher of a request for more data. The subscriber can receive data through calls to the method Subscriber.onNext called with the next item, and this method can be called a number of times (n) determined by the long value passed in the method request(long) of its subscription. The method Subscriber.onError() can be called when an error occurs during the processing of the stream. The method Subscriber.onComplete() can be called when there is no more data to be processed. If both the onError() and onComplete() events are called, no new data will be emitted by the publisher even if the method request(long) is called again.
[0032] Connectable reactive publisher with a certain memory footprint Modern software benefits from using backpressure to orchestrate computations into asynchronous pipelines. This allows developers to control the progress of computations without relying on blocking operations, enabling the pipelines to be built declaratively and achieving high concurrency with a small number of threads.
[0033] A reactive computing environment generally supports the use of publishers and subscribers that use the onComplete signal. In such an environment, developers can control the progress of computations without relying on blocking operations, enabling pipelines to be constructed declaratively and achieving high concurrency with a small number of threads. However, care must be taken to address the ABA problem resulting from the reuse of values or objects in concurrent settings. In the ABA problem, a value may change from A to B and then back to A, and the update may not notice this change. In accordance with an embodiment, a system and method for providing a concatenated reactive publisher with a constant memory footprint for use in a microservice or reactive programming environment are described herein.
[0034] For example, in Reactive Java, asynchronous pipelines are composed of publishers, subscribers, and processors. It is important to be able to combine the outputs from multiple publishers into a single strictly ordered flow and to construct a pipeline that conforms to the publisher API. To do so, it is necessary to carefully orchestrate state transitions and follow backpressure from downstream components to ensure both timely arrival of items and suspension when the downstream is not ready. This is particularly difficult to achieve lock-free and even more difficult to do with a constant (O(1)) memory footprint.
[0035] In accordance with an embodiment, a system and method for providing a concatenated reactive publisher with a constant memory footprint for use in a microservice or reactive programming environment are described herein.
[0036] According to an embodiment, the publisher provides a subscription to the subscriber that supports requests up to a certain value (Long.MAX_VALUE). The publisher can track the number of requested items. When concatenating the outputs from multiple publishers, the switch between the output of one publisher and the output of the next publisher is not atomic and may involve tracking a new state, for example, when one publisher stops generating items and the next publisher has not yet started generating items.
[0037] The amount of state, and the coordination between transitions, is not trivial and may include error conditions and cancellations. The approach described supports the requirement to maintain requests up to Long.MAX_VALUE by enabling the system to extend the range down to negative values and by using an atomic request counter to maintain the necessary state and deliver requests as soon as they are issued by the subscriber owning the subscription in accordance with the backpressure (this reduces the need for buffering).
[0038] According to an embodiment, technical advantages of the approach described include, for example, minimizing the memory footprint and minimizing the points where coordination is required. The memory footprint is reduced by delegating all error condition management to the inner publishers. That is, as long as the inner publishers are used one after another, it is only necessary to transfer their onError signals downstream, and no further coordination is required.
[0039] FIG. 8 shows a system that provides a concatenated reactive publisher with a constant memory footprint according to an embodiment.
[0040] As shown in FIG. 8, in accordance with certain embodiments, the system includes or operates a restricted recursive process 300 that uses an upstream Publisher 251 to publish data items 260, 270, 280 via a plurality of internal publishers A 262, B 272, N 282. Each of the internal publishers A 262, B 272, N 282 is associated with an internal subscriber 264, 274, 284 respectively, and provides data via internal subscriptions 268, 278, 288 as a stream of events used by a downstream Subscriber 252.
[0041] As shown, the concatenated reactive publisher 240 can use a request counter 300, the value 302 of which can be used to indicate the transition A→B→A and as a generation counter. The system also provides a pending counter 310, the value 312 of which is used to track requests coming from the downstream subscriber. Both the pending counter and the request counter can be in any of four states: BAD, CANCEL, SEE_OTHER, or INIT (count). By combining the generation count and the request count, the creation of new small objects is avoided and memory usage is suppressed.
[0042] FIG. 9 further shows a system that provides a concatenated reactive publisher with a constant memory footprint, in accordance with certain embodiments.
[0043] According to an embodiment, the approach described enables the sequential draining of an array of internal publishers. During that time, the system tracks the requests coming from downstream and delegates most of the processing of the transitions or errors to the internal publishers (illustrated as 330, 340, 350 in FIGS. 10 - 15) acting on those transitions. Thereby, the system can avoid creating new objects, minimize the communication between the internal publishers and the downstream subscribers, thus keeping the memory footprint constant, and can also determine an instance that can handle the ABA problem.
[0044] According to an embodiment, the approach described provides a non - buffering component that is O(1) memory footprint, lock - free, and compliant with the Reactive Java Publisher API. Other approaches using two counters may involve discarding one counter after invalidating it and instead allocating a new counter (not a constant memory footprint), maintaining more state considering synchronization considerations such as the ABA problem, or blocking state transitions (not lock - free). According to an embodiment, the approach described supports maintaining the necessary additional state using an extended range.
[0045] According to an embodiment, it can be observed that the request counter does not decrease. The system can modify this condition to always increment the request counter when switching from one publisher to the next. To do so, the request count needs to be extended to allow for all possible requests from downstream in the full range from 0 to Long.MAX_VALUE. However, since the number of publishers concatenated in this way is not limited, the system can support concatenation of publishers up to Long.MAX_VALUE - 3 without loss of precision. This additional range is used to always correct the request counter when a publisher stops generating items.
[0046] According to an embodiment, the described approach supports distinguishing between two types of requests so as to ensure only one delivery of a normal request and at least one delivery of an illegal request.
[0047] According to an embodiment, even if the range is extended, a subscriber can observe that it can issue enough requests to exceed the extended range of the request counter. However, the system needs to accurately capture the request count only for normal requests that do not exceed Long.MAX_VALUE.
[0048] After reaching that value, since MAX_VALUE can always be requested, the system does not need to pass the normal request to any publisher. At the same time, an illegal request needs to generate an onError event. This can be achieved by atomically migrating from the current request count to the BAD request value and delivering this request count to the current publisher. Different from normal requests, since there is no limit that it can only be requested once, the correct publisher for delivering the onError event can be found without relying on the management of additional states. Typically, when an error occurs in an intermediate component, it is necessary to track it as an additional state to ensure that only one and only one onError event is delivered.
[0049] Handling the ABA problem in a certain space According to an embodiment, the ABA problem is a problem of reusing values or objects in a concurrent setting, where the value changes from A to B and then back to A again, and the atomic update may not notice this change. In some examples, this is addressed by not reusing the object so that the state does not return from B to A, but in this approach, new allocations occur during the lifetime of the program.
[0050] According to one embodiment, here, objects are reused while keeping the memory footprint constant. The ABA problem is addressed by ensuring that the transition from B to A can occur only in carefully managed harmless cases. This can be achieved through a monotonic increase in the request counter, and thus, concurrent updates to the counter will not miss other updates. However, this is not sufficient in this scenario. Because there are several other conditions that need to be tracked, such as cancellation of a subscription, error conditions notified by an internal publisher, invalid requests by a downstream subscriber, and switching from one internal subscription to the next.
[0051] In addition, in the presence of an internal publisher, it is necessary to track the number of requests issued by a downstream subscriber that are not satisfied by the current internal publisher, so that when the next internal publisher is ready, this unsatisfied amount can be requested from the next internal publisher.
[0052] One of the complex parts of the reactive specification is the requirement to handle invalid requests from downstream subscribers by generating an onError signal. When the internal publisher is ready, it is easy to simply delegate the invalid request to the internal publisher. However, when switching from one internal subscription to the next, there is a time when the current internal subscription is in a terminated state and the new internal subscription has not yet arrived from the next internal publisher, so it cannot be delegated. When the concatenating publisher issues its own onError event, it is necessary to ensure that for any other signals that any internal publisher may issue, they are serialized correctly, and that no more signals are transferred to the downstream subscribers after the onError event is signaled, and to ensure that non-terminated subscriptions are cancelled. According to the approach described herein, this is addressed by delegating the invalid request to the next internal publisher.
[0053] According to an embodiment, in the option of delegating all requests and cancellations to the internal publisher and transferring all signals to the downstream subscribers, it is necessary to follow the backpressure when switching from one internal subscription to the next, that is, when the subscriber issues a valid request, all internal publishers that are regarded as a single stream of onNext signals by the downstream subscriber do not issue any more onNext events. For this purpose, it is necessary to pass on the number obtained by subtracting the number of satisfied requests from the number of requests issued to a certain internal publisher to the next internal publisher, and this should be achieved without atomic state transitions.
[0054] According to an embodiment, the system can observe that each internal subscription is in one of the following four states.
[0055] Requests can be safely issued for internal subscriptions. Requests can be safely issued for internal subscriptions and can be safely passed on to the next internal publisher.
[0056] Requests can be safely issued for internal subscriptions, but this is wasteful and the requests must be passed on to the next internal publisher.
[0057] Requests can be safely issued for internal subscriptions, but this is wasteful and the new requests will not further affect the signals observed by downstream subscribers.
[0058] It can be observed that the following conditions hold universally. That is, if it cannot be proven that the subscription has ended, requests should be issued to the subscriptions that existed before the atomic update to the request counter. This is to ensure "at most once" delivery of the signal. Also, if it cannot be proven that the subscription has observed a request and delivered the signal, requests should be issued to the subscriptions that exist after the atomic update to the request counter. This is to ensure "at least once" delivery of the signal.
[0059] According to an embodiment, using the first approach, double counting does not occur and it is guaranteed to follow the backpressure. It is necessary to detect the conditions when the subscription reaches the end state and pass on the unfulfilled requests to the next internal subscription (if it can still be safely passed on).
[0060] According to an embodiment, using the second approach, the propagation of cancellation and error signals caused by invalid requests is guaranteed. It is possible to safely issue cancellation or invalid requests more than once to any internal subscription. That is, it is possible to safely permit simultaneous cancellation, requests, and other routines that can observe this state, and guarantee the delivery of these signals to the current or other internal subscriptions, and issuing these signals does not cause two or more onError or other end states (such as suspension).
[0061] According to an embodiment, distinguishing between these two approaches can be achieved through the coordination between the following two.
[0062] onSubscribe - Issued by the internal publisher to indicate that it is ready to provide an internal subscription.
[0063] onComplete - Issued by the internal publisher to indicate that the internal subscription has reached the end state program order between onComplete from an internal subscription and onSubscribe of the next simultaneous call of request() or cancel().
[0064] According to an embodiment, this is done through the management of two atomic counters, a request counter and a pending counter.
[0065] onComplete sets the request counter and the pending counter to a state where either one can be safely updated. The request counter is already in such a state, and the pending is set to the number of requests that have already been satisfied. This number is not modified simultaneously because the internal subscription has reached the end state.
[0066] onComplete atomically sets the request counter to the SEE_OTHER state which requires that simultaneous request() calls only update the pending counter.
[0067] onComplete atomically updates the pending counter with the number of requests that are not yet satisfied. This number is calculated from the value of the request counter and the number of satisfied requests.
[0068] If simultaneous request() calls occur before the request counter is set to the SEE_OTHER state which requires that simultaneous request() calls update the pending counter, they issue requests to subscriptions that are known to be in a state where they update the request counter and do not produce further signals. Thus, the number of requests can be safely carried over to the pending counter later.
[0069] According to one embodiment, if simultaneous request() calls occur after the request counter has been set to the SEE_OTHER state but before the next onSubscribe, they update the pending counter and do not interact with any internal subscriptions. The subsequent atomic update of the pending counter by onComplete tracks both the unsatisfied requests and these simultaneous requests.
[0070] According to one embodiment, the feature of the described approach is the handling of the pending counter and the request counter by onSubscribe. The operation performed is effectively the reverse of what onComplete does, copying the pending counter to the request counter, but this is done in a subtly different way. The reason will become clear when considering the ABA problem later.
[0071] onSubscribe sets up a new internal subscription. onSubscribe sets the demand counter and the pending counter to a state where either one can be safely updated. The pending counter is already in such a state, and the demand counter is set to the current value of the pending counter.
[0072] onSubscribe atomically sets the pending counter to the SEE_OTHER state, which requires that concurrent request() calls only update the demand counter, and issues a request() call for the current internal subscription.
[0073] onSubscribe updates the demand counter if there is a concurrent update to the pending counter between setting the demand counter and setting the pending counter to the SEE_OTHER state.
[0074] onSubscribe issues unfulfilled requests to the internal subscription. This is calculated from the state of the pending counter and the number of previously fulfilled requests. Since the internal publisher cannot issue onNext before onSubscribe completes, this counter is not updated concurrently.
[0075] If concurrent calls to request() occur before setting the demand counter to the pending counter, they update the pending counter and do not interact with any internal subscriptions. Thus, the number of pending requests can be safely passed on to the demand counter, and request() for the internal subscription can be called.
[0076] According to an embodiment, if a concurrent call to request() occurs after setting the request counter to the value of the pending counter, they update the request counter and issue the request directly to the current internal subscription. There is no need to track these in a special way. However, it should be noted that this is a situation where the ABA problem can occur if the request counter is not carefully managed.
[0077] In particular, if the request counter is set to SEE_OTHER by onComplete and then, by onSubscribe, is returned to the same value that was seen by onComplete (temporarily stored in the pending counter), the concurrent request() call will call request() for the internal subscription observed before updating the request counter. This internal subscription could be the one that existed at the time before onComplete finished. Such a request cannot be satisfied by that internal subscription and may be observed by the downstream subscriber as a lack of progress.
[0078] According to an embodiment, the system can ensure that the value of the request counter is not the same when the internal subscription changes. This is done by artificially incrementing the request counter in onComplete and artificially incrementing the counter for satisfied requests in onSubscribe to keep the backpressure the same as before onComplete.
[0079] In addition, the system can maintain the available backpressure range by expanding the request counter range from 0 to approximately twice the required range of Long.MAX_VALUE by starting the request counter from INIT which is Long.MIN_VALUE + 3. Thus, if the publisher processes onComplete INIT times, the downstream subscriber cannot detect the absence of available backpressure. In modern physical systems, this is impossible to achieve, and even reactive specifications treat Long.MAX_VALUE as effectively infinite.
[0080] If a concurrent request() attempts to issue an invalid request, an ABA problem may still occur, and a harmless race condition may occur. If onSubscribe sets a new internal subscription and sets the request counter, such a concurrent request() call will observe this internal subscription when it is set, forward the invalid request to it, and ultimately result in an onError signal. Or, if such a subscription is already in a terminal state, an onComplete may be brought about, which simply maintains the state of the request counter until the next onSubscribe. onSubscribe does not observe concurrent request() that issue invalid requests and can issue some valid requests that are not satisfied. This cannot create more events than permitted by the reactive specification.
[0081] According to one embodiment, by extending the request counter range, it can be observed that internal subscription changes can be detected only until the counter reaches Long.MAX_VALUE. This is possible despite the range extension. That is, the downstream subscriber is not obliged to stop issuing request() when a certain level of backpressure is reached and may exceed the extended range, for example, by requesting Long.MAX_VALUE more than twice.
[0082] In this state, the ABA problem occurs again. That is, it can be observed that the request counter changes from Long.MAX_VALUE to SEE_OTHER and then back to Long.MAX_VALUE again, but concurrent calls to request() cannot detect this. This is because the counter cannot continue to increment beyond Long.MAX_VALUE. However, the proposed design guarantees that this is harmless in the ABA problem case, as will be explained below.
[0083] According to one embodiment, concurrent request() may issue request() for an incorrect internal subscription, i.e., an internal subscription that is already in the terminated state, when it cannot observe changes in the internal subscription. However, when issuing a valid request, this does not lead to a loss of backpressure level. The ABA problem can occur only after onSubscribe follows onComplete. Even if concurrent requests can issue request() for a paused internal subscription, onSubscribe will observe that the request counter is already Long.MAX_VALUE and will issue a request for Long.MAX_VALUE for the new internal subscription, so the correct level of backpressure is maintained.
[0084] Event processing Figures 10 to 15 show various examples of event processing according to an embodiment.
[0085] According to an embodiment, as an example, FIG. 10 shows an environment where the ABA problem occurs but there is no harm. That is, onSubscribe issues a request to maintain an appropriate amount of backpressure, and no new events will occur even if request() is issued to the suspended internal subscription "sub1".
[0086] FIG. 11 shows a second case where when an invalid request reaches Long.MAX_VALUE and is passed by a downstream subscriber, a simultaneous request() cannot observe a change in the internal subscription. In this case, onSubscribe may issue Long.MAX_VALUE to a new internal subscription, but a simultaneous request(), following the normal request procedure, may update the request counter and issue request() to the old (suspended) internal subscription observed before updating the request counter.
[0087] According to an embodiment, FIG. 11 shows an environment where a simultaneous cancel() or request() cannot observe a change in the internal subscription, and if these signals are issued to "sub1" observed before updating the request counter following the normal request() protocol, it may violate the cancellation or error notification requirements of the reactive publisher specification. Instead, in this design, these specific conditions follow different paths. That is, when performing a cancellation or invalid request, these calls are issued to the internal subscription observed after the atomic update of the request counter.
[0088] According to various embodiments, possible interleaves of events may include, for example, the following.
[0089] As shown in FIG. 12, the system issues a cancellation or invalid request to a suspended internal subscription.
[0090] As shown in FIG. 13, the system issues two cancellation or invalidation requests for the same internal subscription.
[0091] As shown in FIG. 14, the system issues a cancellation or invalidation request simultaneously with onSubscribe.
[0092] According to an embodiment, FIG. 15 shows an environment where, when the request counter is updated for each new internal subscription, concurrent calls to request() can detect changes in the internal subscription, and thus issue a request() to an internal subscription that is known to be in a terminal state (the request can be safely passed on to the next internal publisher), or observe a new internal subscription (a routine for setting up a new subscription can detect that such an update of the request counter does not require a handover).
[0093] FIG. 16 shows a process for providing a concatenated reactive publisher with a constant memory footprint according to an embodiment.
[0094] As shown in FIG. 16, according to an embodiment, in step 360, a computer including one or more processors and memory, and a microservices environment (microservices library) provides a reactive environment that can be used with reactive streams so that a client application and a server application can communicate within the microservices environment.
[0095] In step 362, a plurality of publishers and subscribers are provided within a reactive environment, and onSubscribe is issued by an internal publisher to indicate that it is ready to provide internal subscriptions. Also, onComplete can be issued by the internal publisher to indicate that the internal subscription has reached an end state between onComplete from the internal subscription and onSubscribe for the next concurrent call of request() or cancel().
[0096] In step 364, a request counter and a pending counter for storing values are provided in relation to the concatenated reactive publisher.
[0097] In step 366, onComplete sets the request counter and the pending counter to a state where they can be safely updated, which includes that the request counter is already in such a state and the pending counter is set to the number of requests that have already been satisfied.
[0098] In step 368, onComplete atomically sets the request counter to the SEE_OTHER state which requires that a concurrent request() call only updates the pending counter.
[0099] In step 370, onComplete atomically updates the pending counter with the number of requests that have not yet been satisfied, which is calculated from the value of the request counter and the number of satisfied requests.
[0100] In step 372, the reactive environment processing processes requests in a plurality of internal publishers that request communication of data to downstream subscribers.
[0101] In accordance with various embodiments, aspects of the present disclosure may include, for example, the following. A system for providing a concatenated reactive publisher with a certain memory footprint for use in a microservices or reactive programming environment, comprising: a computer including one or more processors, the computer providing access to a microservice or other computing environment for use with a software application, the publisher providing a subscription to a subscriber that supports a quantity of requests up to a specific value, the system being adapted to extend a request range and maintain a required state with the use of a request counter and deliver the request when issued by the subscriber owning the subscription, the system.
[0102] A method for providing a concatenated reactive publisher with a certain memory footprint for use in a microservices or reactive programming environment, comprising: providing, in a computer including one or more processors, a microservice or other computing environment for use with a software application, the publisher providing a subscription to a subscriber that supports a quantity of requests up to a specific value, the method further comprising: extending a request range and maintaining a required state with the use of a request counter and delivering the request when issued by the subscriber owning the subscription.
[0103] A non-transitory computer-readable storage medium storing instructions that, when read and executed by one or more computers, cause the one or more computers to perform steps, the steps comprising: In a computer including one or more processors, including the step of providing a microservice or other computing environment for use with a software application, The publisher provides a subscription to the subscriber that supports an amount request up to a specific value, and the above step further includes In conjunction with the use of a request counter, expanding the request range to maintain the required state and delivering the request when the request is issued by the subscriber owning the above subscription, a non-transitory computer-readable storage medium.
[0104] According to various embodiments, the teachings herein can be advantageously implemented using one or more conventional general-purpose or special-purpose computers, computing devices, machines, or microprocessors, including one or more processors, memories, and / or computer-readable storage media programmed according to the teachings of the present disclosure. Appropriate software coding can be readily prepared by a skilled programmer based on the teachings of the present disclosure, as will be apparent to those skilled in the software art.
[0105] In some embodiments, the teachings herein can include a computer program product that is a non-transitory computer-readable storage medium (s) storing instructions that can be used to program a computer to execute any of the processes of the present teachings. Examples of such storage media include, but are not limited to, hard disk drives, hard disks, hard drives, fixed disks, or other electromechanical data storage devices, floppy (registered trademark) disks, optical disks, DVDs, CD-ROMs, microdrives, and magneto-optical disks, ROMs, RAMs, EPROMs, EEPROMs, DRAMs, VRAMs, flash memory devices, magnetic or optical cards, nanosystems, or other types of storage media or devices suitable for non-transitory storage of instructions and / or data.
[0106] The foregoing description is provided for purposes of illustration and explanation. It is not intended to be exhaustive or to limit the scope of protection to the precise forms disclosed. Many modifications and variations will be apparent to those of ordinary skill in the art.
[0107] For example, while various embodiments of the systems and methods described herein are shown for use in a Helidon microservices environment, the various embodiments can be used in other types of microservices environments or other computing environments.
[0108] Embodiments are chosen and described in order to best explain the principles of the present teachings and their practical application, to thereby enable one of ordinary skill in the art to understand the present teachings in various embodiments and with various modifications as are suited to the particular use contemplated. The scope is intended to be defined by the following claims and their equivalents.
Claims
1. A system for use in a reactive computing environment for providing a chained reactive publisher, comprising a computer including one or more processors, the computer providing a reactive environment for use with microservices and software applications, a publisher, a subscriber, and supporting the use of on-complete signals, the publisher providing to the subscriber a subscription that supports a request for an amount up to a specific value, the system using a value of a request counter to indicate a transition between publishers and using a value of a pending counter to track requests from the subscriber, the request counter and the pending counter being set to a state that can be updated safely, the pending counter being set to the number of satisfied requests, the request counter being set to a state that requires that a concurrent request call update only the pending counter, the pending counter being set to the number of unsatisfied requests calculated from the value of the request counter and the number of satisfied requests, the system being a system that delivers a request when the request is issued by the subscriber that owns the subscription.
2. The system according to claim 1, wherein the system extends a request range to a negative value and delivers a request when the request is issued by the subscriber that owns the subscription.
3. The reactive environment according to claim 1 or 2, wherein the reactive environment enables a client software application to communicate reactively with services as a publisher and a subscriber within a microservices environment.
4. The system according to any one of claims 1 to 3, wherein the reactive environment is provided within a cloud computing environment that provides access to one or more clouds, databases, or other systems or services.
5. A method for use in a reactive computing environment for providing a chained reactive publisher, A computer including one or more processors provides a reactive environment that supports the use of publishers, subscribers, and on-complete signals for use with microservices and software applications, The publisher provides a subscription to the subscriber that supports a quantity request up to a specific value, and the method further includes, The computer uses the value of a request counter to indicate a transition between publishers and uses the value of a pending counter to track requests from the subscriber, The request counter and the pending counter are set to a state that can be updated safely, The pending counter is set to the number of satisfied requests, The request counter is set to a state that requires that concurrent request calls update only the pending counter, The pending counter is set to the number of unsatisfied requests, calculated from the value of the request counter and the number of satisfied requests, and the method further includes, The computer delivers a request when the request is issued by the subscriber that owns the subscription. A method. The method according to claim 5, further comprising the computer expanding a request range to a negative value and delivering the request when the request is issued by the subscriber that owns the subscription. Claim 7 The reactive environment according to claim 5 or 6, wherein a client software application can communicate reactively with a service as a publisher and a subscriber within a microservices environment. Claim 8 The reactive environment according to any one of claims 5 to 7, provided within a cloud computing environment that provides access to one or more clouds, databases, or other systems or services. Claim 9 A computer-readable program for causing one or more computers to execute the method according to any one of claims 5 to 8.
Citation Information
Patent Citations
A Novel Non-Parametric Statistical Behavioral Identification Ecosystem for Power Fraud Detection
JP2020516979A
Systems and Methods for Controlling Retention of Publication
US20110099232A1