[ 
https://issues.apache.org/jira/browse/CAMEL-10638?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15794495#comment-15794495
 ] 

Luca Burgazzoli commented on CAMEL-10638:
-----------------------------------------

[~davsclaus]

I've committed a final refactor of the EIP on my fork, here the diff: 
https://github.com/apache/camel/compare/master...lburgazzoli:CAMEL-10638

The main difference against current setup is that the specific etcd/ribbon/dns 
configuration have disappeared and replaced by component configuration so i.e. 
a ribbon setup may looks like:

{code:xml}
<beans xmlns="http://www.springframework.org/schema/beans";
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://camel.apache.org/schema/spring
         http://camel.apache.org/schema/spring/camel-spring.xsd";>

  <!-- setup a static ribbon server list with these 2 servers to start with -->
  <bean id="discovery" 
class="org.apache.camel.impl.cloud.StaticServiceDiscovery">
    <property name="servers" value="localhost:9090,localhost:9091"/>
  </bean>

  <bean id="balancer" 
class="org.apache.camel.component.ribbon.cloud.RibbonLoadBalancer">
    <constructor-arg index="0">
      <bean class="org.apache.camel.component.ribbon.RibbonConfiguration"/>
    </constructor-arg>
  </bean>

  <camelContext xmlns="http://camel.apache.org/schema/spring";>

    <!-- service call configuration to use ribbon -->
    <serviceCallConfiguration id="ribbon" loadBalancerRef="balancer" 
serviceDiscoveryRef="discovery"/>

    <route>
      <from uri="direct:start"/>
      <serviceCall name="myService"/>
      <to uri="mock:result"/>
    </route>

    <route>
      <from uri="jetty:http://localhost:9090"/>
      <to uri="mock:9090"/>
      <transform>
        <constant>9090</constant>
      </transform>
    </route>

    <route>
      <from uri="jetty:http://localhost:9091"/>
      <to uri="mock:9091"/>
      <transform>
        <constant>9091</constant>
      </transform>
    </route>
  </camelContext>

</beans>
{code}

I've also created a org.apache.camel.cloud package which contains basic 
building blocks for service discovery, load balancing and so on one can reuse, 
the service call then leverage such interfaces.

May I kindly ask you for a quick review ?

> Refactor ServiceCall EIP
> ------------------------
>
>                 Key: CAMEL-10638
>                 URL: https://issues.apache.org/jira/browse/CAMEL-10638
>             Project: Camel
>          Issue Type: Improvement
>          Components: camel-consul, camel-core, camel-etcd, camel-kubernetes, 
> camel-ribbon, camel-spring-cloud
>            Reporter: Luca Burgazzoli
>            Assignee: Luca Burgazzoli
>             Fix For: 2.19.0
>
>
> As today the ServiceCall is implemented loading a ProcessorFactory using a 
> ServiceLoader like system but this may cause issues as if you have multiple 
> components providing an implementation of the ServiceCall SPI so i.e. if you 
> have both consul and etcd components in the classpath, the following set-up 
> will be initialized with the first ServiceCall SPI found in the classpath 
> regardless of the consulConfiguration/etcdConfiguration:
> {code:java}
> from("timer:consul?period=1s")
>     .serviceCall()
>         .name("consul")
>         .consulConfiguration()
>         ...
>     .end();
> from("timer:etcd?period=1s")
>     .serviceCall()
>         .name("etcd")
>         .etcdConfiguration()
>         ...
>     .end();
> {code}
> It may be better to have a different way to set-up the ServiceCall so that 
> each element (server discovery, load balancer, server chooser) is provided 
> instead of created by the ServiceCall ProcessorFactory.
> A possible - high level - definition of the classes may look like:
> {code:java}
> interface ServiceCallLoadBalancer extends Processor {
> }
> interface ServiceCallServer {
>     String getServiceId();
>     String getHost();
>     int getPort();
>     Map<String, String> getMetadata();    
> }
> interface ServiceCallServerDiscovery {
>     List<ServiceCallServer> getInitialListOfServers(String serviceId);
>     List<ServiceCallServer> getUpdatedListOfServers(String serviceId); 
> }
> interface ServiceCallServerDiscoveryAware {
>     void setServerDiscovery(ServiceCallServerDiscovery serverDiscovery);
> }
> interface ServiceCallServerChooser {
>     ServiceCallServer choose(List<ServiceCallServer> serverList)
> }
> interface ServiceCallServerChooserAware {
>     void setServerChooser(ServiceCallServerChooser serverDiscovery);
> }
> class ServiceCallConfiguration {
>     public void setServiceId(String serviceid);
>     public void setComponent(String component);
>     public void setUri(String uri);
>     public void setExpression(Expression expression);
>     public void setLoadBalancer(String loadBalancerRef);
>     public void setLoadBalancer(ServiceCallLoadBalancer<ServiceCallServer> 
> loadBalancer);
>     public void setServerDiscovery(String serverDiscoveryRef);
>     public void 
> setServerDiscovery(ServiceCallServerDiscovery<ServiceCallServer> 
> serverDiscovery);
>     public void setServerChooser(String serverChooserRef);
>     public void setServerChooser(ServiceCallServerChooser<ServiceCallServer> 
> serverChooser);
> }
> class ServiceCallDefinition extends ServiceCallConfiguration {
>     public void setConfiguration(ServiceCallConfiguration configuration);
>     public void setConfiguration(String configurationRef);
> }
> class DefaultServiceCallLoadBalancer implements CamelContextAware, 
> ServiceCallServerDiscoveryAware, ServiceCallServerChooserAware, 
> ServiceCallLoadBalancer {
>     ...
> }
> {code}
> The configuration part will be similar to the one we have today except the 
> etcdConfiguration/consulConfiguration/etc will be removed in favor of a 
> generic one, like:
> {code:java}
> ServiceCallServerDiscovery sd = new EtcdServiceCallServerDiscovery(conf);
> from("timer:consul?period=1s")
>     .serviceCall()
>         .name("consul")
>         .loadBalancer("my-load-balancer")
>         .serverDiscovery(sd)
>         .serverChooser(servers -> servers.get(0))
>         .end();
> {code}
> There will be a default implementation of the load balancer so defining it 
> may not be needed but environment like spring-cloud could provide a different 
> implementation.
> [~davsclaus] what do you think ?



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to