Slides of the talk we gave with David Delabassee at Oracle Code One 2018.
The FnProject was released about a year ago, proposing new ways to design asynchronous systems in a very flexible way. This tutorial shows you how to set up a Fn Server on a local development machine running Windows with a first simple function. Then we cover the design of multi-functions systems, connected together in an asynchronous way, leveraging the Fn Flow API. This API is first presented, including how it compares to the the Java 8 CompletableFuture API. We then set up a real example made of several functions, producing multiple results and see how we can leverage their asynchronous nature to make a non-blocking system, handling errors in a simple and intuitive way. Most of the examples are shown both on slides and live coding parts.
9. @JosePaumard @delabassee#ASFnFlow
Fn
Open Source
Approachable
Container based
Language independent
Platform independent
Scheduler independent
No lock-in
Easy for new users
More controls for advanced users
Leverages Docker
Go, Node, Java, etc.
Cloud, On-Perm, laptop
K8S, etc.
https://github.com/fnproject
13. @JosePaumard @delabassee#ASFnFlow
Setting Up Fn
2) Requires a working Docker installation
▪ Available on Windows Pro but…!
▪ Requires Docker 17.10+
▪ It not, check:
▪ 7 steps to follow to get a fresh Docker installation
$ docker –v
Docker version 18.06.1-ce, build e68fc7a
https://docs.docker.com/install/linux/docker-ce/ubuntu/#prerequisites
14. @JosePaumard @delabassee#ASFnFlow
Setting Up Fn
3) Execute the install script, directly from GitHub!
▪ After some time:
$ curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh
fn version 0.5.13
______
/ ____/___
/ /_ / __
/ __/ / / / /
/_/ /_/ /_/`
16. @JosePaumard @delabassee#ASFnFlow
Setting Up Fn
4) Launch Fn Server
You need to be root for most of the Fn commands (*)
$ fn start
docker: Got permission denied while trying to connect to the Docker daemon socket at
unix:///var/run/docker.sock: Post
http://%2Fvar%2Frun%2Fdocker.sock/v1.38/containers/create?name=fnserver: dial unix
/var/run/docker.sock: connect: permission denied.
See 'docker run --help'.
2018/10/04 10:30:47 Error: processed finished with error exit status 126
24. @JosePaumard @delabassee#ASFnFlow
Introducing Fn Function
Function wrapped in a Container Image
Input from stdin
Output to stdout
Logs to stderr
Or simply use an FDK!
Fn handles everything else!
25. @JosePaumard @delabassee#ASFnFlow
Fn Concepts
In Fn, a function is the fundamental unit
A function is created from (Java) code
A function lives in an « app »
To bootstrap a function:
$ fn init --runtime java myfunction
Creating function at: /myfunction
Function boilerplate generated.
func.yaml created
$ ls myfunction/
func.yaml pom.xml src/
26. @JosePaumard @delabassee#ASFnFlow
Fn Concepts
Functions are deployed within an « app »
$ fn create app first-app
Successfully created app: first-app
$ fn list apps
NAME
first-app
$ fn delete app first-app
App first-app deleted
27. @JosePaumard @delabassee#ASFnFlow
Fn Concepts
Fn deals with triggers
A function is accessible through a trigger
# fn list triggers first-app
FUNCTION NAME TYPE SOURCE ENDPOINT
primefunction prime-trigger http /is-prime http://localhost:8080/t/fn-primes/is-prime
29. @JosePaumard @delabassee#ASFnFlow
Setting Up a Function
Using the Fn CLI
$ fn init --runtime java --trigger http javafunc
Creating function at: /firstfunc
Function boilerplate generated.
func.yaml created.
30. @JosePaumard @delabassee#ASFnFlow
Setting Up a Function
Using the Fn CLI
This command creates a Maven project
With a simple Java class
And a func.yaml file
$ fn init --runtime java --trigger http javafunc
Creating function at: /javafunc
Function boilerplate generated.
func.yaml created.
38. @JosePaumard @delabassee#ASFnFlow
The pom.xml file
The right versions:
<properties>
<maven.compiler.source>9</maven.compiler.source>
<maven.compiler.target>9</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<fdk.version>1.0.72</fdk.version>
</properties>
39. @JosePaumard @delabassee#ASFnFlow
The pom.xml file
The dependencies:
<dependency>
<groupId>com.fnproject.fn</groupId>
<artifactId>api</artifactId>
<version>${fdk.version}</version>
</dependency>
<dependency>
<groupId>com.fnproject.fn</groupId>
<artifactId>flow-runtime</artifactId>
<version>${fdk.version}</version>
</dependency>
40. @JosePaumard @delabassee#ASFnFlow
The pom.xml file
The repository:
<repository>
<id>fn-release-repo</id>
<url>https://dl.bintray.com/fnproject/fnproject</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
41. @JosePaumard @delabassee#ASFnFlow
One last point
Fn is building the function image in a separate container
with its own Maven
configured with access to its own repository
42. @JosePaumard @delabassee#ASFnFlow
A first function
package org.paumard.oc2018.firstFunction;
public class Echo {
public String echo(String input) {
String name = (input == null || input.isEmpty()) ? "world" : input;
return "Hello, " + name + "!";
}
}
44. @JosePaumard @delabassee#ASFnFlow
Deploying your first function
Fn CLI takes care of the function deployment
# fn deploy –-app first-app --local firstfunction
Deploying firstfunction to app: first-app
Bumped to version 0.0.53
Building image fndemouser/firstfunction:0.0.53 .....
Updating function firstfunction using image fndemouser/first-app:0.0.53...
45. @JosePaumard @delabassee#ASFnFlow
Deploying your first function
Fn CLI takes care of the function deployment
This deployment may take some time…
Because Fn is doing many things under the hood
# fn deploy –-app first-app --local firstfunction
Deploying firstfunction to app: first-app
Bumped to version 0.0.53
Building image fndemouser/firstfunction:0.0.53 .....
Updating function firstfunction using image fndemouser/first-app:0.0.53...
46. @JosePaumard @delabassee#ASFnFlow
Deploying your first function
Let us run in verbose mode
# fn --verbose deploy –-app first-app --local firstfunction
Deploying firstfunction to app: first-app
Bumped to version 0.0.53
Building image fndemouser/firstfunction:0.0.53 .....
FN_REGISTRY: fndemouser
Current Context: default
Sending build context to Docker daemon 22.02kB
Step 1/11 : FROM fnproject/fn-java-fdk-build:jdk9-1.0.72 as build-stage
---> b6ccfda3fe63
Step 2/11 : WORKDIR /function
---> Using cache
---> c17fc8ffe44c
Step 3/11 : ENV MAVEN_OPTS -Dhttp.proxyHost= -Dhttp.proxyPort= -Dhttps.proxyHost= -
Dhttps.proxyPort= -Dhttp.nonProxyHosts= -Dmaven.repo.local=/usr/share/maven/ref/repository
---> Using cache
---> 8fc66a3f7245
842bed937b9
47. @JosePaumard @delabassee#ASFnFlow
Deploying your first function
Let us run in verbose mode
Step 4/11 : ADD pom.xml /function/pom.xml
---> Using cache
---> 1cdf0a511da1
Step 5/11 : RUN ["mvn", "package", "dependency:copy-dependencies", "-DincludeScope=runtime", "-
DskipTests=true", "-Dmdep.prependGroupId=true", "-DoutputDirectory=target", "--fail-never"]
---> Using cache
---> 3c9c6b613843
Step 6/11 : ADD src /function/src
---> Using cache
---> 8842bed937b9
Step 7/11 : RUN ["mvn", "package"]
---> Running in 27c78d8e9bd3
48. @JosePaumard @delabassee#ASFnFlow
Deploying your first function
Let us run in verbose mode
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------< org.paumard:main-function >----------------------
[INFO] Building main-function 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ main-function ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ main-function ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /function/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ main-function ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /function/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ main-function ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ main-function ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ main-function ---
[INFO] Building jar: /function/target/main-function-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 42.379 s
[INFO] Finished at: 2018-10-18T14:33:09Z
[INFO] ------------------------------------------------------------------------
49. @JosePaumard @delabassee#ASFnFlow
Deploying your first function
Let us run in verbose mode
Removing intermediate container 27c78d8e9bd3
---> 85e15d82caf4
Step 8/11 : FROM fnproject/fn-java-fdk:jdk9-1.0.72
---> d23b2ab9ca0a
Step 9/11 : WORKDIR /function
---> Using cache
---> 6172132f0ccb
Step 10/11 : COPY --from=build-stage /function/target/*.jar /function/app/
---> cc5f53168459
Step 11/11 : CMD ["org.paumard.oc2018.firstFunction.Echo::echo"]
---> Running in 094ae9918e3e
Removing intermediate container 094ae9918e3e
---> e2e55466ff99
Successfully built e2e55466ff99
Successfully tagged fndemouser/firstfunction:0.0.56
52. @JosePaumard @delabassee#ASFnFlow
Checking the deployment
Check the apps
Check the functions
$ fn list apps
NAME
fn-primes
myapp
travel-booking
$ fn list functions fn-primes
NAME IMAGE
primefunction fndemouser/primefunction:0.0.36
53. @JosePaumard @delabassee#ASFnFlow
Checking the deployment
Check the triggers
$ fn list triggers fn-primes
FUNCTION NAME TYPE SOURCE ENDPOINT
primefunction prime-trigger http /is-prime http://localhost:8080/t/fn-primes/is-prime
56. @JosePaumard @delabassee#ASFnFlow
Function Client
Writing a function client is a matter of writing an HTTP client
We have a nice API for that in Java 11 (*)
https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html
60. @JosePaumard @delabassee#ASFnFlow
Fn Flow
• For long-running, reliable, scalable functions with
primitives for fork-join, chaining, delays & error handling
• Java support « based » on Java CompletableFuture API
• Additonal languages support on the way
• Work in progress