<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luis Rodrigues</title>
    <description>The latest articles on DEV Community by Luis Rodrigues (@luisalexandre).</description>
    <link>https://dev.to/luisalexandre</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F370670%2F58dd82d3-df31-437b-9e61-276ec8150866.jpg</url>
      <title>DEV Community: Luis Rodrigues</title>
      <link>https://dev.to/luisalexandre</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/luisalexandre"/>
    <language>en</language>
    <item>
      <title>Backup Azure Kubernetes Services (AKS) cluster with Velero</title>
      <dc:creator>Luis Rodrigues</dc:creator>
      <pubDate>Sat, 11 Sep 2021 15:38:35 +0000</pubDate>
      <link>https://dev.to/luisalexandre/backup-azure-kubernetes-services-aks-cluster-with-velero-4i0i</link>
      <guid>https://dev.to/luisalexandre/backup-azure-kubernetes-services-aks-cluster-with-velero-4i0i</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7wu94uoJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l90qiqfrmg479o5b37xu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7wu94uoJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l90qiqfrmg479o5b37xu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the past, I was in charge of backup a MongoDB instance that runs in Azure Kubernetes Services (AKS). This database has at least 2 TB of data that was being persisted in an Azure Managed Disk with Kubernetes Persistent Volume (PV).&lt;/p&gt;

&lt;p&gt;I could not run the “mongodump” without issues. This was overloading the database and take a long time to complete the backup process. The same behavior happened when I tried to restore the database backup.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mongodump is a utility tool that allows us to create MongoDB backups. You can check &lt;a href="https://docs.mongodb.com/database-tools/mongodump/"&gt;&lt;strong&gt;this tool here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, instead of run the “mongodump” tool, I applied options below that I found in Microsft Documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Take a backup from the Azure Managed Disk with Azure Backup.&lt;/li&gt;
&lt;li&gt;  Create a scheduler backup to MongoDb’s PVC with the Velero tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;You can see the documentation about AKS backup in this &lt;a href="https://docs.microsoft.com/en-us/azure/aks/operator-best-practices-storage#secure-and-back-up-your-data"&gt;&lt;strong&gt;link from Microsoft Documentation&lt;/strong&gt;.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first option basically, allows you to take a snapshot from the disk that is being used by Kubernetes PVC. Later, you can restore this snapshot if you need it.&lt;/p&gt;

&lt;p&gt;For the second option, you can use a tool called &lt;a href="https://velero.io/"&gt;&lt;strong&gt;&lt;em&gt;Velero&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; to backup the whole AKS cluster, or just some Kubernetes resources, like Deployments, Services, persistent volume claims (PVC), PV, etc.&lt;/p&gt;

&lt;p&gt;The backup destination created by Velero could be set up with plugins, which have support for the principal cloud providers, like Azure, AWS, and Google Cloud. In the case of Azure, the backup will be stored in &lt;strong&gt;Azure Account Storage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the end, what I did was create a backup from PV that MongoDB is using to persist its data.&lt;/p&gt;

&lt;p&gt;So, in this article, I will present how to install Velero and how to use it to create and restore backups.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setup Velero
&lt;/h4&gt;

&lt;p&gt;The setup of Velero in the environment is very simple. Beyond the Azure account, you will need Azure Account Storage and AKS cluster.&lt;/p&gt;

&lt;p&gt;After the resources created in Azure, you can apply the steps below to setup Velero in your environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Install &lt;strong&gt;&lt;em&gt;Azure CLI&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;kubectl&lt;/em&gt;&lt;/strong&gt; tool in the machine that will apply the next steps.&lt;/li&gt;
&lt;li&gt;  Connect to the AKS cluster. You can &lt;a href="https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough#connect-to-the-cluster"&gt;&lt;strong&gt;use this link&lt;/strong&gt;&lt;/a&gt; to connect to your cluster.&lt;/li&gt;
&lt;li&gt;  Create environment variables to store Azure Account Storage configurations.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;  Create a credential file. This file will be used to configure the Azure Account Storage credentials in Velero.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;  Install &lt;strong&gt;Velero client&lt;/strong&gt;. You can find the Velero client on its &lt;a href="https://velero.io/docs/v1.6/basic-install/"&gt;&lt;strong&gt;home page&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Finally, install Velero in the AKS cluster. After that, we can create backups and restore them.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The Velero installation will create a set of new Kubernetes resources in the AKS cluster. Velero will use the Kubernetes namespace &lt;strong&gt;&lt;em&gt;“velero”&lt;/em&gt;&lt;/strong&gt;. Then, to remove Velero from the AKS cluster, apply the command below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Also, like any Kubernetes resources, we can update it to achieve your requirements. For example, we can update resource limits from its Deployment:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Create and Restore Backups
&lt;/h4&gt;

