Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make Service Fabric package sizes practical?

I'm working on a Service Fabric application that is deployed to Azure. It currently consists of only 5 stateless services. The zipped archive weighs in at ~200MB, which is already becoming problematic.

By inspecting the contents of the archive, I can see the primary problem is that many files are required by all services. An exact duplicate of those files is therefore present in each service's folder. However, the zip compression format does not do anything clever with respect to duplicate files within the archive.

As an experiment, I wrote a little script to find all duplicate files in the deployment and delete all but one of each files. Then I tried zipping the results and it comes in at a much more practical 38MB.

I also noticed that system libraries are bundled, including:

  • System.Private.CoreLib.dll (12MB)
  • System.Private.Xml.dll (8MB)
  • coreclr.dll (5MB)

These are all big files, so I'd be interested to know if there was a way for me to only bundle them once. I've tried removing them altogether but then Service Fabric fails to start the application.

Can anyone offer any advice as to how I can drastically reduce my deployment package size?

NOTE: I've already read the docs on compressing packages, but I am very confused as to why their compression method would help. Indeed, I tried it and it didn't. All they do is zip each subfolder inside the primary zip, but there is no de-duplication of files involved.

like image 215
me-- Avatar asked Feb 14 '19 22:02

me--


1 Answers

There is a way to reduce the size of the package but I would say it isn't a good way or the way things should be done but still I think it can be of use in some cases.

Please note: This approach requires target machines to have all prerequisites installed (including .NET Core Runtime etc.)

When building .NET Core app there are two deployment models: self-contained and framework-dependent.

In the self-contained mode all required framework binaries are published with the application binaries while in the framework-dependent only application binaries are published.

By default if the project has runtime specified: <RuntimeIdentifier>win7-x64</RuntimeIdentifier> in .csproj then publish operation is self-contained - that is why all of your services do copy all the things.

In order to turn this off you can simply add SelfContained=false property to every service project you have.

Here is an example of new .NET Core stateless service project:

<PropertyGroup>
  <TargetFramework>netcoreapp2.2</TargetFramework>
  <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
  <IsServiceFabricServiceProject>True</IsServiceFabricServiceProject>
  <ServerGarbageCollection>True</ServerGarbageCollection>
  <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
  <TargetLatestRuntimePatch>False</TargetLatestRuntimePatch>
  <SelfContained>false</SelfContained>
</PropertyGroup>

I did a small test and created new Service Fabric application with five services. The uncompressed package size in Debug was around ~500 MB. After I have modified all the projects the package size dropped to ~30MB.

The application deployed worked well on the Local Cluster so it demonstrates that this concept is a working way to reduce package size.

In the end I will highlight the warning one more time:

Please note: This approach requires target machines to have all prerequisites installed (including .NET Core Runtime etc.)

like image 58
Oleg Karasik Avatar answered Oct 19 '22 10:10

Oleg Karasik