2

I have used Redis version 2.6.66 and DotNet Core 6.0 in my project. The prject works well in the local but after deploying it on cloud.digitalocean.com I get an error.

How Can I solve it?

Error:

fail: API.Middleware.ExceptionMiddleware[0] No connection (requires writable - not eligible for replica) is active/available to service this operation: SETEX /api/products|pageIndex-1|pageSize-6|sort-name, mc: 1/1/0, mgr: 10 of 10 > StackExchange.Redis.RedisConnectionException: No connection (requires writable - not eligible for replica) is active/available to service this operation: SETEX /api/products|pageIndex-1|p> at StackExchange.Redis.ConnectionMultiplexer.ThrowFailed[T](TaskCompletionSource`1 source, Exception unthrownException) in /_/src/StackExchange.Redis/ConnectionMultiplexer.cs:line 1836 --- End of stack trace from previous location --- at Infrastructure.Services.ResponseCacheService.CacheResponseAsync(String cacheKey, Object response, TimeSpan timeToLive) in C:\Workspace\MainProjects\eshop\sigma-backend-dotnet\sigma> at API.Helpers.CachedAttribute.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) in C:\Workspace\MainProjects\eshop\sigma-backend-dotnet\sigma\API\He> at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope,> at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Obje> at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boo> at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context) at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) at API.Middleware.ExceptionMiddleware.InvokeAsync(HttpContext context) in C:\Workspace\MainProjects\eshop\sigma-backend-dotnet\sigma\API\Middleware\ExceptionMiddleware.cs:line 47

error

docker-compose configuration:

services:

  redis:
    image: redis:latest
    ports:
      - 6379:6379
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - redis-data:/data

  redis-commander:
    image: rediscommander/redis-commander:latest
    environment:
      - REDIS_HOSTS=local:redis:6379
      - HTTP_USER=XXX
      - HTTP_PASSWORD=YYY
    ports:
      - 8081:8081
    depends_on:
      - redis

    
volumes:
  redis-data:

Program.cs:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IConnectionMultiplexer>(c =>
{
    var configuration = ConfigurationOptions.Parse(builder.Configuration.GetConnectionString("Redis"), true);
    return ConnectionMultiplexer.Connect(configuration);
});

1 Answer 1

2

I deployed the project according to the instructions below:

Deploy to Linux using Docker - for use with .Net 6.0

  1. Create a new droplet with Digital Ocean using the Docker 19.03.12 on Ubuntu 20.04

IP address: Your IP address

Password for root user: YourPassword

  1. Login to the droplet using either the terminal or Powershell:

    ssh root@ipaddress

You will be asked for your password. Enter this.

  1. Create a new docker-compose file using the following command:

    sudo nano docker-compose.yml

  2. Copy and paste in the docker-compose configuration:

docker-compose

  1. Run the following command to start the docker services

    docker-compose up -d

  2. Install and configure apache by running the following commands:

    sudo apt update

    sudo apt install apache2

    a2enmod proxy proxy_http proxy_html rewrite

    systemctl restart apache2

    sudo ufw app list

    sudo ufw allow 'Apache Full'

    sudo systemctl status apache2

  3. Optional - allow the ports through the firewall to allow you to manage PostGreSQL and Redis via the ports.

sudo ufw allow 8080/tcp

sudo ufw allow 8081/tcp
  1. Test you can access the default apache page by browsing to: http://ipaddress

  2. Create a new directory that will contain our published dotnet app and assign rights to the user:

    sudo mkdir /var/skinet

    sudo chown -R $USER:$USER /var/skinet

  3. Create a new config file for the skinet app:

sudo nano /etc/apache2/sites-available/skinet.conf
  1. Paste in the following configuration which will set up a reverse proxy with the Kestrel server:
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5000
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
  1. Enable the skinet site by running the following commands:
a2ensite skinet

ls /etc/apache2/sites-enabled

a2dissite 000-default

systemctl reload apache2
  1. Install the deploy reloaded extension. Create a settings.json file in the .vscode directory and update the IP address and password for your server:
{
    "deploy.reloaded": {
        "packages": [
            {
                "name": "Version 1.0.0",
                "description": "Package version 1.0.0",

                "files": [
                    "publish/**"
                ]
            }
        ],

        "targets": [
            {
                "type": "sftp",
                "name": "Linux",
                "description": "SFTP folder",

                "host": "ipaddress", "port": 22,
                "user": "root", "password": "your password",

                "dir": "/var/skinet",
                "mappings": {
                    "publish/**": "/"
                }
            }
        ]
    }
}
  1. Optional - Change the logging level for the appsettings.json to information for the Microsoft logging level:
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Information",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
}
  1. Republish the app with changes by running the following command in VS Code terminal:
dotnet publish -c Release -o publish skinet.sln
  1. Deploy the files by using the command pallette -> deploy reloaded -> deploy package

  2. Add an endpoint to stripe for to point to the IP address of the server and select the 2 events we want to listen to: payment_intent.succeeded, payment_intent.payment_failed. Note the web hook MY_SECRET_PASSWORD as we will need this soon.

http://ipaddress/api/payments/webhook
  1. Back on the linux server create a service config for the kestrel server:
sudo nano /etc/systemd/system/skinet-web.service
  1. Update the configuration for your API keys where it says REPLACEME and then paste the config into the nano editor
[Unit]
Description=Kestrel service running on Ubuntu 20.04
[Service]
WorkingDirectory=/var/skinet
ExecStart=/usr/bin/dotnet /var/skinet/API.dll
Restart=always
RestartSec=10
SyslogIdentifier=skinet
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment='Token__Key=CHANGE ME TO SOMETHING SECURE'
Environment='Token__Issuer=http://REPLACEME'
Environment='StripeSettings__PublishibleKey=REPLACEME'
Environment='StripeSettings__SecretKey=REPLACEME'
Environment='StripeSettings__WhSecret=REPLACEME'
Environment='ConnectionStrings__DefaultConnection=Server=localhost;Port=5432;User Id=appuser;Password=MY_SECRET_PASSWORD; Database=skinet'
Environment='ConnectionStrings__IdentityConnection=Server=localhost;Port=5432;User Id=appuser;Password=MY_SECRET_PASSWORD; Database=identity'
Environment='ConnectionStrings__Redis=localhost'
Environment='ApiUrl=http://ipaddress/Content/'
[Install]
WantedBy=multi-user.target
  1. Install the .Net runtime using the instructions here: https://learn.microsoft.com/en-gb/dotnet/core/install/linux-ubuntu#2004-

  2. Restart the journal service by running the following command:

systemctl restart systemd-journald
  1. Start the kestrel service by running the following command:
sudo systemctl start skinet-web.service
  1. Check it is started by running:
netstat -ntpl
  1. Check the journal by running:
journalctl -u skinet-web.service --since "5 min ago"
  1. Make sure there are no errors and then test you can browse to the published app on http://ipaddress
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.