Coder Social home page Coder Social logo

roma-glushko / hyx Goto Github PK

View Code? Open in Web Editor NEW
73.0 3.0 7.0 242 KB

πŸ§˜β€β™€οΈ Lightweight fault tolerant primitives for your modern asyncio Python microservices

Home Page: https://hyx.readthedocs.io/en/latest/

License: Apache License 2.0

Python 98.17% Makefile 1.83%
asyncio chaos-engineering circuit-breaker python3 resilience distributed-systems high-availability stability-patterns

hyx's Introduction

Hyx

πŸ§˜β€β™‚οΈοΈLightweight fault tolerance primitives for your resilient and modern Python microservices

Package Version Downloads Supported Python Versions Discord
Documentation Status Test Status Coverage


Hyx (/ˈhʌΙͺx/) is a set of well-known stability patterns that are commonly needed when you build microservice-based applications. Hyx is meant to be Hystrix (Java), resilience4j (Java) or Polly (C#) but for the Python world.

Key Features

  • Implements five commonly used resiliency patterns with various configurations based on advice and experience of industry leaders (e.g. AWS, Google, Netflix)
  • Idiomatic Pythonic implementation based on decorators and context managers
  • AsyncIO Native Implementation
  • Lightweight. Readable Codebase. High Test Coverage

Requirements

Installation

Hyx can be installed from PyPi:

pip install hyx

# or via poetry
poetry add hyx

Component Map

Component Problem Solution Implemented?
πŸ” Retry The failures happen sometimes, but they self-recover after a short time Automatically retry operation on temporary failures βœ…
πŸ’Ύ Cache
⚑️ Circuit Breaker When downstream microservices have got overloaded, sending even more load can make the situation only worse. Stop doing requests to your failing microservice temporarily if amount of errors exceeded expected thresholds. Then see if the given time helped the microservice to recover βœ…
⏱ Timeout Sometimes operations may take too much time. We cannot wait that long or after that time the success is unlikely Bound waiting to a reasonable amount of time βœ…
🚰 Bulkhead If executed without control, some code can take too much resources and put down the whole application (and upstream services) or cause slowness of other places of the application Fix the amount of calls to the code, queue other calls and fail calls that goes beyond your capacity βœ…
πŸƒβ€β™‚οΈ Rate Limiter The microservice can be requested with any rate even one that can put it down if happens by accident Limit the rate your system can be accessed by βœ…
🀝 Fallback Nothing can guarantee you that your dependencies will work. What would you do when it's failing? Degrade gracefully by defining some default values or placeholders if your dependencies are down βœ…

Inspired by Polly's Resiliency Policies

Acknowledgements

hyx's People

Contributors

chris2w avatar kevkevy3000 avatar roma-glushko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

hyx's Issues

✨ Implement error-rate-based circuit breaker

Hyx is providing a circuit breaker based on the consecutive error number right now.

We need to expand that and provide a circuit breaker based on rolling window stats (e.g. percentage of failed requests).

Let's think about providing the rolling window stats as a separate low-level component, so other project could use it to implement very custom rate limiters or similar things.

References:

✨ Init Pixi

Pixi is an example of a microservice system that used asyncio modern Python to power its services. Microservices are running in Kubernetes cluster with chaos testing tools enabled.

It uses Hyx to improve resiliency of the system and test Hyx under the near-real-world scenarios.

To make this task simpler, I will get my inspiration for Pixi's functionality from Google's https://github.com/GoogleCloudPlatform/microservices-demo

Introduce circuit breaker manager

As brought up in #85, I would be great to have a single component that manages seamlessly all breakers in the service.

The manager could be defined somewhere as a singleton and passed around the places (via dependency injection, for example):

from typing import Any

import httpx


class CurrencyRate:
    ...


class CurrencyRates:
    def __init__(self, breaker_manager: CircuitBreakerManager) -> None:
        self._breaker_manager = breaker_manager

    async def get_rates(self) -> list[CurrencyRate]:
        with self.breaker_manager("currency.rates", exceptions=(httpx.NetworkError,)):  # manager creates/retrieves and activates breaker
            async with httpx.AsyncClient() as client:
                response = await client.get("https://api.github.com/events")

                return self._map_rates(response.json())

    def _map_rates(self, data: list[dict[str, Any]]) -> list[CurrencyRate]:
        ...

✨ Implement hook/event system

Hyx needs to provide various hooks to let user code react to changes in the Hyx's components.

The basic usecase will be metric reporting around component lifecycle.

How do I use this?

Coming from resilience4j, I have no idea how to use this nice library. Am I missing the docs?

✨ Implement service-level retry budgets

The current retry component is based on the counting retries that happens on the scope of one request.

It's useful to watch for a general amount of requests/retries we have done so far trying to communicate with given dependant mservice.

Retry Pattern

Implement the retry pattern:

  • as a decorator that extends existing functions
  • accept list of exceptions to retry on
  • accept wait strategies
  • accept jitter strategies

Expose ToketBucket as a standalone component

The hyx.ratelimit package provides TokenBucketLimiter component:

class TokenBucketLimiter(RateLimiter):

Its API is rather simplistic and hard to reuse if you want to pull that bucket logic to reuse somewhere (for example, to implement a custom bucket retry).

Let's refactor the TokenBucket logic out of the ratelimiter and expose it outside of Hyx, so other projects could import it.

✨ Add LIFO-based bulkheads

In some situations, requests that come some time ago is less relevant to ones that has just arrived. Hyx needs to provide a way to select serving strategy

✨ Implement leaky bucket rate limiter

Hyx is providing a token bucket-based rate limiting at this moment.

Let's implement a leaky bucket-based rate limiting, too.

We should provide LeakyBucket as a standalone component, so other projects could import it to build their very custom logic as well as use it in the leaky bucket limiter implementation.

✨ Design how to bucket rate limiting by users/requesters/etc

The current Hyx's rate limiter APIs were inspired by resilience4j/Polly. So each instance of rate limiter handles one rate limit "shard" (e.g. basically, the level on which you apply rate limiting. It could per user, per user/request route, etc). As you could imagine, this is SUPER low level implementation which is almost certainly insufficient for the regular usecases 😌

What I have found people really needed is an API that would be integrated easily into their API framework of their choice (e.g. Flask, Starlette, FastAPI) and allowed to have many shards right away. With such implementation in place, we will close the most common and basic need for rate limiting.

Now, to be able to store a big number of shards, we will need to explore a use of probabilistic data structures, so we could "compress" the exact shard's limit quotas for the sake of a low memory footprint.

Definition of Done

  • Come up with a new rate limiter API that would incorporate a need for supporting many shards. Feel free to review the existing framework-specific middleware (like https://pypi.org/project/fastapi-limiter/) to account for the step 2 of this initiative which is providing a middleware for such frameworks based on framework-agnostic rate limiters that Hyx provides
  • Try to implement that new API for the tokenbucket rate limiter using probabilistic data structures to hold its shard state

References

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.