Health check failed when service is still running - python

I'm using google health check in order to send request to my flask client to make sure my service is alive.
the same route in flask client sends request to two more flask clients to make sure the other two is also alive.
For some reason the request sometimes fails when the service is still running.
I tries to figure out why but there is nothing in my services logs that indicates that something happened and on most cases it works fine.
This is my code:
#GET /health_check//
def get(self):
try:
for service in INTERNAL_SERVICES_HEALTH_CHECKS:
client = getattr(all_clients, service + '_client')
response = client.get('g_health_check')
except Exception, e:
sentry_client.captureMessage('health check failed for '+env+ ' environment. error log:' + repr(e))
return output_json({'I\'m Not fine!':False}, requests.codes.server_error)
return output_json({'I\'m fine!':True}, requests.codes.ok)
If anyone has any suggestions I will be happy to try and fix it.

Related

Getting Error 400 when sending GET request with json field from one Cloud Run to another

I am trying to send a request from one Cloud Run service to another. Both are running on Flask. My issue is that there is an email field that I need to send as part of the body of both PUT and GET requests. I know GET doesn't usually have a body but I need to send it this way. However I keep getting an Error 400 (Bad Request). It works fine when I run the services on my local machine but this error starts to appear when on Cloud Run. Please help me figure out if there is a configuration or something I can change to get this to work.
#bigbox_routing_bp.route("/variants/", methods=["GET"])
#secure(
scope=UserAccountType.INTERNAL,
resource_type=ResourceType.VARIANT,
permissions=[ProductPermissions.ALL, ProductPermissions.READ],
)
def get_variants():
regexMatch = re.match(f"(.*)({request.path})(.*)", request.url)
response = requests.get(
url=f"{BIGBOX_URL}{regexMatch.group(2)}{regexMatch.group(3)}",
json={"email": request.user.email},
)
return (response.json(), response.status_code)

Troubleshooting "Connection reset by peer"

I have a web api (Flask) and a mobile app (Xamarin.Forms) that uses it. Everything had been working well for a few months until a week ago. Suddenly mobile app clients started throwing "Connection reset by peer" when trying to access the web api. The exact exception message is:
Read error: ssl=0xd6269d18: I/O error during system call, Connection reset by peer
It seems to happen randomly - sometimes everything works well, sometimes not.
On the clients' side, requests are made using the System.Net.Http.HttpClient:
public async Task<string> GetClientData(string token)
{
HttpResponseMessage response =
await httpClient.GetAsync(server_url + Resx.Urls.get_route + "?token=" + token);
return await response.Content.ReadAsStringAsync();
}
The server is hosted on Heroku. Even when clients throw exceptions, the Heroku logs show that the requests were correctly handled (status 200).
An example route of my server:
#app.route('/get', methods=['GET'])
def get():
clients = get_users() # database call
token = request.args.get('token')
for c in clients:
if(c.token == token):
return c.to_json()
abort(400) # no client with such token
I wrote a short python script that tries to use the api the same way my mobile app does, and it seems that the problem does not occur there.
Where should I look for the solution? Is it more likely that something is wrong with the Flask server, or is it a problem with the mobile app?

GoneException when calling post_to_connection on AWS lambda and API gateway

I want to send a message to a websocket client when it connects to the server on AWS lambda and API gateway. Currently, I use wscat as a client. Since the response 'connected' is not shown on the wscat console when I connect to the server, I added post_to_connection to send a message 'hello world' to the client. However, it raises GoneException.
An error occurred (GoneException) when calling the PostToConnection
operation
How can I solve this problem and send some message to wscat when connecting to the server?
My python code is below. I use Python 3.8.5.
import os
import boto3
import botocore
dynamodb = boto3.resource('dynamodb')
connections = dynamodb.Table(os.environ['TABLE_NAME'])
def lambda_handler(event, context):
domain_name = event.get('requestContext',{}).get('domainName')
stage = event.get('requestContext',{}).get('stage')
connection_id = event.get('requestContext',{}).get('connectionId')
result = connections.put_item(Item={ 'id': connection_id })
apigw_management = boto3.client('apigatewaymanagementapi',
endpoint_url=F"https://{domain_name}/{stage}")
ret = "hello world";
try:
_ = apigw_management.post_to_connection(ConnectionId=connection_id,
Data=ret)
except botocore.exceptions.ClientError as e:
print(e);
return { 'statusCode': 500,
'body': 'something went wrong' }
return { 'statusCode': 200,
"body": 'connected'};
Self-answer: you cannot post_to_connection to the connection itself in onconnect.
I have found that the GoneException can occur when the client that initiated the websocket has disconnected from the socket and its connectionId can no longer be found. Is there something causing the originating client to disconnect from the socket before it can receive your return message?
My use case is different but I am basically using a DB to check the state of a connection before replying to it, and not using the request context to do that. This error's appearance was reduced by writing connectionIds to DynamoDB on connect, and deleting them from the table upon disconnect events. Messaging now writes to connectionIds in the table instead of the id in the request context. Most messages go through but some errors are still emitted when the client leaves the socket but does not emit a proper disconnect event which leaves orphans in the table. The next step is to enforce item deletes when irregular disconnections occur. Involving a DB may be overkill for your situation, just sharing what helped me make progress on the GoneException error.
We need to post to connection after connecting (i.e. when the routeKey is not $connect)
routeKey = event.get('requestContext', {}).get('routeKey')
print(routeKey) # for debugging
if routeKey != '$connect': # if we have defined multiple route keys we can choose the right one here
apigw_management.post_to_connection(ConnectionId=connection_id, Data=ret)
#nemy's answer is totally true but it doesn't explain the reason. So, I just want to explain...
So, first of all What is GoneException or GoneError 410 ?
A 410 Gone error occurs when a user tries to access an asset which no longer exists on the requested server. In order for a request to return a 410 Gone status, the resource must also have no forwarding address and be considered to be gone permanently.
you can find more details about GoneException in this article.
In here, GoneException has occured; it means that the POST connection we are trying to make, doesn't exist - which fits perfectly in the scenario. Because we still haven't established the connection between Client and Server. The way APIGatewayWebsocketAPIs work is that you request an Endpoint(Route) and that Endpoint will invoke that Lambda Function (In our case it is ConnectionLambdaFunction for $connect Route).
Now, if The Lambda function resolves with statusCode: 200 then and only then the API Gateway will allow the connection to be established. So, basically untill we return statusCode: 200 from our Lambda Function we are not connected and untill then we are totally unknown to server and thats why the Post call that has been made before the return statement itself will throw an error.

