Why does the App engine (python3 - standard environment) generate aborted connections when connecting to a cloud sql -2nd Gen Mysql instance? - google-app-engine

I'm currently developing a project with python 3.7, Django 2.1, Mysql as database.
I'm deploying it in google cloud app engine standard environment and for the database I'm using a cloud SQL - MySql 2nd gen instance.
The application works well, however when I analyze the logs I see these errors:
"aborted connection - Got an error reading communication packets"
In this case the connection is being closed by my app (django).If I configure my app to have persistent connections and I put wait_timeout (i.e 60) in the config of the cloud sql, the error is:
"aborted connection - Got timeout reading communication packets".
I just determined that it's not a problem with sql cloud, or with the configuration of my application, but that it's an app engine problem. I came to this conclusion in the following way:
if I connect to the sql cloud instance through Mysql workbench, no connection is aborted
Similarly if I run my application on a local server, but connecting to cloud sql (through the cloud_sql_proxy), no error is generated and everything works perfect.
So my conclusion is that it is a problem of how the app engine connects to the cloud sql instance.
Why does this happen? How could it be solved?

The "Aborted connection" messages you're seeing, are usually triggered when a connection is closed improperly or there is a networking anomaly between the server and the client.
Sometimes Cloud SQL instances and GAE have long-live idle connections. In order to address this issue, it is recommended to set "wait_timeout' flag below 600 seconds - as you've already attempted to do so.
Another possible solution, is to implement application-level keepalives. SQLAlchemy provides “pre-ping” for this. Otherwise, generate activity on all open connections by sending a simple SQL statement such as "SELECT 1;" regularly, at least once every 5 minutes. Also consider using statements in your code like “with db.connect() as conn:” to control the connection’s lifetime.

I believe this is because requests from App Engine applications to Cloud SQL are subject to the following time and connection limits:
For apps running in the App Engine standard environment, all database requests must finish within the HTTP request timer, around 60 seconds. For apps running in the flexible environment, all database requests must finish within 60 minutes.
Offline requests like cron tasks have a time limit of 10 minutes.
Requests to Cloud SQL have limitations based on the scaling type of the App Engine module and how long an instance can remain in memory (residence).
Each App Engine instance running in a standard environment cannot have more than 60 concurrent connections to a Cloud SQL instance. For applications written in Java 8 or Go 1.8, the limit is 100.
Connection Issues: If you see errors containing "Aborted connection nnnn to db:", it usually indicates that your application is not terminating connections properly. It could also be caused by network issues. This error does not mean that there are problems with your Cloud SQL instance.

Related

Cloud SQL Connection Limits with Google APP Engine

Does anybody knows how can we use more than 12 concurrent connections from App Engine to the Cloud SQL?
We found that the documentation says:
"Each App Engine instance running in a standard environment cannot have more than 12 concurrent connections to a Google Cloud SQL instance."
We're using Java for App Engine using Hibernate... The connection pooling states that it shouldn't be used in production environment but if we disable the pooling we reach the max number of connections.
From Google Cloud FAQ: https://cloud.google.com/sql/faq#sizeqps
Google App Engine Limits
Requests from Google App Engine applications to Google Cloud SQL are subject to the following time and connection limits
For apps running in the Google App Engine standard environment, all database requests must finish within the HTTP request timer, around 60 seconds. For apps running in the flexible environment, all database requests must finish within 24 hours.
Offline requests like cron tasks have a time limit of 10 minutes.
Requests to Google Cloud SQL have limitations based on the scaling type of the App Engine module and how long an instance can remain in memory (residence).
Each App Engine instance running in a standard environment cannot have more than 12 concurrent connections to a Google Cloud SQL instance.

How to filter App Engine connections by host with Google Cloud SQL Second Generation? (2nd)

