Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Hands-On Swift 5 Microservices Development

You're reading from   Hands-On Swift 5 Microservices Development Build microservices for mobile and web applications using Swift 5 and Vapor 4

Arrow left icon
Product type Paperback
Published in Mar 2020
Publisher Packt
ISBN-13 9781789530889
Length 392 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Ralph Kuepper Ralph Kuepper
Author Profile Icon Ralph Kuepper
Ralph Kuepper
Arrow right icon
View More author details
Toc

Table of Contents (19) Chapters Close

Preface 1. Introduction to Microservices 2. Understanding Server-Side Swift FREE CHAPTER 3. Getting Started with the Vapor Framework 4. Planning an Online Store Application 5. Creating Your First Microservice 6. Application Structure and Database Design 7. Writing the User Service 8. Testing Microservices 9. Product Management Service 10. Understanding Microservices Communication 11. Order Management Service 12. Best Practices 13. Hosting Microservices 14. Docker and the Cloud 15. Deploying Microservices in the Cloud 16. Scaling and Monitoring Microservices 17. Assessment Answers 18. Other Books You May Enjoy

Swift on the server

What does it look like to run a Swift application on a server? When Swift was released as open source, it was released for Linux right away as well. Specifically, Swift favors the Linux flavor, Ubuntu. Hosting a Swift application is very different from traditional web hosting. If you get a web hosting package from companies such as GoDaddy, you will not see them say "Runs Swift 5". Most mainstream web hosters only offer scripting languages. The reasoning is simple:

  • Most applications use scripting languages.
  • Scripting applications can share the same server.

Swift, on the other hand, as a native language, is the actual web server itself. What that means is that your Swift application is directly responding to incoming requests. Let's look at the following aspects of server-side Swift:

  • A self-contained server
  • Linux/Ubuntu
  • SwiftNIO
  • Docker

Let's dive into it.

Self-contained server

A self-contained server is a program that does not need another program to run. A PHP script, for example, will run through at least two other programs: PHP (the compiler) and Nginx, Apache, or another HTTP(S) server. A self-contained server such as a Swift application, however, is the only application that needs to run; it answers HTTP(S) requests directly.

Let's look at a small Swift web server:

import Vapor
let app = try Application()

app.get("hello") { req in
return "Hello, world."
}
try app.run()

Without going into much detail, the crucial part is the last line:

try app.run()

The application does not close; it keeps running. What the framework (Vapor) and the network library (SwiftNIO) are hiding here is that the application is actively listening to incoming connections over TCP on a given port (8080 by default). So, incoming requests are answered directly by the application and, by extension, the return statement.

If you have a background in dealing with scripting web applications, you may find a lot of perks in self-contained servers. In scripting languages, every request is usually isolated. Every request is treated individually, and you have no access to the other requests that are coming in. Technologies such as Memcached are designed to bridge this for you to share information between requests.

In Swift servers, however, the process, the running application, is the same for all requests. You can share memory, objects, and instances across requests. It not only allows you to centralize some of your logic (such as the database), it also saves you a lot of memory and CPU power.

Now that you have learned how a self-contained server operates, let's take a look at the hosting operating system: Linux/Ubuntu.

Linux/Ubuntu

When Swift was open-sourced, it was delivered Linux-compatible. Ubuntu is the official flavor of Linux that Swift currently supports. Numerous other platforms that are Linux-based are being developed currently; for servers, the best option was and remains Ubuntu.

Ubuntu has been and still is a favored Linux-distribution for server applications way before Swift. A lot of other technologies are running reliably and well on Ubuntu, and so it is not surprising Apple decided to support Ubuntu primarily. Since Ubuntu is also open source and has a large user base, it is unlikely that using Ubuntu for Swift applications will disappoint. Initially, Swift on Linux had some compatibility issues; however, with every Swift version, those have been eliminated.

In the distant future, it is thinkable that Swift applications might run on other platforms, including Windows and it might be another hosting option, but you might ask why you would want that since Linux has been reliable and stable. According to one of Swift's authors, Chris Lattner, "the ultimate goal for Swift has always been and still is total world domination. It's a modest goal."(https://oleb.net/blog/2017/06/chris-lattner-wwdc-swift-panel/#in-which-fields-would-you-like-to-see-swift-in-the-future)

So, for a Swift app to run on a Linux server requires a few libraries and tools to be installed—most of which can be done with package managers. As the Swift ABI is still maturing, you will almost always deliver the source code with your app. The server will then compile it into the executable you need for the respective OS version. As time goes on, this might soon change into a more library-oriented approach in which you can compile locally and simply move the compiled file.

You can already compiling the executable and move it by itself. The problem is that the target OS might not have the correct Swift libraries installed, or you might not have the right OS handy (for example, compile on macOS while wanting it to run on Linux).