&lt;p&gt;Now that you have Velero in the AKS cluster, you can create and schedule backups, and restore them with the &lt;strong&gt;Velero client&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Below, there are some commands to help you create and restore backups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create a new backup:&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;  Create a new schedule:&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;  Restore backup:&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;You can find more commands and options in the Velero’s home page. &lt;a href="https://velero.io/docs/v1.6/"&gt;Click here to check them&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When the commands above are executed by Velero, new folders are created in its Azure Blob Storage. Here is an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wZVDlL74--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o3z59harl5gfwjufgi6v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wZVDlL74--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o3z59harl5gfwjufgi6v.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beyond backup and restore the cluster, Velero can be useful in the migration process.&lt;/p&gt;

&lt;p&gt;We can use that to migrate our AKS cluster to a new AKS cluster or a new Kubernetes cluster from another Cloud Provider.&lt;/p&gt;

&lt;p&gt;For now, that’s all. I hope that can be helpful for you!&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>azure</category>
      <category>kubernetes</category>
      <category>velero</category>
    </item>
    <item>
      <title>.NET and Apache Ignite: Testing Cache and SQL API features — Part I</title>
      <dc:creator>Luis Rodrigues</dc:creator>
      <pubDate>Sat, 11 Sep 2021 15:33:15 +0000</pubDate>
      <link>https://dev.to/luisalexandre/net-and-apache-ignite-testing-cache-and-sql-api-features-part-i-5gm0</link>
      <guid>https://dev.to/luisalexandre/net-and-apache-ignite-testing-cache-and-sql-api-features-part-i-5gm0</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iexKalxX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tpo5fwn662mfri7ao763.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iexKalxX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tpo5fwn662mfri7ao763.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some non-functional requirements from our applications are about performance and scalability. Then, we start thinking about a lot of strategies: review architecture, refactor features and algorithms, apply some caching strategy, etc.&lt;/p&gt;

&lt;p&gt;Last days, I started using &lt;a href="https://ignite.apache.org/"&gt;&lt;strong&gt;&lt;em&gt;Apache Ignite&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; as a cache strategy for some applications. Apache Ignite is an open-source In-Memory Data Grid, distributed database, caching, and high-performance computing platform.&lt;/p&gt;

&lt;p&gt;Yeah! That’s it! All this in one solution. :D&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to know more about Apache Ignite, take a look at its &lt;a href="https://ignite.apache.org/docs/latest/"&gt;documentation&lt;/a&gt;. Beyond .NET, there are samples for other programming languages as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This article will be split into two parts. In this first one, I will present the basic steps to work with the &lt;strong&gt;Cache&lt;/strong&gt; feature and check results from a small test with that. In the second part, let’s see how can we work with &lt;strong&gt;SQL API&lt;/strong&gt; feature in .NET applications.&lt;/p&gt;

&lt;h4&gt;
  
  
  Machine settings
&lt;/h4&gt;

&lt;p&gt;For this test, I used the machine settings below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Windows 10&lt;/li&gt;
&lt;li&gt;  Intel(R) Core(TM) i5–4440&lt;/li&gt;
&lt;li&gt;  16 GB RAM&lt;/li&gt;
&lt;li&gt;  .NET 5&lt;/li&gt;
&lt;li&gt;  Apache Ignite 2.10.0&lt;/li&gt;
&lt;li&gt;  Docker version 20.10.6&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Run docker container
&lt;/h4&gt;

&lt;p&gt;Before implementing our cache repository, let’s run Apache Ignite with its official &lt;a href="https://www.docker.com/"&gt;&lt;strong&gt;&lt;em&gt;Docker&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; container.&lt;/p&gt;

&lt;p&gt;Then, run the following command to start the Apache Ignite container:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We can persist the data that will be used in the sections below in memory or on disk. For this article, the is being persisted in memory.&lt;/p&gt;

&lt;p&gt;After running the command above, you should see the screen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2BEQt1eY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z0et6v5wrrnyv316pv0j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2BEQt1eY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z0et6v5wrrnyv316pv0j.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check if there are error messages when the Apache Ignite container has been started. If everything is OK, let’s test its Cache feature in the sections below.&lt;/p&gt;

&lt;h4&gt;
  
  
  Basic Settings for .NET and Apache Ignite
&lt;/h4&gt;

&lt;p&gt;The steps to use Apache Ignite are very simple. You can follow the items below to allow your application to connect with Apache Ignite.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Add NuGet package below:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Install-Package Apache.Ignite&lt;/strong&gt; -Version 2.10.0&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Set up a new connection with &lt;strong&gt;IgniteClientConfiguration&lt;/strong&gt; class*&lt;em&gt;.&lt;/em&gt;* in this part you need to provide at least one Apache Ignite server:&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;  Start a new connection with &lt;strong&gt;&lt;em&gt;Ignition.StartClient method&lt;/em&gt;&lt;/strong&gt;. This method returns an interface called &lt;strong&gt;&lt;em&gt;IIgniteClient&lt;/em&gt;&lt;/strong&gt;, which contains methods to work with cache clusters:&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;  With &lt;strong&gt;&lt;em&gt;IIgniteClient.GetOrCreateCache,&lt;/em&gt;&lt;/strong&gt; get or create a new cache repository to a specific object type. This method returns the &lt;strong&gt;&lt;em&gt;ICacheClient&lt;/em&gt;&lt;/strong&gt; interface, which contains methods to work with the cache repository.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Done! Now your application can perform operations in a cache repository from Apache Ignite. I recommend checking the Apache Ignite documentation to know more about available methods.&lt;/p&gt;

&lt;h4&gt;
  
  
  Testing the Cache system
&lt;/h4&gt;

&lt;p&gt;Now that we have an Apache Ignite cluster ready and the application set up appropriately, let’s test its cache feature.&lt;/p&gt;

&lt;p&gt;For this test, two classes were created to be inserted on the Apache Ignite Cache: &lt;em&gt;OrderCacheEntity (Order)&lt;/em&gt; and &lt;em&gt;ItemCacheEntity (OrderItem)&lt;/em&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Basically, one Order can have one or more OrderItem associated with it. Then, the next step is to generate as many Order instances as possible, adding and getting them to the cache, and finally check the performance with some counters.&lt;/p&gt;

&lt;p&gt;The code below inserts 1 million Orders in the cache repository and checks its performance for “&lt;strong&gt;&lt;em&gt;ICacheClient.Put&lt;/em&gt;&lt;/strong&gt;” and “&lt;strong&gt;&lt;em&gt;ICacheClient.TryGET&lt;/em&gt;&lt;/strong&gt;” methods. As an attempt to create a small &lt;strong&gt;&lt;em&gt;“workload”&lt;/em&gt;&lt;/strong&gt; against the Apache Ignite container, those operations are executed with Parallel Task.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As we can see in the code above, some KPIs were created to check the performance of each operation against Apache Ignite Cache:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;KPIs Operation Time:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;INPUT time (AVG seconds)&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;:&lt;/em&gt; the average in seconds to add an item to the cache&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;OUTPUT time (AVG seconds):&lt;/em&gt;&lt;/strong&gt; the average in seconds to get an item from the cache&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;INPUT time (MAX seconds):&lt;/em&gt;&lt;/strong&gt; the maximum time in seconds to add an item to the cache.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;OUTPUT time (MAX seconds):&lt;/em&gt;&lt;/strong&gt; the maximum time in seconds to get an item from the cache.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;INPUT time (MIN seconds):&lt;/em&gt;&lt;/strong&gt; the minimum time in seconds to add an item to the cache.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;OUTPUT time (MIN seconds):&lt;/em&gt;&lt;/strong&gt; the minimum time in seconds to get an item from the cache.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;KPIs Exceptions:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;INPUT ERROR:&lt;/em&gt;&lt;/strong&gt; number of exceptions created when the application was adding an item to the cache.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;OUTPUT ERROR:&lt;/em&gt;&lt;/strong&gt; number of exceptions created when the application was getting an item from the cache.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;KPIs Summary&lt;/em&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;ITEMS CREATED&lt;/em&gt;&lt;/strong&gt;: how many items were created in the cache.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;ITEMS RECEIVED&lt;/em&gt;&lt;/strong&gt;: how many items were got from the cache.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;ITEMS MISSING&lt;/em&gt;&lt;/strong&gt;: how many items were not in the cache.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Results from Application Test
&lt;/h4&gt;

&lt;p&gt;After running the application test, the metrics below were collected:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NOqSRLs8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n1p62c9isnc36b4rngmx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NOqSRLs8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n1p62c9isnc36b4rngmx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In general, the Apache Ignite presented a nice performance adding and getting objects. The average time to add items in the cache was &lt;strong&gt;0.016&lt;/strong&gt; seconds and &lt;strong&gt;0.025&lt;/strong&gt; seconds to get those items from the cache. Also, there were no exceptions and lost items in this test.&lt;/p&gt;

&lt;p&gt;Checking the Apache Ignite container, the memory consumption increase by about 390 MB, which represents about 130% more than its initial state:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Container stats (initial state)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bUMD5Fg1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wvdn7105slqripoq39mi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bUMD5Fg1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wvdn7105slqripoq39mi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Container stats (after running application test)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZBjDt1tl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufvu6ayoa2hwlycmvu62.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZBjDt1tl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufvu6ayoa2hwlycmvu62.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For now, that’s all. In the second part, let's see how can we implement the SQL API feature in our .NET applications. From a development perspective, I think that this feature from Apache Ignite is the most interesting so far.&lt;/p&gt;

&lt;p&gt;I hope that this can be helpful for you!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>apache</category>
      <category>csharp</category>
      <category>programming</category>
    </item>
    <item>
      <title>Creating a local development environment to Kong API with Docker</title>
      <dc:creator>Luis Rodrigues</dc:creator>
      <pubDate>Sat, 11 Sep 2021 15:27:29 +0000</pubDate>
      <link>https://dev.to/luisalexandre/creating-a-local-development-environment-to-kong-api-with-docker-2cnl</link>
      <guid>https://dev.to/luisalexandre/creating-a-local-development-environment-to-kong-api-with-docker-2cnl</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7ncx99khx1i2dhk1tvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7ncx99khx1i2dhk1tvp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
In this article let’s create a local development environment for Kong API. This environment is very useful to test our integration between our applications and Kong API Gateway.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to know more about Kong API Management, &lt;a href="https://konghq.com/kong" rel="noopener noreferrer"&gt;&lt;strong&gt;check its documentation&lt;/strong&gt;&lt;/a&gt;. Beyond API Gateway, Kong has other nice features to management our APIs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We are going to use Docker to create our local development environment. Then, please install &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;Docker tools&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; in your local machine if you don’t have them yet.&lt;/p&gt;

&lt;p&gt;Three docker containers are required to create a local development environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://hub.docker.com/r/pantsel/konga/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;pantsel/konga&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;: open source admin tool for Kong API Management.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://hub.docker.com/_/kong" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;kong&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;: Kong API Management&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://hub.docker.com/_/postgres" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;postgres&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;: Database for Kong API Management&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Running Kong API Gateway
&lt;/h4&gt;

&lt;p&gt;First, let’s create a docker network to each initiate docker container can communicate between themselves:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Start Postgres database to create a database for Kong API:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;In this example we are using Postgres to creating a new database, however, Kong API Gateway supports &lt;strong&gt;Cassandra&lt;/strong&gt; as its database as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, we need to run a data migration process to prepare Kong API database. Run the command below to start the data migration process:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Finally, start Kong API Gateway with the command below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;When the container is ready, two ports will be available for use in our machine (&lt;strong&gt;localhost)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Admin API [&lt;/em&gt;&lt;a href="http://localhost:8001" rel="noopener noreferrer"&gt;&lt;em&gt;http://localhost:8001&lt;/em&gt;&lt;/a&gt;&lt;em&gt;]:&lt;/em&gt; Use this port to manage your APIs in Kong API Gateway.&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Proxy [&lt;/em&gt;&lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;&lt;em&gt;http://localhost:8000&lt;/em&gt;&lt;/a&gt;&lt;em&gt;]:&lt;/em&gt; Use this port to call your APIs with Kong API Gateway.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Check &lt;a href="https://docs.konghq.com/gateway-oss/2.5.x/admin-api/" rel="noopener noreferrer"&gt;&lt;strong&gt;Admin API documentation&lt;/strong&gt;&lt;/a&gt; to know more about how to manage your APIs in Kong API Gateway.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Running Admin UI
&lt;/h4&gt;

&lt;p&gt;Now that we have our Kong API Gateway ready, we can manage services, routes, and plugins for our APIs.&lt;/p&gt;

&lt;p&gt;Those Kong API objects are managed with Admin API. For instance, the command below creates a new service to fictional &lt;em&gt;“Product API”&lt;/em&gt; from the fictional address &lt;em&gt;“&lt;a href="https://product-api.net%E2%80%9D" rel="noopener noreferrer"&gt;https://product-api.net”&lt;/a&gt;&lt;/em&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Sometimes, this task can be very challenging. Then, for testing purposes, we can manage our APIs in Kong API Gateway with &lt;a href="https://github.com/pantsel/konga" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;Konga&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Konga is an open source project that allows us to manage Kong API Gateway with a UI. You can know more about the &lt;a href="https://github.com/pantsel/konga" rel="noopener noreferrer"&gt;&lt;strong&gt;project here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Run the command below to start the Konga container:&lt;/p&gt;

&lt;p&gt;Konga will be started on port 1337 from your localhost. In the first access, the application will request to create a new user.&lt;/p&gt;

&lt;p&gt;After creating the user, we need to create a new connection between Konga and Kong API Admin to manage our services:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98wkua0xdnanb61a4skg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98wkua0xdnanb61a4skg.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Provide a name for the new connection, the IP address where Kong Admin API is running, and click on the &lt;em&gt;“Create Connection”&lt;/em&gt; button. Then, you can see the Konga Dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xh5ip7zqo7v4j0e3n8v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xh5ip7zqo7v4j0e3n8v.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you had some issue with Kong Admin URL, try to provide the IP address from the Kong docker container. Execute the command below to get the IP address from the container:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;It’s done! Now you can explore more Kong API Gateway in your local machine. Have happy findings with Kong API Gateway! :D&lt;/p&gt;

&lt;p&gt;I hope that this can be helpful for you!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>kong</category>
    </item>
    <item>
      <title>.NET: Call Func delegates from Dictionary objects</title>
      <dc:creator>Luis Rodrigues</dc:creator>
      <pubDate>Fri, 13 Aug 2021 19:46:39 +0000</pubDate>
      <link>https://dev.to/luisalexandre/net-invoking-func-delegates-from-dictionary-objects-2gjp</link>
      <guid>https://dev.to/luisalexandre/net-invoking-func-delegates-from-dictionary-objects-2gjp</guid>
      <description>&lt;p&gt;How about store Func delegates in a Dictionary object and invoke them when you really need them?&lt;/p&gt;

&lt;p&gt;This approach can help us to avoid having nested conditional in our code and keep its cyclomatic complexity lower.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“Cyclomatic complexity&lt;/strong&gt; is a software metric used to determine the complexity of a program”. &lt;a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity"&gt;Click here&lt;/a&gt; to know more about that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, suppose we want to create a method that returns a result from a math operation between two numbers. Its result will depend on the operation type that the user will provide to us: addition, subtraction, multiplication, and division.&lt;/p&gt;

&lt;p&gt;A simple way to solve that is by creating a method that accepts three parameters: a number that will apply some operation and the operation type. Like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As you can see, we need to add four conditions to this method. From that, we have the cyclomatic complexity metric below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fRjn7_eu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hjobyb50qd75p0o5thuf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fRjn7_eu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hjobyb50qd75p0o5thuf.png" alt="nested conditions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now check the same method with a Dictionary type that stores Func delegates:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In this case, we don’t need a lot of “if” statements in our code and it’s getting easier to read. Also as you can see in the picture below our cyclomatic complexity is lower than in the first approach:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eBatt3Kz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0vymza7ju6jzfakrunxr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eBatt3Kz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0vymza7ju6jzfakrunxr.png" alt="without nested conditions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, this sample is so simple. Now, try to think how easier can be our life in complex scenarios where we need to support code with higher cyclomatic complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.buymeacoffee.com/techwithluis"&gt;How about buying me a coffee? :D&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QRlBnShy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ocojbj7yf8l59aibats8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QRlBnShy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ocojbj7yf8l59aibats8.png" alt="buy me a coffe?"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>.Net Reverse Proxy with YARP</title>
      <dc:creator>Luis Rodrigues</dc:creator>
      <pubDate>Sun, 04 Apr 2021 20:39:00 +0000</pubDate>
      <link>https://dev.to/luisalexandre/net-reverse-proxy-with-yarp-56kl</link>
      <guid>https://dev.to/luisalexandre/net-reverse-proxy-with-yarp-56kl</guid>
      <description>&lt;p&gt;How about creating a reverse proxy with .NET Core or .NET 5?&lt;br&gt;
If you had to do that once, you should know &lt;a href="https://microsoft.github.io/reverse-proxy/articles/getting_started.html"&gt;&lt;strong&gt;YARP&lt;/strong&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;YARP is a Reverse Proxy project that Microsoft is working on. For now, it is in preview, but it's an easier way to create a simple reverse proxy for our applications.&lt;/p&gt;
&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;In this &lt;a href="https://github.com/yt-tech-knowledge/proxy-sample/tree/main/ProxySample/src"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/a&gt;, you can find a sample that presents how we can use YARP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ProductA: the API that can only list "products".&lt;/li&gt;
&lt;li&gt;ProductB: the API that can only insert new "products"&lt;/li&gt;
&lt;li&gt;Proxy: the reverse proxy that will redirect each request to APIs: ProductA and ProductB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basically, what we need to create a simple Reverse Proxy is to set Routes and Clusters in &lt;strong&gt;&lt;em&gt;appSettings.json&lt;/em&gt;&lt;/strong&gt; from the Proxy project.&lt;/p&gt;

&lt;p&gt;For each Route we should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define how we want to expose an API.&lt;/li&gt;
&lt;li&gt;Set the API original path that Reverse Proxy must redirect our calls.&lt;/li&gt;
&lt;li&gt;Define which Cluster is associated with API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Cluster settings, we should define the host address for each API exposed by YARP. When we call a route, YARP will call the original path concatenated with the API address defined in the Cluster section.&lt;/p&gt;

&lt;p&gt;See below a sample of YARP settings:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Finally, in our startup class, we need to register YARP and load all settings. &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;After that, we need to add each route defined in our Proxy appSettings.json to endpoint collections.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;It's done! Now we can call our APIs through our reverse proxy. Try to get a list of products by this endpoint: &lt;strong&gt;&lt;em&gt;&lt;a href="http://localhost:5000/produto"&gt;http://localhost:5000/produto&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bkISfJma--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dloaldvlhj9fbycpjhqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bkISfJma--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dloaldvlhj9fbycpjhqc.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As presented above, when we call a route from our Proxy, the request is redirected to the original API, in this case to ProductA API.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
