Repository: camel Updated Branches: refs/heads/master 89ba56d3d -> 60675efc3
Add ServiceCall EIP documentation Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/60675efc Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/60675efc Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/60675efc Branch: refs/heads/master Commit: 60675efc3ac420b35da219542607bdc01e9f9598 Parents: 89ba56d Author: lburgazzoli <lburgazz...@gmail.com> Authored: Tue Apr 18 13:09:12 2017 +0200 Committer: lburgazzoli <lburgazz...@gmail.com> Committed: Tue Apr 18 13:09:30 2017 +0200 ---------------------------------------------------------------------- .../src/main/docs/eips/serviceCall-eip.adoc | 420 +++++++++++++++++++ 1 file changed, 420 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/60675efc/camel-core/src/main/docs/eips/serviceCall-eip.adoc ---------------------------------------------------------------------- diff --git a/camel-core/src/main/docs/eips/serviceCall-eip.adoc b/camel-core/src/main/docs/eips/serviceCall-eip.adoc new file mode 100644 index 0000000..35965ea --- /dev/null +++ b/camel-core/src/main/docs/eips/serviceCall-eip.adoc @@ -0,0 +1,420 @@ +## Service Call EIP + +The serviceCall EIP allows to call remote services in a distributed system. The service to call is looked up in a service registry of some sorts such as Kubernetes, Consul, Etcd, Zookeeper, DNS. The EIP separates the configuration of the service registry from the calling of the service. + +When calling a service you may just refer to the name of the service in the EIP as shown below: + +[source,java] +.Java DSL +---- +from("direct:start") + .serviceCall("foo") + .to("mock:result"); +---- + +[source,xml] +.XML DSL +---- +<camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:start"/> + <serviceCall name="foo"/> + <to uri="mock:result"/> + </route> +</camelContext> +---- + +Camel will then: + +* search for a service call configuration from the Camel context and registry +* lookup a service with the name ```foo``` from an external service registry +* filter the servers +* select the server to use +* build a Camel URI using the choosen server info + +By default the Service Call EIP uses camel-http4 so assuming that the selected service instance runs on host ```myhost.com``` on port ```80```, the computed Camel URI will be: + +[source] +---- + http4:myhost.com:80 +---- + +### Service Name to Camel URI Examples + +It is often needed to build more complex Camel URI which may include options or paths which is possible through different options:name: value + +* The *service name* supports a limited uri like syntax, here some examples ++ +[width="100%",cols="25%a,75%a",options="header"] +|=== +|Name |Resolution + +|foo | http4://host:port +|foo/path | http4://host:port/path +|foo/path?foo=bar | http4://host:port/path?foo=bar +|=== ++ +[source,java] +---- +from("direct:start") + .serviceCall("foo/hello") + .to("mock:result"); +---- ++ +* If you wan to have more control over the uri construction, you can use the *uri* directive: ++ +[width="100%",cols="25%a,40%a,35%a",options="header"] +|=== +|Name | URI | Resolution + +|foo | undertow:http://foo/hellp | undertow:http://host:port/hello +|foo | undertow:http://foo.host:foo.port/hello | undertow:http://host:port/hello +|=== ++ +[source,java] +---- +from("direct:start") + .serviceCall("foo", "undertow:http://foo/hello") + .to("mock:result"); +---- ++ +* Advanced users can have full control over the uri construction through expressions: ++ +[source,java] +---- +from("direct:start") + .serviceCall() + .name("foo") + .expression() + .simple("undertow:http://${header.CamelServiceCallServiceHost}:${header.CamelServiceCallServicePort}/hello"); +---- + +### Configuring Service Call + +The Service Call EIP can be configured through the following options: + +[width="100%",cols="3,1m,6",options="header"] +|======================================================================= +| Name | Java Type | Description +| name | String | *Required* Sets the name of the service to use +| uri | String | The uri of the endpoint to send to. +| component | String | The component to use. +| pattern | ExchangePattern | Sets the optional ExchangePattern used to invoke this endpoint +| configurationRef | String | Refers to a ServiceCall configuration to use +| serviceDiscoveryRef | String | Sets a reference to a custom ServiceDiscovery to use. +| serviceDiscovery | ServiceDiscovery | Sets the ServiceDiscovery to use ([.underline]_Java DSL only_). +| serviceFilterRef | String | Sets a reference to a custom ServiceFilter to use. +| serviceFilter | ServiceFilter | Sets the ServiceFilter to use ([.underline]_Java DSL only_). +| serviceChooserRef | String | Sets a reference to a custom ServiceChooser to use. +| serviceChooser | ServiceChooser | Sets the ServiceChooser to use ([.underline]_Java DSL only_). +| loadBalancerRef | String | Sets a reference to a custom LoadBalancer to use. +| loadBalancer | LoadBalancer | Sets the LoadBalancer to use ([.underline]_Java DSL only_). +| expressionRef | String | Set a reference to a custom Expression to use. +| expression | Expression | Set the Expression to use to compute the Camel URI ([.underline]_Java DSL only_). +|======================================================================= + +In addition to ref/binding configuration style you can leverage specific configuration DSL to customize specific options: + +* *Consul Service Discovery:* ++ +To leverage Consul for Service Discover, maven users will need to add the following dependency to their pom.xml ++ +[source,xml] +---- +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-consul</artifactId> + <!-- use the same version as your Camel core version --> + <version>x.y.z</version> +</dependency> +---- ++ +*Available options:* ++ +[width="100%",cols="3,1m,6",options="header"] +|======================================================================= +| Name | Java Type | Description +| url | String | The Consul agent URL +| datacenter | String | The data center +| aclToken | String | Sets the ACL token to be used with Consul +| userName | String | Sets the username to be used for basic authentication +| password | String | Sets the password to be used for basic authentication +| connectTimeoutMillis | Long | Connect timeout for OkHttpClient +| readTimeoutMillis | Long | Read timeout for OkHttpClient +| writeTimeoutMillis | Long | Write timeout for OkHttpClient +|======================================================================= ++ +[source,java] +.Example +---- +from("direct:start") + .serviceCall("foo") + .consulServiceDiscovery() + .url("http://consul-cluster:8500") + .datacenter("neverland") + .end() + .to("mock:result"); +---- + +* *DNS Service Discovery:* ++ +To leverage DNS for Service Discover, maven users will need to add the following dependency to their pom.xml ++ +[source,xml] +---- +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-dns</artifactId> + <!-- use the same version as your Camel core version --> + <version>x.y.z</version> +</dependency> +---- ++ +[source,xml] +.XML DSL +---- +<camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:start"/> + <serviceCall name="foo"> + <consulServiceDiscovery url="http://consul-cluster:8500" datacenter="neverland"/> + </serviceCall> + <to uri="mock:result"/> + </route> +</camelContext> +---- + ++ +*Available options:* ++ +[width="100%",cols="3,1m,6",options="header"] +|======================================================================= +| Name | Java Type | Description +| proto | String | The transport protocol of the desired service, default "_tcp" +| domain | String | The user name to use for basic authentication +|======================================================================= ++ +[source,java] +.Example +---- +from("direct:start") + .serviceCall("foo") + .dnsServiceDiscovery("my.domain.com") + .to("mock:result"); +---- ++ +[source,xml] +.XML DSL +---- +<camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:start"/> + <serviceCall name="foo"> + <dnsServiceDiscovery domain="my.domain.com"/> + </serviceCall> + <to uri="mock:result"/> + </route> +</camelContext> +---- + +* *Etcd Service Discovery:* ++ +To leverage Etcd for Service Discover, maven users will need to add the following dependency to their pom.xml ++ +[source,xml] +---- +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-etcd</artifactId> + <!-- use the same version as your Camel core version --> + <version>x.y.z</version> +</dependency> +---- ++ +*Available options:* ++ +[width="100%",cols="3,1m,6",options="header"] +|======================================================================= +| Name | Java Type | Description +| uris | String | The URIs the client can connect to +| userName | String | The user name to use for basic authentication +| password | String | The password to use for basic authentication +| timeout | Long | To set the maximum time an action could take to complete +| servicePath | String | The path to look for for service discovery, default "/services" +| type | String | To set the discovery type, valid values are on-demand and watch. +|======================================================================= ++ +[source,java] +.Example +---- +from("direct:start") + .serviceCall("foo") + .etcdServiceDiscovery() + .uris("http://etcd1:4001,http://etcd2:4001") + .servicePath("/camel/services") + .end() + .to("mock:result"); +---- ++ +[source,xml] +.XML DSL +---- +<camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:start"/> + <serviceCall name="foo"> + <etcdServiceDiscovery uris="http://etcd1:4001,http://etcd2:4001" servicePath="/camel/services"/> + </serviceCall> + <to uri="mock:result"/> + </route> +</camelContext> +---- + +* *Kubernetes Service Discovery:* ++ +To leverage Kubernetes for Service Discover, maven users will need to add the following dependency to their pom.xml ++ +[source,xml] +---- +<dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-kubernetes</artifactId> + <!-- use the same version as your Camel core version --> + <version>x.y.z</version> +</dependency> +---- ++ +*Available options:* ++ +[width="100%",cols="3,1m,6",options="header"] +|======================================================================= +| Name | Java Type | Description +| lookup | String | How to perform service lookup. Possible values: client, dns, environment +| apiVersion | String | Kubernetes API version when using client lookup +| caCertData | String | Sets the Certificate Authority data when using client lookup +| caCertFile | String | Sets the Certificate Authority data that are loaded from the file when using client lookup +| clientCertData | String | Sets the Client Certificate data when using client lookup +| clientCertFile | String | Sets the Client Certificate data that are loaded from the file when using client lookup +| clientKeyAlgo | String | Sets the Client Keystore algorithm, such as RSA when using client lookup +| clientKeyData | String | Sets the Client Keystore data when using client lookup +| clientKeyFile | String | Sets the Client Keystore data that are loaded from the file when using client lookup +| clientKeyPassphrase | String | Sets the Client Keystore passphrase when using client lookup +| dnsDomain | String | Sets the DNS domain to use for dns lookup +| namespace | String | The Kubernetes namespace to use. By default the namespace's name is taken from the environment variable KUBERNETES_MASTER +| oauthToken | String | Sets the OAUTH token for authentication (instead of username/password) when using client lookup +| username | String | Sets the username for authentication when using client lookup +| password | String | Sets the password for authentication when using client lookup +| trustCerts | Boolean | Sets whether to turn on trust certificate check when using client lookup +|======================================================================= ++ +[source,java] +.Java DSL +---- +from("direct:start") + .serviceCall("foo") + .kubernetesServiceDiscovery() + .lookup("dns") + .namespace("myNamespace") + .dnsDomain("my.domain.com") + .end() + .to("mock:result"); +---- ++ +[source,xml] +.XML DSL +---- +<camelContext xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:start"/> + <serviceCall name="foo"> + <kubernetesServiceDiscovery lookup="dns" namespace="myNamespace" dnsDomain="my.domain.com"/> + </serviceCall> + <to uri="mock:result"/> + </route> +</camelContext> +---- + +### Shared configurations + +The Service CAll EIP can be configured straight on the route definition or through shared configurations, here an example with two configurations registered in the Camel Context: + +[source,java] +.Example +---- +ServiceCallConfigurationDefinition globalConf = new ServiceCallConfigurationDefinition(); +globalConf.setServiceDiscovery( + name -> Arrays.asList( + new DefaultServiceDefinition(name, "my.host1.com", 8080), + new DefaultServiceDefinition(name, "my.host2.com", 443)) +); +globalConf.setServiceChooser( + list -> list.get(ThreadLocalRandom.current().nextInt(list.size())) +); + +ServiceCallConfigurationDefinition httpsConf = new ServiceCallConfigurationDefinition(); +httpsConf.setServiceFilter( + list -> list.stream().filter(s -> s.getPort() == 443).collect(toList()) +); + +getContext().setServiceCallConfiguration(globalConf); +getContext().addServiceCallConfiguration("https", httpsConf); +---- + +Each Service Call definition and configuration will inheriths from the ```globalConf``` which can be see as default configuration, then you can reference the ```httpsConf``` in your rute as follow: + +[source,java] +.Example +---- +rom("direct_:start") + .serviceCall() + .name("foo") + .serviceCallConfiguration("https") + .end() + .to("mock:result"); +---- + +This route will leverages the service discovery and service chooser from ```globalConf``` and the service filter from ```httpsConf``` but you can override any of them if needed straight on the route: + +[source,java] +.Example +---- +rom("direc_:start") + .serviceCall() + .name("foo") + .serviceCallConfiguration("https") + .serviceChooser(list -> list.get(0)) + .end() + .to("mock:result"); +---- + +### Spring Boot support + +In a Spring-Boot application you can externalize most of the configuration options: + +[source,properties] +.application.properties +---- +# this can be configured stright tot he route and it has been included to show +# property placeholders support +service.name = foo + +# this property is not mandatory and it has been included to show how to configure +# the service discovery implementation provided by camel-consul +camel.cloud.consul.service-discovery.url = http://localhost:8500 + +# Add a static list of servers for the service named foo +camel.cloud.service-discovery.services[foo] = host1.static:8080,host2.static:8080 +---- + +[source,java] +.Routes +---- +@Component +public class MyRouteBuilder implements RouteBuilder { + @Override + public void configure() throws Exception { + from("direct:start") + .serviceCall("{{service.name}}"); + } +} +----