To conclude, right now Ubuntu is the most promising and reliable way to launch a Swift application on a server. In this next section, we will explore how to achieve that without necessarily having Ubuntu running.

After looking at the actual OS that will run Swift, let's explore an alternative that allows Swift to run on other hosts as well: Docker.

Docker

When deploying your application, you can run it on macOS or Ubuntu. In the world of servers, it is a lot more economical to use Ubuntu than macOS (as macOS is only supposed to run on Apple hardware, whereas Ubuntu can run on any hardware). So, you want an Ubuntu server running for Swift. Let's talk about a popular and essential way to make things easier. Docker has been an upcoming trend over the last years. It is a container system that allows for operation-system-level virtualization. What that means is that you can run applications on your machine as if you have another operating system installed.

Docker containers are packages that include everything to run certain software. For example, the Swift container has everything you need to run Swift applications in Docker. Instead of using separate kernels during virtualization (like many VMs do), Docker uses the same kernel and isolates the resources and RAM for each container.

The implications of Docker are huge, especially for microservices: instead of having to deal with many different servers for an application, it is now possible to only deal with Docker containers. So, particularly when developing a microservices application, it is beneficial to run multiple services in separate Docker containers as they all run on the same hardware. It also allows for an interesting scaling opportunity since the applications operate without needing to worry about the underlying OS. For example, if you need to run 100 instances of one service, you could run it on one big server or 20 smaller services—your application won't know nor notice the difference.

The relevant elements of Docker are the following:

  • Images: These contain everything to run.
  • Containers: These have image instances that are running.
  • Repositories: Like GitHub, these are just for Docker images.

Furthermore, a Docker container can specify how much CPU and RAM it needs. This prevents applications from stealing resources from each other.

Let's now look at the last central piece of server-side Swift: SwiftNIO.

SwiftNIO

What is SwiftNIO? It is the official library Apple offers for managing and dealing with network connections and data streams, including filesystems. SwiftNIO provides all of the tools, protocols, and features you would need to operate in a network.

Before SwiftNIO, Swift server applications had to rely mostly on external C libraries. While this is not a problem in principle, having a pure Swift network library allows for better debugging and cleaner code.

SwiftNIO is a big step forward to the server-side Swift world since it standardizes network communication and delivers the tools—in Swift—you need to build performant and reliable network applications. Apple has invested a lot of time and energy into SwiftNIO for it to be the main go-to tool when it comes to the network.

At this point, SwiftNIO is used in all major network libraries and frameworks that are developed for server applications in Swift. The convenient part of it is that framework developers—and by extension, you—don't need to worry about debugging hardly any network issues anymore because Apple has taken that part over.

For all the intents and purposes of this book, SwiftNIO is something essential to be aware of, but it will mainly stay in the background. Vapor—along with other frameworks—build around NIO in a developer-friendly way.

SwiftNIO allows us to operate asynchronously, we can send and receive data without having to worry about the exact timing or the network connection. This leads us to look at asynchronous events in general.

Asynchronous events

If you have dealt with network connections in the past, you will be familiar with the concept. There are two ways of looking at requests: synchronously and asynchronously.

Synchronously means you send a request (for example, to a server) and your code will wait for a response before it continues. An example would look like this. This is the actual code from a Vapor 2 project:

let user = User()    // User is a model that is connected to a database
user.id = 2 // set some attribute
try user.save() // saves this model to the database
print("saved") // this line is called after we saved

The last line is only called after the user is saved; the whole program waits for the saving process to be finished. In contrast to the synchronous approach is the asynchronous method. The following is the same code, now written for Vapor 4:

let user = User() 
user.id = 2
return try user.save(on: request.db) { _ in
print("saved")
}

You can see here that we are returning an EventLoopFuture<User> (line 3), but we are also not printing the "saved" string right after the return statement (because it would never be called), but we put it in a callback function. The fundamental difference here is that deal with the fact that we do not know when the user is saved. The database might be busy or slow; it might take 1 or 10 seconds. But when it is saved, we know that the callback function is called and then we print the "saved" string.

SwiftNIO is all based on the concept of asynchronous events; it handles all of the magic in the background for us, and we do not have to worry about it.

The reason we are not using synchronous calls (anymore) is that it can and most certainly will create problems for us down the line. Synchronous events in an asynchronous environment (which networks are) create issues that can look like deadlocks or threading complications. Using synchronous code causes threads to "wait" until they have finished; using asynchronous frameworks allows us to use the CPU resources in the meantime for different activities.

Now, let's look at some of the new features Swift 5 has brought to the table.

You have been reading a chapter from
Hands-On Swift 5 Microservices Development
Published in: Mar 2020
Publisher: Packt
ISBN-13: 9781789530889
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime