Azure webapp to elasticsearch, sometimes "A connection attempt failed" on azure - azure

I have a web app and a elasticsearch cluster inside a virtiual network.
The web app is on one azure catalog and the elasticsearch cluster on another catalog/subscription. I cannot have them in the same catalog because of bizspark subscription rules (5 accounts $150 each).
Due to this I cannot have the web app connected to the virtual network with Point to site as I can understand.
Therefore I have opened traffic in the virtual network firewall for port 9200. And it works great to index and search in the web app which is connected to elasticsearch cluster. But only sometimes?!
Now and then I get this error:
A connection attempt failed because the connected party did not
properly respond after a period of time, or established connection
failed because connected host has failed to respond x.x.x.x:9200
I also get this error sometimes from my web job which is in the same webb app.
Are there something that is blocking my connection to elasticsearch?
If I change plan for my web app (e.g. Standard S1 to S1 or vice versa) it starts to work again. But then after a while I get blocked gain.

As Martin Laarman wrote. The SetTcpKeepAlive was the problem.
NEST has implemented this in their ConnnectionConfiguration with the method EnableTcpKeepAlive().
I don't know what parameters call EnableTcpKeepAlive. The values i set for now seems to work ok.
public static ElasticClient ElasticClient
{
get
{
var uri = new Uri(ConfigurationManager.AppSettings["ElasticSearchUrl"]);
var setting = new ConnectionSettings(uri);
setting.SetDefaultIndex("myIndex");
var connectionConfiguration = new ConnectionConfiguration(uri);
connectionConfiguration.EnableTcpKeepAlive(200000, 200000);
var client = new ElasticClient(setting, new HttpConnection(connectionConfiguration));
return client;
}
}
In version 7.13.0 of NEST, EnableTcpKeepAlive is on the settings object:
var settings = new ConnectionSettings(url);
settings.EnableTcpKeepAlive(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(1));
client = new ElasticClient(settings);

Related

High Availability on Azure database for Postgres

As per document https://learn.microsoft.com/en-us/azure/postgresql/concepts-high-availability
for any failure/service down , automatically new service will deployed and re attach the storage to new server.
new service with same hostname/ip address or different.if it is different,how can we achieve same hostname because we can't change the connection string in application
What you are asking for is answered in the document you linked.
Applications using the PostgreSQL databases need to be built in a way that they detect and retry dropped connections and failed transactions. When the application retries, the Gateway transparently redirects the connection to the newly created database server.

azure connection issue using sql

I am using Azure SQL DB and asp.net web application running on azure app service . I registered application in Azure AD. I am using Active directory integrated security to connect to SQL. And, I am using ADO.net entity framework.
SQL connection string is
All the app service outbound ips are added in SQl server firewall settings.
When I run the application locally (localhost), the app able to connect to SQL with no errors.
I tried building connection string using SqlConnectionStringBuilder. I am facing the same issue.
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder["Data Source"] = "dbname.windows.net";
builder["Initial Catalog"] = "dbname";
builder["Connect Timeout"] = 15;
builder.Authentication = SqlAuthenticationMethod.ActiveDirectoryIntegrated;
I also tried adding connection strings in App service -> Application settings -> connection strings with SqLClinet and Custom but still no use.
Please let me know what I missed to successfully connect to Azure SQL from AppService.

How to get correct WSDL URL when hosting a WCF service behind an Azure Application Gateway?

We are in the process of migrating services from on-premise to Azure, and we are now hosting a legacy WCF service an Azure App Service. To make it backwards compatible with existing clients, it needs to be available through {domainNameHere}.com/services.
There are also other services that should be accessible through the same domain, for example {domainNameHere}.com/api. We have set up an Azure Application Gateway to route requests to different App Services based on the request paths, and have set {domainNameHere}.com to point to the Application Gateway IP.
This works well for all the services except for the WCF service. It is accessible in the browser at https://{domainNameHere}.com/services/exports.svc, but the WSDL URIs at that page shows the azurewebsites.net URIs instead of our custom domain. When clients attempt to access the service, they get the following error:
System.ServiceModel.EndpointNotFoundException:
'There was no endpoint listening at https://{domainNameHere}.com/services/export.svc
that could accept the message. This is often caused by an incorrect address or SOAP
action. See InnerException, if present, for more details.'
Inner Exception
WebException: The remote server returned an error: (404) Not Found.
We have tried to use useRequestHeadersForMetadataAddress in the WCF config to no avail.
Here is the WCF configuration, all in code. The endpoint URI is https://{domainNameHere}.com/services/exports.svc.
public static void Configure<T>(ServiceConfiguration config, Uri endpoint) where T : class
{
// Configure service behavior
config.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true, HttpsGetEnabled = true });
config.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });
var serviceCredential = config.Description.Behaviors.Find<ServiceCredentials>();
if (serviceCredential == null)
{
serviceCredential = new ServiceCredentials();
config.Description.Behaviors.Add(serviceCredential);
}
serviceCredential.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
serviceCredential.UserNameAuthentication.CustomUserNamePasswordValidator = new CredentialsValidator();
config.AddServiceEndpoint(typeof(T), GetBinding(), endpoint);
}
I finally figured it out. The Application Gateway made requests to the WCF service using HTTP, but the WCF service only replied on HTTPS. As soon as I updated the Application Gateway to make requests using HTTPS it was working as expected.

Can't connect to Azure SQL Database from Azure Container Instances

I've built a Windows container with my app inside and ran it locally. The app in the container connects to an Azure SQL Database, using the domain name from the connection string. SQL Server is configured to accept clients from any IP and from Azure Services.
Everything works fine locally. But when I run my container in Azure Container Instances, I get the following standard error:
A network-related or
instance-specific error occurred while establishing a connection to SQL
Server. The server was not found or was not accessible. Verify that the
instance name is correct and that SQL Server is configured to allow remote
connections. (provider: TCP Provider, error: 0 - A connection attempt failed
because the connected party did not properly respond after a period of time,
or established connection failed because connected host has failed to
respond.)
You need to create a managed identity https://learn.microsoft.com/en-us/azure/container-instances/container-instances-managed-identity and grant that identity permission to the SQL database.
You can then use the Microsoft.Azure.Services.AppAuthentication library to get an access token and use it during authentication. This is only available in dotnetcore 2.2 and .net 4.6 and above.
string connectionString = "Data Source=<AZURE-SQL-SERVERNAME>; Initial Catalog=<DATABASE>;";
SqlConnection conn = new SqlConnection(connectionString);
conn.AccessToken = (new AzureServiceTokenProvider()).GetAccessTokenAsync("https://database.windows.net/").Result;
conn.Open();
More info can be found in the below links. None of them are explicitly for ACI but it should be basically the same from a code perspective once you have created the MSI.
https://learn.microsoft.com/en-us/azure/key-vault/service-to-service-authentication
https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/tutorial-windows-vm-access-sql
https://learn.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi
I've experienced a similar issue with a Windows container in ACI trying to connect to an Azure SQL database. For some reason, DNS was not working inside the container. I could not resolve any public DNS names. Inside the container, DNS was pointed to a 10.x.x.x address. I never set this as part of the image build so I assume ACI is setting this as part of DHCP.
To fix this I ran the following as part of my PowerShell entrypoint script:
$nic = Get-NetAdapter
Set-DnsClientServerAddress -InterfaceIndex $nic.IfIndex -ServerAddresses ('1.1.1.1','8.8.8.8')

Azure Relay - Hybrid connection reuse

Creating new HybridConnectionStream object like below, for every client request thread takes time (~3sec)
var client = new HybridConnectionClient(new Uri(String.Format("sb://{0}/{1}", relayConfiguration.Value.RelayNamespace, relayConfiguration.Value.ConnectionName)), tokenProvider);
-- (takes ~3 secs)
HybridConnectionStream relayConnection= await client.CreateConnectionAsync();
Is there any way out to reuse/cache already established HybridConnectionStream to serve all future request of same client or possible to create pool of HybridConnectionStream to cater future client request faster.
Our implementation as follows: Some user action on mobile app requires data from on premises DB, so the user action hits azure hosted service fabric api which in turn forward the request to specific azure relay hybrid connection then our custom, on premise hosted listener service pick the request & forward it to on premises web service to pick data Here the service fabric app creates NEW hybridconnection/hybridconnectionstream to establish connection with azure relay hybrid connection for each & every incoming user request which is time consuming & we want to avoid new hybridconnection creation everytime instead looking for options to cache & reuse already created costly hybridconnection or trying to create hybridconnection pool kind of thing. please advice if it is possible or suggest something else which is even better. Thanks
We use hybrid connections between one of our App Services and one of several VMs. An Azure hybrid connection is kind of like a VPN. (You have to tilt your head and squint just right.)
Within App Service, Hybrid Connections can be used to access application resources in other networks. Source: Azure App Service Hybrid Connections
So I think you should look at a hybrid connection as something persistent. It's part of your network infrastructure, not something you need to create for each thread. I think the amount of time it takes to create a hybrid connection is in line with that kind of thinking.
Just keep the HybridConnectionStream open and reuse it. Do not close it when you still need it. You can send multiple messages over a single stream. It is read / write so should not be a problem.

Resources