Google App Engine seems to automatically tunnel its connections to Cloud SQL 2nd generation internally through Cloud SQL Proxy. This was discovered inadvertently while trying to sort out how to use TLS, unsuccessfully: "TLS requested but server does not support TLS" error with Google Cloud SQL (2nd generation) from Google App Engine?
I noticed that this works without allowing unsecured access globally to the Cloud SQL instance... which is nice. However, we can only filter the accepted hostname for connections to cloudsqlproxy~% and not to localhost, and this allows virtually any "cloudsqlproxy" host to connect with the right credentials.
Is this safe and correct to do, and better than using %... which would obviously bypass any sort of host filtering? Or, does this open any cloudsqlproxy's possible connection to our 2nd generation instance?
The goal is to restrict connections on a particular user account on the SQL instance to ONLY come from our App Engine project. Nothing else should be able to connect with these credentials.
Good question, you are right that using cloudsqlproxy-% is the strictest filtering you can apply for App Engine connections right now and unfortunately that means you cannot effectively say "allow connections from App Engine but not from Cloud SQL Proxy".
It's hard to come up with a solution that maintains the consistency between App Engine Standard and App Engine Flexible since App Engine Flex VMs live in the customer project. It could be somewhat confusing if the restriction only applied to App Engine Standard, but not App Engine flex.
You can somewhat limit the exposure by limiting who can use the Cloud SQL Proxy by limiting the Editors (and owners) of a project as the account connecting using Cloud SQL Proxy must have Editor access or above. In the future, this will become more fine grained with IAM support.

"TLS requested but server does not support TLS" error with Google Cloud SQL (2nd generation) from Google App Engine?

I'm running into an issue in re-using my connection string (resolved here ... Cannot connect to Google Cloud SQL using SSL + Golang from Google App Engine ...) from connecting to a Google Cloud SQL generation one instance while trying to connect to a generation two instance. I'm receiving this error: TLS requested but server does not support TLS
I can't figure out how to get around this, and the documentation is pretty scarce.
I caught the fact that Instance connection name follows a different structure on generation two, but that doesn't seem like the issue. Has anyone solved this? I'm connecting from Golang.
MySQL level SSL is not currently supported between App Engine Standard Environment and Cloud SQL Second Generation instances.
Communication between App Engine Standard Environment and Cloud SQL is already encrypted so using MySQL level SSL does not add a lot of value, though I can understand that doing application level SSL can add some peace of mind since what happens between Cloud SQL and App Engine is opaque.
I'll try to see if this is something we can change.

Can't connect to Google Cloud 2nd Gen from GAE

I backed up my Cloud SQL V1 DB to a bucket and restored to a new 2nd-gen instance. Connecting via the console works fine. I can select, look at procs etc. Connecting to it from my Java GAE app doesn't. The GAE app and the Cloud SQL DB are in the same project.
I get these values in the logs:
GAE log:
java.sql.SQLInvalidAuthorizationSpecException: Not authorized to access instance: xxxx
SQL log:
[Warning] User 'root'#'%' was assigned access 0x1fffffff but was allowed to have only 0x1fff7dff.
Any tips?
Make sure your JDBC URL uses the jdbc:google:mysql:// prefix and not the old/deprecated jdbc:google:rdbms:// prefix.
While jdbc:google:rdbms:// continues to work for First Generation instances, it won't work when connecting to Second Generation instances. jdbc:google:mysql:// will work for both.

Communications link failure when connect to Google Cloud SQL(second gen) only from prod

Setting up a google cloud platform app with google cloud sql and for the life of me I cannot get a connection to the db when I run the code from google servers.
Following this example: https://cloud.google.com/appengine/docs/java/cloud-sql/?csw=1
I've gotten the non production url constructed properly and can connect with no issues to the cloud sql with this url
Class.forName("com.mysql.jdbc.Driver");
url = "jdbc:mysql://<ip-address>:3306/<database>?user=root";
So that's all good. This is the url I'm building for the prod connection.
Class.forName("com.mysql.jdbc.GoogleDriver");
url = "jdbc:google:mysql://<project-id>:<cloud sql instance name>/<database>?user=root";
I got the Project ID from the dashboard and the Instance ID SQL Instances List, database is the same as the non prod value and since non prod works I'm confident that's alright
Product and Instance ID locations I pulled them from
After deploying it all out I get the error message:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
appengine-web.xml does have use-google-connector-j set to true and I saw that for the second generation cloud sql you do not need to specify your app on the authorization list in cloud SQL.
Any help would be appreciated
https://cloud.google.com/sql/docs/dev-access#gaev1-csqlv2-connect
You should look at "instance connection name" in "Instance details" of your instance. For second generation, it's "project-id:region-name:cloud-sql-instance-name", not "project-id:cloud-sql-instance-name" as in the first generation.
When trying to connect to GCP SQL from google cloud run, do not forget to enable connection to GCP SQL from the google cloud run service level settings.
Having the setting disabled (default) can also cause the communications link faulure error.

Resources