Openresty concurrent requests - multithreading

I would like to use OpenResty with Lua interpreter.
I can't make the OpenResty framework to handle two concurrent requests to two separate endpoints. I simulate that one request is doing some hard calculations by running in a long loop:
local function busyWaiting()
local self = coroutine.running()
local i = 1
while i < 9999999 do
i = i + 1
coroutine.yield(self)
end
end
local self = coroutine.running()
local thread = ngx.thread.spawn(busyWaiting)
while (coroutine.status(thread) ~= 'zombie') do
coroutine.yield(self)
end
ngx.say('test1!')
The other endpoint just sends response immediately.
ngx.say('test2')
I send a request to the first endpoint and then I send a second request to the second endpoint. However, the OpenResty is blocked by the first request and so I receive both responses almost at the same time.
Setting nginx parameter worker_processes 1; to higher number does not help either and I would like to have only single worker process anyway.
What is the proper way to let OpenResty handle additional requests and not to get blocked by the first request?

local function busyWaiting()
local self = ngx.coroutine.running()
local i = 1
while i < 9999999 do
i = i + 1
ngx.coroutine.yield(self)
end
end
local thread = ngx.thread.spawn(busyWaiting)
while (ngx.coroutine.status(thread) ~= 'dead') do
ngx.coroutine.resume(thread)
end
ngx.say('test1!')

Related

Why does transact and wait behave differently when within a function is behaving different?

