Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: XRay Integration to Full Async with Enhanced Concurrency and Stability #67

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

fraybyl1
Copy link

@fraybyl1 fraybyl1 commented Feb 13, 2025

This Pull Request makes a significant change to the service architecture, moving it completely to an asynchronous operating model. This change is aimed at improving performance, scalability and reliability.

This change is intended to increase the stability of the nodes.

Key Changes and Improvements:

xray.py

  • Replaced the thread-based implementation of XRayCore with an asyncio-based approach.
  • Used asyncio.create_subprocess_exec for non-blocking interaction with the XRay process.
  • Implemented an asyncio.Event (_start_event) to signal XRay startup completion, replacing the previous blocking polling mechanism.
  • Implemented a dedicated asynchronous task (_log_processor_task) for processing logs and distributing them to panel, avoiding blocking the main event loop.
  • Improved error handling and timeout management during startup, shutdown, and restart of the XRay process. Includes graceful termination with a fallback to kill() if necessary.
  • Cancels the log processing task on shutdown to prevent resource leaks and ensure proper cleanup.

rest_service.py

All methods of the Service class are now fully asynchronous, avoiding I/O locks.

  • Added asyncio.Lock for secure access to shared resources:
  • _conn_lock - protects connection state (connected, client_ip, session_id).
  • _core_lock - prevents simultaneous execution of several operations with XRayCore (start, stop, restart).

Improved handling of WebSocket logs:

  • Logs are now read via log_queue.get_nowait(), without blocking.
  • Added batch processing to improve efficiency.
  • Handled errors (WebSocketDisconnect and others) to avoid crashes.
  • Asyncio.sleep replaced blocking delays.
  • Start, stop, and restart methods simplified by asynchronous XRayCore calls.
  • Removed time.sleep and polling loops - the service became faster and more responsive.
  • Logging and error handling have been improved.

Added an @app.on_event("shutdown") handler to ensure that the XRayCore is stopped cleanly when the FastAPI application shuts down. This prevents resource leaks and ensures proper termination of the XRay process.

These changes result in significant improvements in node performance and responsiveness, especially under load. The elimination of blocking operations allows FastAPI to efficiently handle requests and WebSocket connections.

The changes do not affect API backward compatibility.

TESTING HAS NOT BEEN CONDUCTED. Thorough testing is required.

- Replaces threading with asyncio for process management and log handling.
- Uses asyncio.subprocess for non-blocking process interaction.
- Adds an asyncio.Event for signaling Xray startup completion.
- Improves error handling and timeout management during startup, shutdown, and restart.
- Adds a separate task for processing logs and distributing them to clients.
- Cancels log processing task on shutdown to prevent resource leaks.
- Improved process termination with fallback to kill if necessary.
- Migrates Service class methods to be fully asynchronous.
- Introduces locks (`_conn_lock`, `_core_lock`) for thread-safe access to shared resources.
- Improves WebSocket log streaming with batching and error handling.
- Adds a shutdown event handler to stop XRayCore on application shutdown.
- Simplifies start/stop/restart logic using asyncio.
- Removes blocking `time.sleep` calls in favor of `asyncio.sleep`.
- Improved WebSocket connection management and graceful closure.
@x0sina
Copy link

x0sina commented Feb 13, 2025

Change target branch to dev

@ImMohammad20000
Copy link
Contributor

ImMohammad20000 commented Feb 13, 2025

Change target branch to dev

There is no dev branch in node

@fraybyl1
Copy link
Author

fraybyl1 commented Feb 13, 2025

It takes careful testing because the change is too big. Should gather some feedback before taking PR, I think.
I don't have the opportunity to test it unfortunately.

@ImMohammad20000
Copy link
Contributor

if you use a old marzban it raise an error

/.pyenv/versions/marzban/lib/python3.12/site-packages/urllib3/connection.py:463: SubjectAltNameWarning: Certificate for 172.21.117.3 has no `subjectAltName`, falling back to check for a `commonName` for now. This feature is being removed by major browsers and deprecated by RFC 2818. (See https://github.com/urllib3/urllib3/issues/497 for details.)

i cant test with ur pr

@fraybyl1
Copy link
Author

/.pyenv/versions/marzban/lib/python3.12/site-packages/urllib3/connection.py:463: SubjectAltNameWarning: Certificate for 172.21.117.3 has no subjectAltName, falling back to check for a commonName for now. This feature is being removed by major browsers and deprecated by RFC 2818. (See urllib3/urllib3#497 for details.)

Hmm. This is very strange. It's a normal warning that asks to generate a certificate with subjectAltName. But it should not throw an error. Apparently, because of the improved error handling, a long-standing problem has resurfaced. Now it needs to be jammed, but so far I can't figure out exactly where it's happening. Asking users to regenerate certificates is not an option. So we need to look for where the problem is occurring. Let me clarify the situation. Have you not updated the libraries? I'll try to figure it out tomorrow. But if you can figure out where exactly the exception is raised, that would be great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants