Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I found that making requests to our web role after periods on inactivity would result in a very slow request (up to 30 seconds). After that initial request, the role would perform as it should.
After much Googling, I came across four different strategies (listed below):
(a) Disabling IIS idle timeout in RoleEntryPoint.OnStart()
public override bool OnStart()
{
using (var server = new ServerManager())
{
server.ApplicationPoolDefaults.ProcessModel.IdleTimeout = TimeSpan.Zero;
server.CommitChanges();
}
return base.OnStart();
}
This also requires that the role runs at an elevated level.
(b) Perform regular requests in the RoleEntryPoint.Run()
public override void Run()
{
var localuri = new Uri(string.Format("https://{0}/Help", RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["HttpsIn"].IPEndpoint));
while (true)
{
try
{
var request = (HttpWebRequest)WebRequest.Create(localuri);
request.Method = "GET";
var response = request.GetResponse();
}
catch { }
System.Threading.Thread.Sleep(3000);
}
}
(c) Set preloadEnabled and startMode in the RoleEntryPoint.OnStart()
public override void OnStart()
{
using (var serverManager = new ServerManager())
{
foreach (var application in serverManager.Sites.SelectMany(x => x.Applications))
{
application["preloadEnabled"] = true;
}
foreach (var applicationPool in serverManager.ApplicationPools)
{
applicationPool["startMode"] = "AlwaysRunning";
}
serverManager.CommitChanges();
}
return base.OnStart();
}
(d) And lastly, using Azure's "Always On" (EDIT: This is only for Azure websites unfortunately!)
Which of these strategies should I perform?
We use a combination of a couple of those answers and it works perfectly well for us, they're very quick to change and test however, it seems to cover all bases.
public override bool OnStart()
{
ServicePointManager.DefaultConnectionLimit = 12;
if(!RoleEnvironment.IsEmulated)
{
using(ServerManager serverManager = new ServerManager())
{
foreach (var app in serverManager.Sites.SelectMany(x => x.Applications))
{
app["preloadEnabled"] = true;
}
foreach (var appPool in serverManager.ApplicationPools)
{
appPool.AutoStart = true;
appPool["startMode"] = "AlwaysRunning";
appPool.ProcessModel.IdleTimeout = TimeSpan.Zero;
appPool.Recycling.PeriodicRestart.Time = TimeSpan.Zero;
}
serverManager.CommitChanges();
}
}
return base.OnStart();
}
Have you considered using the Azure endpoint monitoring to both monitor and trigger your role to respond every 5 minutes? It's built into Azure and there's no code needed.
http://azure.microsoft.com/en-us/documentation/articles/web-sites-monitor/
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 days ago.
Improve this question
I am working on a amazon based web services where i have to send and receive some information to Amazon IOT and then receive some message from there. I have problem in connecting to IOT , can any one help me with MQTT and IOT.
Try this. it may help you.
credentialsProvider = new CognitoCachingCredentialsProvider(
getApplicationContext(), // context
COGNITO_POOL_ID, // Identity Pool ID
MY_REGION // Region);
Region region = Region.getRegion(MY_REGION);
// MQTT Client
mqttManager = new AWSIotMqttManager(clientId, CUSTOMER_SPECIFIC_ENDPOINT);
// Set keepalive to 10 seconds. Will recognize disconnects more quickly but will also send
// MQTT pings every 10 seconds.
mqttManager.setKeepAlive(10);
mIotAndroidClient = new AWSIotClient(credentialsProvider);
mIotAndroidClient.setRegion(region);
try {
mqttManager.connect(clientKeyStore, new AWSIotMqttClientStatusCallback() {
#Override
public void onStatusChanged(final AWSIotMqttClientStatus status,
final Throwable throwable) {
Log.d(LOG_TAG, "Status = " + String.valueOf(status));
runOnUiThread(new Runnable() {
#Override
public void run() {
if (status == AWSIotMqttClientStatus.Connecting) {
} else if (status == AWSIotMqttClientStatus.Connected) {
tvStatus.setText("Connected");
} else if (status == AWSIotMqttClientStatus.Reconnecting) {
if (throwable != null) {
Log.e(LOG_TAG, "Connection error.", throwable);
}
tvStatus.setText("Reconnecting");
} else if (status == AWSIotMqttClientStatus.ConnectionLost) {
if (throwable != null) {
Log.e(LOG_TAG, "Connection error.", throwable);
}
}
}
});
}
});
} catch (final Exception e) {
}
I'm using the Db property in a ServiceStack service to access my database but every now and then I get the following error from IIS:
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
Stack Trace:
[InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.]
System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) +6371713
System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) +6372046
System.Data.SqlClient.SqlConnection.Open() +300
ServiceStack.OrmLite.OrmLiteConnection.Open() +44
ServiceStack.OrmLite.OrmLiteConnectionFactory.OpenDbConnection() +132
ServiceStack.ServiceInterface.Service.get_Db() +68
I have set the ReuseScope in the Configure method to ReuseScope.None which should close the connection on a per request basis I believe? What am I doing wrong here?
public override void Configure(Container container)
{
JsConfig.EmitCamelCaseNames = true;
//Register all your dependencies
ConfigureDb(container);
//Set MVC to use the same Funq IOC as ServiceStack
ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
}
ConfigureDb:
private static void ConfigureDb(Container container)
{
var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider))
.ReusedWithin(ReuseScope.None);
using (var db = container.Resolve<IDbConnectionFactory>().Open())
{
// Do database seed/initialisation
}
}
Edit
After more diagnosis, it seems to happen when I refresh the page several times when I call this service method:
public Warranty Get(Warranty request)
{
var warranty = new Warranty();
if (request.Id != default(int))
{
warranty = Db.Id<Warranty>(request.Id);
warranty.WarrantyOrder = ResolveService<WarrantyOrderService>().Get(new WarrantyOrder { WarrantyId = warranty.Id });
warranty.WarrantyStatus = ResolveService<WarrantyStatusService>().Get(new WarrantyStatus { Id = warranty.StatusId });
warranty.WarrantyNotes = ResolveService<WarrantyNoteService>().Get(new WarrantyNotes { WarrantyId = warranty.Id });
warranty.WarrantyDialogues = ResolveService<WarrantyDialogueService>().Get(new WarrantyDialogues { WarrantyId = warranty.Id });
warranty.WarrantyCredit = ResolveService<WarrantyCreditService>().Get(new WarrantyCredit { WarrantyId = warranty.Id });
warranty.WarrantyPhotos = ResolveService<WarrantyPhotoService>().Get(new WarrantyPhotos { WarrantyReference = warranty.WarrantyReference });
warranty.WarrantyReport = ResolveService<WarrantyReportService>().Get(new WarrantyReport { WarrantyId = warranty.Id });
}
return warranty;
}
I have changed ConfigureDb as per #mythz answer below:
private static void ConfigureDb(Container container)
{
var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;
container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider));
}
The service needs to call out other services to populate the other objects on my Warranty object, I'm not sure on how to improve this?
The IDbConnectionFactory like all connection managers is a thread-safe factory to create DB Connections, i.e. it's not a DB connection itself. It is supposed to be registered as a singleton.
By default ServiceStack's IOC (Funq) registers as a Singleton by default, so the correct registration is just:
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider));
Resolving Services
As ServiceStack Services have the potential to utilize managed resources, they should be used within a using statement whenever they're resolved from another service, so that they're appropriately disposed of, e.g:
using var orders = ResolveService<WarrantyOrderService>();
using var status = ResolveService<WarrantyStatusService>();
var warranty = new Warranty {
WarrantyOrder = orders.Get(new WarrantyOrder { WarrantyId = warranty.Id }),
WarrantyStatus = status.Get(new WarrantyStatus {
WarrantyId = warranty.StatusId }),
//etc
}
return warranty;
I am attempting to write a Validation attribute in MVC4.
The purpose is to check for the existence of an application reference (just a string that represents a key I wish to prevent a duplicate for).
My data is accessed via WebAPI and because I am using 4.5 I wish to make this asynchronous if possible.
I am perhaps not making the best or appropriate usage of async and await but I would like to know how to call my async method from the overridden IsValid method of the inherited Validation class.
public class UniqueApplicationReferenceAttribute : ValidationAttribute
{
public UniqueApplicationReferenceAttribute() : base(() => "The {0} already exists") { }
public int? ApplicationCount { get; set; }
public override bool IsValid(object value)
{
var myTask = GetApplicationRefCountAsync();
myTask.Wait();
this.ApplicationCount = this.ApplicationCount ?? 0;
if (ApplicationCount > 0)
{
return true;
}
else
{
return false;
}
}
public async Task GetApplicationRefCountAsync()
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:11111/");
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var apps = client.GetStringAsync("api/dataapplications");
await Task.WhenAll(apps);
var appList = apps.Result;
this.ApplicationCount = appList.Count();// apps.Count();
}
}
Many thanks,
Dan.
I recommend that you call your WebAPI methods synchronously. ValidationAttribute does not support asynchronous implementations natively, so any synchronous-over-asynchronous code you'll write is just going to be a hack and not actually provide any benefit as compared to the synchronous version.
I'm not able to test this in full, but you should be able to do something like this:
public bool IsValid(object value)
{
var appCount = GetApplicationRefCountAsync().Result;
return appCount > 0;
}
public async Task<int> GetApplicationRefCountAsync()
{
var client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:11111/");
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
return await client.GetStringAsync("api/dataapplications")
.ContinueWith(r => Convert.ToInt32(r))
.ConfigureAwait(false);
}
Be careful about using async/await methods in an ASP.NET thread. It's easy to create deadlocks.
I want every to hour restart windows service by c# code. I have this method
but when I but it in project installer or where? Can I put it in the same service I want to restart it?
public static void RestartService(string serviceName, int timeoutMilliseconds)
{
ServiceController service = new ServiceController(serviceName);
try
{
int millisec1 = Environment.TickCount;
TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
// count the rest of the timeout
int millisec2 = Environment.TickCount;
timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds - (millisec2 - millisec1));
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running, timeout);
}
catch
{
// ...
}
}
i solved it by making a method inside the service like this
private void StopService()
{
using (ServiceController service = new ServiceController("ServiceName"))
{
try
{
TimeSpan timeout = TimeSpan.FromMilliseconds(80000);
if (!(service.Status.Equals(ServiceControllerStatus.StartPending) || service.Status.Equals(ServiceControllerStatus.StopPending)))
{
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
}
}
catch (Exception ex)
{
ExceptionLog(ex);
}
}
}
and make another service to restart it
You could add this to the Windows scheduler. Just put this function in a windows command program and schedule hourly launch of it. Also, you could have a second service to accomplish the recycling of the first service.
-rwg
I'm creating a timer Job. And i have to access some lists which are in my solution stored in the site : "http://server:9090/sites/thesite"
For the moment, in my Timer Job i use this :
SPWebApplication webApplication = this.Parent as SPWebApplication;
SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId];
SPList ParametresTech = contentDb.Sites["sites/thesite"].RootWeb.Lists[Constantes.Listes.PARAMETRES_TECHNIQUES.Name];
The problem i'm facing here is that i'm in my development environnement, and i don't know what will be the url of the site they will use to deploy the solution in production.
So is there a way to get to the list without knowing the name of the site ?
Thanks
EDIT :
That's how the timer job is activated :
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
string ListJobName = "SAPToSQL";
SPSite site = properties.Feature.Parent as SPSite;
// make sure the job isn't already registered
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
{
if (job.Name == ListJobName)
job.Delete();
}
// install the job
TimerJobSAPToSP listLoggerJob = new TimerJobSAPToSP(ListJobName, site.WebApplication);
SPHourlySchedule schedule = new SPHourlySchedule();
schedule.BeginMinute = 0;
schedule.EndMinute = 59;
listLoggerJob.Schedule = schedule;
listLoggerJob.Update();
}
I would definitely identify the site collection using the feature ID that creates the timer job rather than by URL. Not only does this give you flexibility in naming sites, it also allows you to process multiple site collections that have each subscribed to the job.
I wrote the following utility method to collect the site collections for a timer job:
public static List<Guid> GetSiteIDs(SPWebApplication webApplication, Guid featureId)
{
List<Guid> ids = new List<Guid>();
foreach (SPSite site in webApplication.Sites)
{
try
{
if (SPSite.Exists(new Uri(site.Url))
&& null != site.Features[featureId])
{
try
{
ids.Add(site.ID);
}
catch (Exception ex)
{
// Handle Exception
}
}
}
finally
{
site.Dispose();
}
}
return ids;
}
In the featureId parameter, I pass a constant that I declare in my job definition class.
For more information see: Scope of a feature activated Custom Sharepoint-Timer Job