Azure / app-service-linux-docs

Azure App Service: Frequently Asked Questions on Linux App Service
Creative Commons Attribution 4.0 International
139 stars 79 forks source link

Deploy gRPC app on App Service with Rest api endpoint #144

Open LindaLawton opened 1 year ago

LindaLawton commented 1 year ago

I have been following How-to deploy a .NET 6 gRPC app on App Service

When I add this to my project it breaks everything else in the project, swagger wont even load anymore let alone all of the other rest api endpoints, everything is returning connection refused.

builder.WebHost.ConfigureKestrel(options => 
{ 
    options.ListenAnyIP(8080); 
    options.ListenAnyIP(8585, listenOptions => 
    { 
        listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2; 
    }); 
});

Is it possible to mix gRPC and rest api end points in the same project?

Stackoverflow: Mixing Rest api endpoints with grpc on azure app services in the same project. ECONNREFUSED Issue forum: Deploy gRPC app on App Service with Rest api endpoint Microsofft: deploy a .NET 6 gRPC app on App Service -Error starting gRPC call

crosenblatt commented 1 year ago

Hi Linda, Yes, it should be possible to have rest api endpoints as well as gRPC endpoints in the same project in .NET 6. Do you have a minimal repro that demonstrates how this breaks? Would love to help take a look.

As far as getting it to work in App Service, double check the following:

  1. In portal, check the Http Version is "2.0" and Http 2.0 Proxy is turned "On"
  2. Check that the appsetting HTTP20_ONLY_PORT is set to 8585
  3. Ensure the deployed App Service is a Linux app.
LindaLawton commented 1 year ago

would you mind clarifying what you mean by nr 2? the guild doesn't mention anything about appsettings.

LindaLawton commented 1 year ago

@crosenblatt does this mean anything to you

1:08 Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: The SSL connection could not be established, see inner exception. AuthenticationException: Authentication failed because the remote party sent a TLS alert: 'ProtocolVersion'. Win32Exception: The message received was unexpected or badly formatted.",

crosenblatt commented 1 year ago

The docs do mention to set an app setting specifying the Http20 port your app exposes. From the docs:

3. Add HTTP20_ONLY_PORT application setting

Earlier, we configured the application to listen to a specific HTTP/2 only port. Here we'll add an app setting HTTP20_ONLY_PORT and put the value as the port number we used earlier.

  1. Navigate to the Configuration under Settings on the left pane of your web app.
  2. Under Application Settings, click on New application setting
  3. Add the following app setting to your application
    1. Name = HTTP20_ONLY_PORT
    2. Value = 8585

This setting will communicate to your web app which port is specified to listen over HTTP/2 only.

As for the SSL error, would it be possible to post a code snippet showing how you are calling out to the app? Two things I can think of are: 1. You may be trying to create the gRPC channel with http:// rather than https://, which would not be allowed, or 2. You may need to add validation to check the certificate that is returned depending on the client stack.

LindaLawton commented 1 year ago

I need my clients permission before I can share the code. The thing is this all works locally. When we upload it to web apps it works without grpc as soon as i include the code for grpc it fails with the ssl error.

I have added the code exactly as is in the article

builder.WebHost.ConfigureKestrel(options => 
{ 
    //options.ListenAnyIP(8080); 
    options.ListenAnyIP(8585, listenOptions => 
    { 
        listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2; 
    }); 
});

If i remove all of the grpc section the Rest api endpoints work. As soon as i add it back webapps wont even start. we don't even get a healthz check endpoint.

crosenblatt commented 1 year ago

You are not commenting out the 8080 endpoint correct? That is necessary to keep. A few more things to verify:

Is this .NET 6 or some other version of .NET? Did you comment out the section in appsettings.json?

If you can get a network capture that might also help, or even just a sitename for your deployed App Service.

thern743 commented 1 year ago

No movement on this issue?

To re-create, simply follow the instructions here:

https://learn.microsoft.com/en-us/aspnet/core/tutorials/grpc/grpc-start?view=aspnetcore-6.0&tabs=visual-studio-code#create-a-grpc-service

Update the App Service to use HTTP2 and the correct port (8585). Then add an API controller to the code:

using Microsoft.AspNetCore.Mvc;

namespace GrpcGreeter.Controllers;

[ApiController]
[Route("[controller]")]
public class HealthController : ControllerBase
{
  [HttpGet]
  public ActionResult Get()
  {
    return Ok();
  }
}

and update Program.cs to the following (notice AddControllers() and MapControllers()):

using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
builder.Services.AddControllers();

builder.WebHost.ConfigureKestrel(options =>
{
  options.ListenAnyIP(8080);
  options.ListenAnyIP(8585, listenOptions => 
  { 
      listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http2; 
  }); 
});

var app = builder.Build();

app.MapGrpcService<GreeterService>();
app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");

app.MapControllers();
app.Run();

Doing so causes the app service this is deployed to to fail to start. Example error:

2023-02-03T17:56:51.544876165Z    _____                               
2023-02-03T17:56:51.544909265Z   /  _  \ __________ _________   ____  
2023-02-03T17:56:51.544915166Z  /  /_\  \\___   /  |  \_  __ \_/ __ \ 
2023-02-03T17:56:51.544918966Z /    |    \/    /|  |  /|  | \/\  ___/ 
2023-02-03T17:56:51.544922466Z \____|__  /_____ \____/ |__|    \___  >
2023-02-03T17:56:51.544926166Z         \/      \/                  \/ 
2023-02-03T17:56:51.544929366Z A P P   S E R V I C E   O N   L I N U X
2023-02-03T17:56:51.544932566Z 
2023-02-03T17:56:51.544935566Z Documentation: http://aka.ms/webapp-linux
2023-02-03T17:56:51.544938666Z Dotnet quickstart: https://aka.ms/dotnet-qs
2023-02-03T17:56:51.544941766Z ASP .NETCore Version: 6.0.12
2023-02-03T17:56:51.544944866Z Note: Any data outside '/home' is not persisted
2023-02-03T17:56:53.652518284Z Starting OpenBSD Secure Shell server: sshd.
2023-02-03T17:56:54.171924731Z Starting periodic command scheduler: cron.
2023-02-03T17:56:54.172866437Z Running oryx create-script -appPath /home/site/wwwroot -output /opt/startup/startup.sh -defaultAppFilePath /defaulthome/hostingstart/hostingstart.dll     -bindPort 8080 -bindPort2 '8585' -userStartupCommand '' 
2023-02-03T17:56:55.428426339Z Cound not find build manifest file at '/home/site/wwwroot/oryx-manifest.toml'
2023-02-03T17:56:55.428596740Z Could not find operation ID in manifest. Generating an operation id...
2023-02-03T17:56:55.428951042Z Build Operation ID: 0961dd61-91c7-4520-9f38-14e09f7883d1
2023-02-03T17:56:55.830698173Z 
2023-02-03T17:56:55.831500278Z Agent extension 
2023-02-03T17:56:55.831518278Z Before if loop >> DotNet Runtime 
2023-02-03T17:56:55.893870756Z DotNet Runtime 6.0Writing output script to '/opt/startup/startup.sh'
2023-02-03T17:56:55.955292327Z Trying to find the startup DLL name...
2023-02-03T17:56:55.955330428Z Found the startup D name: GrpcGreeter.dll
2023-02-03T17:56:55.955337328Z Running the command: dotnet "GrpcGreeter.dll"
2023-02-03T17:56:59.718877139Z warn: Microsoft.AspNetCore.Server.Kestrel[0]
2023-02-03T17:56:59.718921439Z       Overriding address(es) 'http://*:8080'. Binding to endpoints defined via IConfiguration and/or UseKestrel() instead.
2023-02-03T17:57:00.417194664Z Unhandled exception. System.IO.IOException: Failed to bind to address http://[::]:8080: address already in use.
2023-02-03T17:57:00.417475866Z  ---> Microsoft.AspNetCore.Connections.AddressInUseException: Address already in use
2023-02-03T17:57:00.422366399Z  ---> System.Net.Sockets.SocketException (98): Address already in use
...
/home/obsidian/Projects/GrpcGreeter/Program.cs:line 23
2023-02-03T17:57:07.665446944Z /opt/startup/startup.sh: line 21:    68 Aborted                 (core dumped) dotnet "GrpcGreeter.dll"
OnlyOnePro commented 1 year ago

Any news on this? This fails even following the official documentation quoted above