Azure / Azure-Functions

1.11k stars 195 forks source link

V3 Functions fail locally on net5.0 with: The gRPC channel URI 'http://:0' could not be parsed. #2032

Closed lewinskimaciej closed 2 years ago

lewinskimaciej commented 3 years ago

Trying to move our V3 functions project to Isolated Process and net5.0, it fails on startup with following exception:

Unhandled exception. System.InvalidOperationException: The gRPC channel URI 'http://:0' could not be parsed.
   at Microsoft.Extensions.DependencyInjection.GrpcServiceCollectionExtensions.<>c.<AddGrpc>b__1_1(IServiceProvider p) in D:\a\1\s\src\DotNetWorker.Grpc\GrpcServiceCollectionExtensions.cs:line 61
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
   at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at MWS.Core.Functions.Program.Main(String[] args) in C:\repos\MWS-GIT-G-Dev\MWS.Core.Functions\Program.cs:line 134
   at MWS.Core.Functions.Program.<Main>(String[] args)
****

The whole issue seems to be due to IServiceCollection AddGrpc(this IServiceCollection services) adding gRPC and not having sensible defaults on GrpcWorkerStartupOptions which creates malformed URL when on localhost. What's more, I can't configure GrpcWorkerStartupOptions because they're internal within Microsoft.Azure.Functions.Worker namespace. I also don't see a way of setting it properly at all, there seems to be no documentation on it, tried putting them in appsettings.json and host.json, none are actually binding for some reason.

I would like to have an option to NOT add gRPC to my Functions project. I don't need it and I don't see the reason it's being added as default now, especially if default configuration doesn't seem to work.

.csproj:

<PropertyGroup>
       <OutputType>Exe</OutputType>
       <TargetFramework>net5.0</TargetFramework>
       <AzureFunctionsVersion>v3</AzureFunctionsVersion>
       <LangVersion>8.0</LangVersion>
 </PropertyGroup>

<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.5.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.0.4" />

I'm running in Rider, but it also doesn't work using dotnet run. Haven't yet tried deploying to Azure.

Seems to be connected to: https://github.com/Azure/Azure-Functions/issues/2005

v-anvari commented 3 years ago

Hi @lewinskimaciej , would it be possible to give us a sample that repro's what you're seeing? One of the users got this exception resolved by re-installing the local developing environment as mentioned in the issue 2005. Also let us know the function App details by providing the invocation id, region and timestamp of the error

Treit commented 3 years ago

@v-anvari I am seeing a very similar issue that is blocking me from using dependency injection with Azure functions using .NET 5.

I have created a stand-alone trivial repro here: https://github.com/Treit/AzureFunctionIssue

eluchsinger commented 3 years ago

Same here... especially when I run it on Rider, I have had this issue on MacOS and on Windows.

aylmercarson commented 3 years ago

same issue.

Microsoft Visual Studio Professional 2019, Version 16.11.3 .NET 5

PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Storage" Version="4.0.4" /> PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.0.4" OutputItemType="Analyzer" /> PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.5.1" /> PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.30" /> PackageReference Include="Microsoft.Azure.WebJobs.Core" Version="3.0.30" /> PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.5" /> PackageReference Include="System.Collections" Version="4.3.0" /> PackageReference Include="System.Collections.NonGeneric" Version="4.3.0" />

AzureFunctionsVersion v3

this is in a pretty plain vanilla project.

v-anvari commented 2 years ago

Hi @lewinskimaciej , If you running on rider, you may want to set up the configuration additionally - https://github.com/Azure/Azure-Functions-dotnet-worker#jetbrains-rider

lewinskimaciej commented 2 years ago

Hi @lewinskimaciej , If you running on rider, you may want to set up the configuration additionally - https://github.com/Azure/Azure-Functions-dotnet-worker#jetbrains-rider

Sorry for late reply, I was on vacation. I've created a repro repo here: https://github.com/lewinskimaciej/functions-bug-repro

The thing I noticed now, is that the project will fail if I run it with dotnet run as well as if I chose (in Rider) configuration .NET Project. But if I pick Azure Function host configuration, it actually works. In the last commit I've added .run configurations for Rider. Project config won't work, Functions - will.

Why is that? Wasn't the whole purpose of this transition to make Functions a basic class library that starts the Functions host? I'm honestly not sure now how are we supposed to run Functions project after changing to Isolated process.

v-anvari commented 2 years ago

Thank you for the information! We will investigate this scenario and update as appropriate

v-anvari commented 2 years ago

Hi @lewinskimaciej , Below is the analysis after further investigation by the team.

Team is able to repro the Grpc exception (Invalid URI: The hostname could not be parsed.). We get the same error in RIDER IDE when we use the incorrect configuration( dotnet configuration) to run/debug.

image

The cause for this error is the usage of incorrect run/debug configuration the IDE is using (which user has picked in this case). In the above screenshot I have highlighted the Incorrect configuration used.

User is not supposed to run thedotnet run command on an isolated (out-of-process) function app. Instead the user should use function CLI command func start. Behind the scene, this command start the host process and the host process will internally invoke the out-of-process function app. When it does this, the host passes some information the worker needs so that it can properly communicate with the host (things like the port number to be used for GRPC communication between host and worker)

The C# out-of-process function app cannot run by itself. It runs with the host (func.exe).

When you create a new function app & run/debug in IDEs (Visual studio or Rider), the IDE does the above magic for us behind the scene. It creates a configuration which calls the func start command. You can see that in the configuration file in his repo here.

You should use the configuration created for function app in RIDER IDE. If you choose to run from command prompt, you should be using the functions CLI command func start . The dotnet run should not be used directly on an out-of-process c# function app image

I hope this information helps

eluchsinger commented 2 years ago

Thank you very much. This piece of feedback is an example of a good and complete response.

aylmercarson commented 2 years ago

agreed. thanks very much for your help guys. first class! :)

v-anvari commented 2 years ago

Thankyou for the feedback, closing this issue as resolved

kan-nan-k commented 2 years ago

I had similar issue, I did not have Azure Development tools selected in my visual studio 2022 installation. Hope this helps someone.

image

cristicazan commented 1 year ago

I had a similar issue and I found out that the problem was caused by the services.AddConfigurations method in the ConfigureServices extension method. This method was overriding the settings done by the ConfigureFunctionsWorkerDefaults() method. To fix this, I had to include the hostContext.Configuration in the AddConfigurations() method, like this:

var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices((hostContext, services) =>
{
    var location = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);

    services.AddConfigurations(c => c.SetBasePath(location)
                        .AddJsonFile("example.settings.json", optional: false, reloadOnChange: true)
                        .AddConfiguration(hostContext.Configuration));
}).Build();
host.Run();

This way, the configuration from the hostContext is merged with the configuration from the JSON file, and the settings are not overridden. I hope this helps you solve your problem.

EmilAlipiev commented 1 year ago

to run from command prompt, you should be using the functions CLI command func start . The dotnet run should not be used directly on an out-of-process c# function app

thats nice to know but I have this error when i try to debug docker-compose with Rider. how to make this working? I dont see any configuration file possibility for docker

santo2 commented 11 months ago

tried a lot of things already, still didn't find anything that helped for my problem. Am getting the exception on debugging startup. Couldn't this exception be made more clear, about what exactly is missing? or could GRPC in general be disabled somehow