forked from eventlet/eventlet
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Describes Eventlet's Alternatives Into the Migration Guide (eventlet#971
) * shorten the lines * Document alternatives and methodology * adding a glossary * why abandonning eventlet This is the beginning of the implementation of the migration guide proposed here: https://review.opendev.org/c/openstack/governance/+/902585 The goal is to centralize all the materials we have to help users to safely migrate off of Eventlet.
- Loading branch information
Showing
5 changed files
with
336 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
.. _awaitlet_alternative: | ||
|
||
Awaitlet as an Alternative | ||
========================== | ||
|
||
Applications with several years of existence may have seen their code base | ||
growing again and again, thus, migrating this kind of existing code | ||
base toward AsyncIO, would be painful or even unrealistic. For most of these | ||
applications, migrating to AsyncIO would may mean a complete rewriting of | ||
these applications. | ||
|
||
`Awaitlet <https://awaitlet.sqlalchemy.org/en/latest/>`_ is an alternative | ||
which allow you to migrate this kind of existing code base without getting | ||
the headaches associated to migrating such deliverables. | ||
|
||
Awaitlet allows existing programs written to use threads and blocking APIs to | ||
be ported to asyncio, by replacing frontend and backend code with asyncio | ||
compatible approaches, but allowing intermediary code to remain completely | ||
unchanged, with no addition of ``async`` or ``await`` keywords throughout the | ||
entire codebase needed. Its primary use is to support code that is | ||
cross-compatible with asyncio and non-asyncio runtime environments. | ||
|
||
Awaitlet is a direct extract of `SQLAlchemy <https://www.sqlalchemy.org/>`_’s | ||
own asyncio mediation layer, with no dependencies on SQLAlchemy. This code has | ||
been in widespread production use in thousands of environments for several | ||
years. | ||
|
||
.. warning:: | ||
|
||
Using Awaitlet require to use the :mod:`Asyncio Hub | ||
<eventlet.hubs.asyncio>` | ||
|
||
:ref:`understanding_hubs` | ||
|
||
Here is an example of Awaitlet usage:: | ||
|
||
import asyncio | ||
import awaitlet | ||
|
||
def asyncio_sleep(): | ||
return awaitlet.awaitlet(asyncio.sleep(5, result='hello')) | ||
|
||
print(asyncio.run(awaitlet.async_def(asyncio_sleep))) | ||
|
||
We invite the reader to read the `Awaitlet synopsis | ||
<https://awaitlet.sqlalchemy.org/en/latest/synopsis.html>`_ to get a better | ||
overview of the opportunities offered by this library. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
.. _manage-your-deprecations: | ||
|
||
Manage Your Deprecations | ||
======================== | ||
|
||
Libraries or applications may have specific features who are strongly related | ||
to Eventlet, like the ``heartbeat_in_pthread`` feature in | ||
the Opentack `oslo.messaging | ||
<https://docs.openstack.org/oslo.messaging/latest/configuration/opts.html#oslo_messaging_rabbit.heartbeat_in_pthread>`_ | ||
deliverable. | ||
|
||
Migrating off of Eventlet would make these features obsolete. As this kind of | ||
feature expose configuration endpoints people would have to deprecate them to | ||
allow your users to update their config files accordingly. However, the | ||
deprecation process would take several months or even numerous versions before | ||
hoping to see these features removed. Hence blocking the migration. | ||
|
||
The proposed solution is to mock these features with empty entrypoints | ||
who will only raise deprecation warnings to inform your users that they have | ||
to update their config files. After 1 or 2 new versions these empty mocks | ||
could be safely removed without impacting anybody. | ||
|
||
In other words, these feature will remain in the code, but they will do | ||
nothing. They will be empty feature allowing us to migrate properly. | ||
|
||
Example with the ``heartbeat_in_pthread`` feature, by using Asyncio | ||
we wouldn't have to run heartbeats in a separated threads. This feature, | ||
the RabbitMQ heartbeat, would be run in a coroutine. A coroutine who is | ||
ran in the main native thread. The config option will remain available but | ||
it will only show a deprecation warning like the following one:: | ||
|
||
__main__:1: DeprecationWarning: Using heartbeat_in_pthread is | ||
deprecated and will be removed in {SERIES}. Enabling that feature | ||
have no functional effects due to recent changes applied in the | ||
networking model used by oslo.messaging. Please plan an update of your | ||
configuration. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
.. _glossary_guide: | ||
|
||
Glossary | ||
======== | ||
|
||
This glossary provides a brief description of some of the terms used within | ||
Eventlet in general, and more specifically in the migration context. | ||
The goal of this glossary is to ensure that everybody has the same | ||
understanding of the used terms. | ||
|
||
For more information about anything the migration, see the | ||
:ref:`migration-guide`. | ||
|
||
.. _glossary-concurrency: | ||
|
||
Concurrency | ||
----------- | ||
|
||
**Concurrency** is when two or more tasks can start, run, and complete in | ||
overlapping time **periods**. It doesn't necessarily mean they'll ever both be | ||
running **at the same instant**. For example, _multitasking_ on a single-core | ||
machine. | ||
|
||
.. _glossary-cooperative-multitasking: | ||
|
||
Cooperative Multitasking | ||
------------------------ | ||
|
||
Whenever a **thread** begins sleeping or awaiting network I/O, there is a | ||
chance for another thread to take the **GIL** and execute Python code. | ||
This is **cooperative multitasking**. | ||
|
||
.. _glossary-coro: | ||
|
||
Coro | ||
---- | ||
|
||
Using the name **coro** is a common convention in the Python API | ||
documentation. It refers to a coroutine; i.e., strictly speaking, the result | ||
of calling an async def function, and not the function itself. | ||
|
||
.. _glossary-coroutine: | ||
|
||
Coroutine | ||
--------- | ||
|
||
**Coroutines** are programs components that allow execution to be suspended | ||
and resumed, generalizing. They have been described as "functions whose | ||
execution you can pause". | ||
|
||
.. _glossary-future: | ||
|
||
Future | ||
------ | ||
|
||
A **future** represents a future completion state of some activity and is | ||
managed by the loop. A Future is a special low-level awaitable object that | ||
represents an eventual result of an asynchronous operation. | ||
|
||
.. _glossary-greenlet: | ||
|
||
Greenlet | ||
-------- | ||
|
||
A **greenlet** is a lightweight **coroutine** for in-process sequential | ||
concurrent programming (see **concurrency**). You can usually think of | ||
greenlets as cooperatively scheduled **threads**. The major differences are | ||
that since they’re cooperatively scheduled, you are in control of when they | ||
execute, and since they are **coroutines**, many greenlets can exist in a | ||
single native **thread**. | ||
|
||
Greenlets are cooperative (see **cooperative multitasking**) and sequential. | ||
This means that when one greenlet is running, no other greenlet can be | ||
running; the programmer is fully in control of when execution switches between | ||
greenlets. In other words ones, when using greenlets, should not expect | ||
**preemptive** behavior. | ||
|
||
Greenlet is also the name of a `library | ||
<https://greenlet.readthedocs.io/en/latest/>`_ that provide the greenlet | ||
mechanism. Eventlet is based on the greenlet library. | ||
|
||
.. _glossary-green-thread: | ||
|
||
Green Thread | ||
------------ | ||
|
||
A **green thread** is a **threads** that is scheduled by a runtime library | ||
or virtual machine (VM) instead of natively by the underlying operating system | ||
(OS). Green threads emulate multithreaded environments without relying on any | ||
native OS abilities, and they are managed in user space) instead of kernel | ||
space, enabling them to work in environments that do not have native thread | ||
support. | ||
|
||
.. _glossary-gil: | ||
|
||
Global Interpreter Lock (GIL) | ||
----------------------------- | ||
|
||
A **global interpreter lock (GIL**) is a lock used internally to CPython to | ||
ensure that only one **thread** runs in the Python VM at a time. In general, | ||
Python offers to switch among threads only between bytecode instructions (see | ||
**preemptive multitasking** and **cooperative multitasking**). | ||
|
||
.. _glossary-parallelism: | ||
|
||
Parallelism | ||
----------- | ||
|
||
**Parallelism** is when tasks _literally_ run at the same time, e.g., on a | ||
multicore processor. A condition that arises when at least two threads are | ||
executing simultaneously. | ||
|
||
.. _glossary-preemptive: | ||
|
||
Preemptive/Preemption | ||
--------------------- | ||
|
||
**Preemption** is the act of temporarily interrupting an executing **task**, | ||
with the intention of resuming it at a later time. This interrupt is done by | ||
an external scheduler with no assistance or cooperation from the task. | ||
|
||
.. _glossary-preemptive-multitasking: | ||
|
||
Preemptive multitasking | ||
----------------------- | ||
|
||
**Preemptive multitasking** involves the use of an interrupt mechanism which | ||
suspends the currently executing process and invokes a scheduler to determine | ||
which process should execute next. Therefore, all processes will get some | ||
amount of CPU time at any given time. | ||
|
||
CPython also has _preemptive multitasking_: If a thread runs | ||
uninterrupted for 1000 bytecode instructions in Python 2, or runs 15 | ||
milliseconds in Python 3, then it gives up the GIL and another thread may run. | ||
|
||
.. _glossary-task: | ||
|
||
Task | ||
---- | ||
|
||
A **task** is a scheduled and independently managed **coroutine**. Tasks are | ||
awaitable objects used to schedule coroutines concurrently. | ||
|
||
.. _glossary-thread: | ||
|
||
Thread | ||
------ | ||
|
||
**Threads** are a way for a program to divide (termed "split") itself into two | ||
or more simultaneously (or pseudo-simultaneously) running tasks. Threads and | ||
processes differ from one operating system to another but, in general, a | ||
thread is contained inside a process and different threads in the same process | ||
share same resources while different processes in the same multitasking | ||
operating system do not. | ||
|
||
When do threads switch in Python? The switch depends on the context. The | ||
threads may be interrupted (see **preemptive multitasking**) or behave | ||
cooperatively (see **cooperative multitasking**). |
Oops, something went wrong.