How to see if user is connected to internet or NOT?

I am building a BlogApp and I am stuck on a Problem.
What i am trying to do
I am trying to implement a feature that ,`If user is connected to internet then everything works fine BUT if user is not connected to internet then show a message like "You're not Connected to Internet".
What have i tried
I also tried channels but then i think internet connection are far away from Django-channels.
I also tried this :
url = "http://127.0.0.1:8000/"
timeout = 5
try:
request = requests.get(url, timeout=timeout)
print("Connected to the Internet")
except (requests.ConnectionError, requests.Timeout) as exception:
print("No INTERNET")
But it is keep showing me :
'Response' object has no attribute 'META'
I don't know what to do.
Any help would be Appreciated.
Thank You in Advance
It is not easy to know whether you're connected to the internet. In fact it is not even clear what this means. It depends a lot on the context.
In many practical cases it means, that your network setup is setup such, that you can access a DNS server and that you can access at least one machine on the internet.
You could just use one known url like for example "https://google.com" or "https://stackoverflow.com".
However this means that:
your test will fail if given service is for any reason down
you create requests to a server that isn't yours.
If you know, that the application should access your special web service, then you could use the url of your special web service:
url = "https://your_special_webservice.yourdomain"
Side information:
If you put the code in your question into a django view, that handles http requests, then you should probably write something like:
request = requests.get(url, timeout=timeout)
instead of
response = requests.get(url, timeout=timeout)
Otherwise you will overwrite the request object, of your django view
and this is probably what provoked your error message:
'Response' object has no attribute 'META'

Empty reply from Django web service

I have created a web service in django and its hosted on a shared server.The django web service respond to request from a game made in unity. But whenever game tries to request a django Web service url the server send empty resonse.Response is always:
WWW Error: server return empty string
The Unity webplayer expects a http served policy file named "crossdomain.xml" to be available on the domain you want to access with the WWW class, (although this is not needed if it is the same domain that is hosting the unity3d file).So I placed a file "crossdomain.xml" at the root of my domain ,but still i am getting same empty reply.Help plz...
EDIT:
I tried it through browser my service works fine and reply with proper response.And you know what My game can communicate to django web service when both are running on local machine.But now the django project is hosted on actual server and when game tried accessing service it never get response :(
url.py
urlpatterns = patterns('',
url(r'^crossdomain.xml$',views.CrossDomain),
url(r'^ReadFile/$',views.ReadFile),
)
views.py
def CrossDomain(request):
f = open(settings.MEDIA_ROOT+'jsondata/crossdomain.xml', 'r')
data = f.read()
f.close()
return HttpResponse(data, mimetype="application/xml")
def ReadFile(request):
f = open(settings.MEDIA_ROOT+'jsondata/some_file.json', 'r')
data = f.read()
f.close()
return HttpResponse(data, mimetype="application/javascript")
def Test(request):
return HttpResponse("Hello", mimetype="text/plain")
As I said using django for this is slight overkill because you could just serve them. Point aside though. If your serving on a different server it could be
A) Connection problems mean that your response is lost
B) Firewall issues mean that the request mean something
C) The server isn't setup correctly and therefore it justs get an error.
You need to test the response on the server. so is you access the page on the server through your browser. If so then make the game make a request and check the server error and access logs. In the apache access log you should see something like
GET "/url" 200 each time a request is made.
If you don't see any request getting through then either the request isn't made or its been lost.
If you do then the problem is in the code somewhere.

Categories