Within my project I intend to send large volumes of transactions therefore for simplicity I am building a wrapper function for the following functions to be executed together: contractName.functions.functionName(params).transact() and w3.eth.wait_for_transaction(tx_hash). However when I write the functions transact_and_wait with the above implemented within in the transactions do not get executed!
Implementation of Transact and wait
def transact_and_wait(contract_function, transaction_params= {"gas": 100000}):
# Send the transaction
if transaction_params != {"gas": 100000}:
transaction_params["gas"] = 100000
transaction_hash = contract_function.transact(transaction_params)
# Wait for the transaction to be mined
transaction_receipt = w3.eth.wait_for_transaction_receipt(transaction_hash)
return transaction_receipt
Where it is called via: Transact_and_wait(contractName.functions.functionName(account.address))
For example this should set the a role for a user defined via index 1
However when I call. print(contractName.functions.stateVariable(account.address).call()) it returns 0
If i do the same process above but not within a functions:
tx_hash = contractName.functions.functionName(account.address).transact({"gas": 100000}))
transaction_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
Then I can call the same getter: print(contractName.functions.stateVariable(account.address).call()
It returns 1.

how to include a sleep function in Yew app?

I am trying to build small application with Yew (Rustwasm) . I would like to put sleep function in Yew app.when I use use std::thread::sleep , I am getting below error
I am using sleep as below
let mut index = 0;
sleep(Duration::new(1, 0));
if col < 3 {
index = row * 4 + (col + 1);
if self.cellule[index].value == 1 {
sleep(Duration::new(1, 0));
wasm.js:314 panicked at 'can't sleep', src/libstd/sys/wasm/thread.rs:26:9
Stack:
Error
at imports.wbg.__wbg_new_59cb74e423758ede (http://127.0.0.1:8080/wasm.js:302:19)
at console_error_panic_hook::hook::hd38f373f442d725c (http://127.0.0.1:8080/wasm_bg.wasm:wasm-function[117]:0x16a3e)
at core::ops::function::Fn::call::hf1476807b3d9587d (http://127.0.0.1:8080/wasm_bg.wasm:wasm-function[429]:0x22955)
at std::panicking::rust_panic_with_hook::hb07b303a83b6d242 (http://127.0.0.1:8080/wasm_bg.wasm:wasm-function[211]:0x1ed0d)
at std::panicking::begin_panic::h97f15f2442acdda4 (http://127.0.0.1:8080/wasm_bg.wasm:wasm-function[321]:0x21ee0)
at std::sys::wasm::thread::Thread::sleep::hdd97a2b229644713 (http://127.0.0.1:8080/wasm_bg.wasm:wasm-function[406]:0x22829)
The methods like thread::sleep doesn't work, because in the JS environment you have a single thread only. If you call that sleep you will block the app completely.
If you want to use an interval you should "order" a callback. You can check the following example how to use TimeoutService or IntervalService for that: yew/examples/timer
The core idea to create a service this way:
let handle = TimeoutService::spawn(
Duration::from_secs(3),
self.link.callback(|_| Msg::Done),
);
// Keep the task or timer will be cancelled
self.timeout_job = Some(handle);
Now you can use handler of Msg::Done to react to that timer elapsed.
Threads are actually available, but it's a complex topic and you have to use Web Workers API reach them. Anyway it's useless for your case. Also there are some proposals in standards, but they aren't available in the browsers yet.

Websocket client not receiving data

I have a weird issue. After reading about websocket-client, it seems easy enough, send data via websocket.send() and receive via recv().
I have setup my websocket to read and send a binary file. The codes are below
ws = websocket.WebSocket()
ws.connect(uri)
text_list = list()
# setup the receiving portion
receiving_tread = threading.Thread(target=thread_receiving, args=(ws, text_list))
receiving_tread.start()
ws.send_binary([48]) # telling server file has started
f = open(binary_file, 'rb')
chunk = f.read(8000)
while chunk != b'':
ws.send(chunk)
time.sleep(0.5)
chunk = f.read(8000)
ws.send_binary([49]) # tell server file has ended
The process to receive the data:
def thread_receiving(ws, text_list):
data = json.loads(ws.recv())
text_list.append(data)
I know the data gets sent because I get the first part of the data returned, then it stops. So I get only 1 return and somehow the recv() stops listening. Note: I have no access to the server or the server websocket so I have to troubleshoot from the client side.
Can anyone tell me, what it is I'm doing wrong?
Okay, I've found the answer, it seems that the receiving function exits after it runs. So we need to keep it running.
Therefore,
def thread_receiving(ws, text_list):
data = json.loads(ws.recv())
while len(data) > 0
text_list.append(data)
data = json.loads(ws.recv())

Gunicorn is not rejecting connections over backlog limit

In gunicorn app, I need to allow only certain number of connections and reject the rest with error. I have this testing config:
timeout = 60
graceful_timeout = 60
workers = 1
worker_connections = 1
backlog = 1
worker_class = "gevent"
max_requests = 1000
max_requests_jitter = 42
preload_app = True
bind = "0.0.0.0:8080"
loglevel = "debug"
accesslog = "-" # Send access log to stdout.
which I expected should result in accepting only one connection at a time and rejecting the rest. But when I send multiple requests at once, they are queued and processed one by one. For testing purposes, it takes 10 seconds to process one request to make sure there is one active connection.
Using gunicorn version 19.9.0

Using Socket and Threads Why Is my Chat Server so Slow and CPU Usage so High?

So my code works fine except for when iterating through arrays and sending a response to multiple chat clients the latency between each client's reception of the response is nearly a second. I'm running the server and client on my computer so there shouldn't be any real latency, right? I know ruby isn't this slow. Also, why does my computer's fan spin up when running this? There's a bit more if it would be helpful to include it.
# Creates a thread per client that listens for any messages and relays them to the server viewer and all the other clients.
create_client_listener_threads = Thread.new do
x = nil
client_quantity = 0
# Loops indefinitely
until x != nil
#Checks to see if clients have joined since last check.
if #client_join_order_array.size > client_quantity
# Derives number of new arrivals.
number_of_new_arrivals = #client_join_order_array.size - client_quantity
# Updates number of clients in client_quantity.
client_quantity = #client_join_order_array.size
if number_of_new_arrivals != 0
# Passes new arrivals into client for their thread creation.
#client_join_order_array[-1 * number_of_new_arrivals..-1].each do |client|
# Creates thread to handle receiving of each client's text.
client_thread = Thread.new do
loop do
text = client.acception.gets
# Displays text for server viewer.
puts "#{client.handle} # #{Time.now} said: #{text}"
#client_hash.each_value do |value|
if value.handle != client.handle
# Displays text for everyone except server viewr and person who spoke.
value.acception.puts "#{client.handle} # #{Time.now} said: #{text}"
end
end
end
end
end
end
end
end
end
Instead of testing if #client_join_order_array.size > client_quantity, and doing nothing except smoke the CPU if it is false, you should be accepting the new connection at this point, and blocking until there is one. In other words move the code that accepts connections and adds them to the array here.

Resources