Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Service Discovery. Spring Cloud Internals

There is a problem of finding the correct operating services In a distributed systems with dynamic configuration. Currently, there are designed one and more solutions for the ever-changing storage configuration. It should be mentioned at least Netflix Eureka, Consul, etcd or good old Zookeeper. Spring Cloud project allows to integrate some of these solutions to your project and provides powerful solutions for typical problems. However, on the way to unicorns not the most obvious subtleties of implementation and associated problems of use in real projects wait for a developer.

This talk will review the internal structure SpringCloud, implementation of Client-Side Service Discovery pattern, and specific details of concrete implementations on the example of the official libraries and the author's own library.

  • Be the first to comment

Service Discovery. Spring Cloud Internals

  1. 1. Spring Cloud Internals Service Discovery
  2. 2. About me Architect @ /aatarasoff /aatarasoff habrahabr.ru/aatarasoff developerblog.info 2
  3. 3. Agenda Today 1. New reality - new problems 2. What service discovery means? 3. Dive into Spring Cloud service discovery pattern implementation 4. Tips and tricks during the session 5. Own experience as a conclusion 3
  4. 4. What is the problem? 4
  5. 5. Database ESB (service layer) Service Service Service Service Hardware Load Balancer Alfa-Click 2.0 (JSF/Weblogic) 5
  6. 6. Big App Static resource Database Remote EJB 6
  7. 7. Simple Binding Small number of resources Static host and port binding Rare reconfiguration 7
  8. 8. insert into resources_table values (key, endpoint) 8
  9. 9. final Properties props = new Properties(); final Context context = new InitialContext(props); // lookup Foo bean = context.lookup("ejb:myejb//Foo!org.myapp.Foo"); bean.call(); 9
  10. 10. final Properties props = new Properties(); final Context context = new InitialContext(props); // lookup Foo bean = context.lookup("ejb:myejb//Foo!org.myapp.Foo"); //do something bean.call(); 10
  11. 11. Big Frontend App 11
  12. 12. Big Frontend App Small App Small App Small App 12
  13. 13. Small App UI API 1 API 2 13
  14. 14. ESB Services API 1 API 2 API 4 UIMobile Mongo DB 14
  15. 15. API API instance API instance API instance 15
  16. 16. Some API Another API Instance 1 Another API Instance 2 Another API Instance 3 ? 16
  17. 17. - hosts: dc1-rest-api roles: - { role: api, name: transactions-api, service_port: 9081 } - { role: api, name: cards-api, port: 8081 } - { role: api, name: customers-api, port: 9091 } dc1-rest-api <ip_address_1> <ip_address_2> ... Static Configuration 17
  18. 18. { "id": "/retail-online-bank/middle/transactions-api", "cpus": 1, "mem": 1024, "instances": 5, "container": { "docker": { "image": "docker/retail-online-bank-transactions-api:1.17.0", "portMappings": [ { "containerPort": 8080, "servicePort": 0 } ] } } } Dynamic Configuration (PAAS) 18
  19. 19. Service Discovery What instance we can call? 19
  20. 20. 20
  21. 21. Remote API Calls 21
  22. 22. Five parallel service calls 22
  23. 23. S1 S2 S3 S4 S5 23
  24. 24. Client call S1 S2 S3 S4 S5 24
  25. 25. Client call S1 S2 S3 S4 S5 25
  26. 26. Five parallel service calls 26
  27. 27. p = 0.99 p – the probability of success for one service 27
  28. 28. P = p5 = (0.99)5 ≈ 0.95 p – the probability of success for one service 28
  29. 29. Service Discovery What instance we can call? What instance is better for call? 29
  30. 30. Service Discovery What instance we can call? What instance is better for call? How we can increase probability of success for one call? 30
  31. 31. S1 S2 S3 S4 S5 31
  32. 32. STATE S1 S2 S3 S4 S5 S1 S2 S3 S4 S5 32
  33. 33. STATE FILTER S1 S2 S3 S1 S2 S3 S4 S5 S1 S2 S3 S4 S5 33
  34. 34. STATE FILTER S2 S4 Other DC S1 S2 S3 S4 S5 S1 S2 S3 S4 S5 34
  35. 35. STATE FILTER S2 S4 Other DC S1 S2 S3 S4 S5 S1 S2 S3 S4 S5 ? 35
  36. 36. Service Service Service Service Service STATE FILTER S2 S4 RULE S2 S1 S2 S3 S4 S5 S1 S2 S3 S4 S5 36
  37. 37. Service Service Service Service Service STATE FILTER S2 S4 RULE S2 Client S1 S2 S3 S4 S5 call S1 S2 S3 S4 S5 37
  38. 38. Client-Side Service Discovery 38
  39. 39. Server-Side Service Discovery 39
  40. 40. Server-Side Client-Side VS Dummy client Language/Library tolerance Single Responsibility Principle More complex and smart decision implementation Avoid point of failure Flexibility Hard to implement something complex and smart One more point of failure Very good implementation is required Lock on libraries Hard to make changes 40
  41. 41. Spring Cloud Tools for building common patterns in distributed systems Part of Spring Boot Implements Client-Side Service Discovery Pattern 41
  42. 42. Rollback 42
  43. 43. S1 S2 S3 S4 S5 ? How we get them all? 43
  44. 44. Service Registry? Database Properties File Environment Variables 44
  45. 45. Service Registry? Database Properties File Environment Variables 45
  46. 46. Service Registry Netflix Eureka Consul etcd Zookeeper … 46
  47. 47. Leader Master Master Leader-Election Quorum (n + 1)/2 Distributed Locks 47
  48. 48. Peer Peer Peer Eureka is not the same 48
  49. 49. Client/Slave Leader Master Master Client/Slave Client/Slave horizontal scaling 49
  50. 50. Service A Leader Master Master Service B Service C register 50
  51. 51. Service A Leader Master Master Service B Service C health check 51
  52. 52. Service A Leader Master Master Service B Service C heartbeat 52
  53. 53. Service A Leader Master Master Service B Service C health check 53
  54. 54. Service A Leader Master Master Service B Service C health check 54
  55. 55. Service A Leader Master Master Service B Service C deregister 55
  56. 56. Service A Leader Master Master Service B Service C deregister graceful shutdown 56
  57. 57. Spring Cloud Core Eureka Consul Marathon 57
  58. 58. Spring Cloud Core Eureka Consul Marathon Reference/Native implementation Most complex load balancing 58
  59. 59. Spring Cloud Core Eureka Consul Marathon Out of the box PaaS 59
  60. 60. 60
  61. 61. 61 { "host": "server1", "ports": [ 20688 ], "ipAddresses": [ { "ipAddress": "172.17.0.21", "protocol": "IPv4" } ], "appId": "/retail-online-bank/middle/a2a-transactions-api", "healthCheckResults": [ { "alive": true } ] }
  62. 62. Spring Cloud Core Eureka Consul Marathon Out of the box PaaS One tool for deployment and configuration storage Own library 62
  63. 63. Deep Dive 1. Discovery 63
  64. 64. ... @EnableDiscoveryClient ... public class Application { @Autowired private DiscoveryClient discoveryClient; public List<String> services() { return discoveryClient.getServices(); } } 64
  65. 65. ... @EnableDiscoveryClient ... public class Application { @Autowired private DiscoveryClient discoveryClient; public List<String> services() { return discoveryClient.getServices(); } } 65
  66. 66. public interface DiscoveryClient { public ServiceInstance getLocalServiceInstance(); public List<ServiceInstance> getInstances(String serviceId); public List<String> getServices(); } 66
  67. 67. public interface DiscoveryClient { public ServiceInstance getLocalServiceInstance(); public List<ServiceInstance> getInstances(String serviceId); public List<String> getServices(); } 67
  68. 68. public interface DiscoveryClient { public ServiceInstance getLocalServiceInstance(); public List<ServiceInstance> getInstances(String serviceId); public List<String> getServices(); } 68
  69. 69. Eureka Implementation 69
  70. 70. Eureka Cluster (Zone 1) appname: app1 virtualHostName: app eureka: client: serviceUrl: defaultZone: ${ZONE1_EUREKA_URL} Eureka Cluster (Zone 2) appname: app2 virtualHostName: app serviceId -> virtualHostName 70
  71. 71. Eureka Cluster (Zone 1) appname: app1 virtualHostName: app eureka: client: serviceUrl: defaultZone: ${ZONE1_EUREKA_URL} zone2: ${ZONE2_EUREKA_URL} availabilityZones: zone1,zone2 Eureka Cluster (Zone 2) appname: app2 virtualHostName: app 71
  72. 72. EurekaClientEurekaDiscoveryClient serviceId 72
  73. 73. virtualHostName Applications EurekaClientEurekaDiscoveryClient serviceId 73
  74. 74. Eureka Cluster (Zone 1) appname: app1 virtualHostName: app virtualHostName Applications EurekaClient fetch EurekaDiscoveryClient serviceId eureka: client: registryFetchIntervalSeconds: 5 (30) 74
  75. 75. Eureka Cluster (Zone 1) appname: app1 virtualHostName: app virtualHostName Applications EurekaClient fetch and filter EurekaDiscoveryClient serviceId eureka: client: registryFetchIntervalSeconds: 5 (30) filterOnlyUpInstances: true (true) 75
  76. 76. Marathon Implementation 76
  77. 77. Mesos Cluster (DC 1) taskId: {random} appId: app1 spring: cloud: marathon: host: ${MARATHON_HOST} port: ${MARATHON_PORT} Mesos Cluster (DC 2) taskId: {random} appId: app1 serviceId -> appId 77
  78. 78. Mesos Cluster (DC 1) taskId: {random} appId: app1 spring: cloud: marathon: host: ${MARATHON_HOST} port: ${MARATHON_PORT} Mesos Cluster (DC 2) taskId: {random} appId: app1 serviceId -> appId <- - - - there is no failover to another dc 78
  79. 79. Mesos Cluster (DC 1) taskId: {random} appId: app1 task = instance MarathonClient fetch tasks for apps MarathonDiscoveryClient serviceId spring: cloud: marathon: <no app cache> <no property> only healthy tasks 79
  80. 80. Is it success? 80
  81. 81. @Autowired private LoadBalancerClient loadBalancer; @RequestMapping("/instance") public ServiceInstance instance() { return loadBalancer.choose(serviceId); } 81
  82. 82. @Autowired private LoadBalancerClient loadBalancer; @RequestMapping("/instance") public ServiceInstance instance() { return loadBalancer.choose(serviceId); } ? 82
  83. 83. @Autowired private LoadBalancerClient loadBalancer; @RequestMapping("/instance") public ServiceInstance instance() { return loadBalancer.choose(serviceId); } 83 1. ServiceInstance 2. null 3. Error
  84. 84. @Autowired private LoadBalancerClient loadBalancer; @RequestMapping("/instance") public ServiceInstance instance() { return loadBalancer.choose(serviceId); } 84 1. ServiceInstance 2. null 3. Error
  85. 85. Where it is used? Hypermedia Links Dynamic Routes for Edge Server DiscoveryClient health check in actuator is based on it Less than you expect, right? 85
  86. 86. Deep Dive 1. Discovery 2. Balance it 86
  87. 87. Load Balancer Client Based on Netflix Ribbon Ribbon may be used with or without service registry 87
  88. 88. Service Service Service Service Service STATE FILTER S2 S4 RULE S2 Client S1 S2 S3 S4 S5 call S1 S2 S3 S4 S5 88
  89. 89. Service Service Service Service Service FILTER S2 S4 RULE S2 Client S1 S2 S3 S4 S5 call S1 S2 S3 S4 S5 Server List 89
  90. 90. Service Service Service Service Service S2 S4 RULE S2 Client S1 S2 S3 S4 S5 call S1 S2 S3 S4 S5 Server List Filter Chain 90
  91. 91. Service Service Service Service Service S2 S4 S2 LoadBalancerClient S1 S2 S3 S4 S5 call S1 S2 S3 S4 S5 Server List Filter Chain Rule 91
  92. 92. Ribbon Server List Static Configuration Based Discovery Based 92
  93. 93. Spring Cloud Ribbon Configure Bean Lifecycle Spring native configuration 93
  94. 94. test-service: #service name ribbon: #namespace listOfServers: host:8080,anotherHost:8081 ConfigurationBasedServerList 94
  95. 95. test-service: #service name ribbon: #namespace listOfServers: host:8080,anotherHost:8081 public List<Server> getListOfServers() { return derive( clientConfig.get(CommonClientConfigKey.ListOfServers) ); } ConfigurationBasedServerList 95
  96. 96. @Autowired private LoadBalancerClient loadBalancer; @RequestMapping("/url") public String realUrl() throws IOException { return loadBalancer.reconstructURI( instance, new URI("http://"+ serviceId +"/me") ).toString(); } it will be replaced with real host and port 96
  97. 97. @Autowired private LoadBalancerClient loadBalancer; @RequestMapping("/url") public String realUrl() throws IOException { return loadBalancer.reconstructURI( instance, new URI("http://"+ serviceId +"/me") ).toString(); } > curl service:8080/url http://host:8080/me 97
  98. 98. @Autowired private LoadBalancerClient loadBalancer; @RequestMapping("/url") public String realUrl() throws IOException { return loadBalancer.reconstructURI( instance, new URI("http://"+ serviceId +"/me") ).toString(); } > curl service:8080/url http://anotherHost:8080/me 98
  99. 99. Copy-past Implementation 99 Same as DiscoveryClient
  100. 100. Is our instance alive? 100
  101. 101. S1 S2 S3 S4 S5 S2 S4 S2 LoadBalancerClient call S1 S2 S3 S4 S5? 101 Server List Filter Chain Rule
  102. 102. t t + 1 S1 S2 S3 102
  103. 103. t t + 1 S1 S2 S3 ServerList S1 S2 S3 103
  104. 104. t t + 1 S1 S2 S3 ServerList S1S1 S2 S3 104
  105. 105. t t + 1 S1 S2 S3 ServerList S1 S1S1 S2 S3 105
  106. 106. t t + 1 S1 S2 S3 ServerList S1 S1 t + 2 S1 S2 S3 106
  107. 107. S1 S2 S3 S4 S5 S2 S4 S2 LoadBalancerClient call S1 S2 S3 S4 S5Ping -> 107 Server List Filter Chain Rule
  108. 108. Pinger (background thread) LoadBalancer background task force if setServerList() is called 108
  109. 109. Pinger (background thread) LoadBalancer background task force if setServerList() is called IPingStrategy pingServers 109
  110. 110. Pinger (background thread) LoadBalancer background task force if setServerList() is called IPingStrategy pingServers isAlive(server) IPing 110
  111. 111. IPingStrategy SerialPingStrategy int numCandidates = servers.length; boolean[] results = new boolean[numCandidates]; for (int i = 0; i < numCandidates; i++) { results[i] = false; /* Default answer is DEAD. */ if (ping != null) { results[i] = ping.isAlive(servers[i]); } } return results; And what if ping will take a long time? 111
  112. 112. NIWSDiscoveryPing (Eureka) IPing instance.status.equals( InstanceStatus.UP ) ConsulPing (Consul) MarathonPing (Marathon) server.isPassingChecks() server.isPassingChecks() All are fake pings 112
  113. 113. public class MarathonPing implements IPing { @Override public boolean isAlive(Server server) { return server.isHealthChecksPassing(); } } 113
  114. 114. public class MarathonPing implements IPing { @Override public boolean isAlive(Server server) { return server.isHealthChecksPassing(); } } public class MarathonServer extends Server { public boolean isHealthChecksPassing() { return healthChecks.parallelStream() .allMatch(HealthCheckResult::isAlive); } } 114
  115. 115. IPingStrategy ? You may implement your own strategy at your own risk IPing PingUrl public boolean isAlive(Server server) { URL url = constructUrl(server); HttpResponse response = httpClient.execute(createReq(url)); return response.getStatusLine().getStatusCode() == 200; } 115
  116. 116. Reduce fetch interval 116
  117. 117. S1 S2 S3 S4 S5 S2 S4 S2 LoadBalancerClient call S1 S2 S3 S4 S5 Server List Filter Chain -> Rule 117
  118. 118. Eureka Cluster (Zone 1) S1 S2 S3 Eureka Cluster (Zone 2) S4 S5 S6 Client (Zone 1) 118
  119. 119. Eureka Cluster (Zone 1) S1 S2 S3 Eureka Cluster (Zone 2) S4 S5 S6 Client (Zone 1) cheap call 119
  120. 120. Eureka Cluster (Zone 1) S1 S2 S3 Eureka Cluster (Zone 2) S4 S5 S6 Client (Zone 1) expensive call 120
  121. 121. Eureka Cluster (Zone 1) S2 S3 Eureka Cluster (Zone 2) S4 S5 S6 Client (Zone 1) unpredictable S1 121
  122. 122. Eureka Cluster (Zone 1) S1 S2 S3 Eureka Cluster (Zone 2) S4 S5 S6 Client (Zone 1) more guaranteed result 122
  123. 123. FilterZonePreferenceFilter List servers = super.getFilteredServers(); List local = servers.filter(server -> server.zone == zoneFromConfig ); if (!local.isEmpty()) { return local; } return servers; super.getFilteredServers() DynamicServerListLoadBalancer default (local) zone 123
  124. 124. ZoneAffinityFilterZonePreferenceFilter super.getFilteredServers(servers) LoadBalancerStats getZoneSnaphot(servers) 124
  125. 125. S1 S2 S3 S4 S5 S2 S4 S2 LoadBalancerClient call S1 S2 S3 S4 S5LB Stats -> Server List Filter Chain Rule 125
  126. 126. S1 S2 S3 S4 S5 S2 S4 S2 LoadBalancerClient call S1 S2 S3 S4 S5LB Stats -> Server Stats Server List Filter Chain Rule 126
  127. 127. S1 S2 S3 Zone Snapshot Server Stats 127
  128. 128. S1 S2 S3 Zone Snapshot activeConnections activeServers circuitBreakerTrippedCount 128
  129. 129. ZoneAffinityFilterZonePreferenceFilter super.getFilteredServers(servers) LoadBalancerStats enableZoneAffinity? zoneAffinity: maxLoadPerServer: 0.6 maxBlackOutServersPercentage: 0.8 minAvailableServers: 2 129
  130. 130. ZoneAffinityFilterZonePreferenceFilter super.getFilteredServers(servers) ZoneAffinityPredicate filter out instances from other zones 130 zoneAffinity: maxLoadPerServer: 0.6 maxBlackOutServersPercentage: 0.8 minAvailableServers: 2
  131. 131. Eureka Cluster (Zone 1) S1 S2 S3 Eureka Cluster (Zone 2) S4 S5 S6 Client (Zone 1) cheap call 131
  132. 132. ZoneAffinityFilterZonePreferenceFilter super.getFilteredServers(servers) ZoneAffinityPredicate no filter 132 zoneAffinity: maxLoadPerServer: 0.6 maxBlackOutServersPercentage: 0.8 minAvailableServers: 2
  133. 133. Eureka Cluster (Zone 1) S1 Eureka Cluster (Zone 2) S4 S5 S6 Client (Zone 1) 133 S2 S3
  134. 134. Use Eureka. Use zones 134
  135. 135. Define your rules 135
  136. 136. S1 S2 S3 S4 S5 S2 S4 S2 LoadBalancerClient call S1 S2 S3 S4 S5 ? 136 Server List Filter Chain Rule
  137. 137. IRule RoundRobin ZoneAvoidance default Weighted Random BestAvailability AvailabilityFilter 137
  138. 138. IRule RoundRobin ZoneAvoidance Weighted Random BestAvailability AvailabilityFiltering 138
  139. 139. upstream test-marathon-app { server host1 weight=3; server host2 weight=1; server host3 weight=1; } Weighted typically is predefined 139
  140. 140. Weight Task (background thread) Weighted Rule background task LoadBalancerStats calculate serverWeight = summ(avgServerResponseTime)- avgServerResponseTime 140
  141. 141. Weight Task (background thread) Weighted Rule background task LoadBalancerStats calculate serverWeight = summ(avgServerResponseTime)- avgServerResponseTime 141 More response time -> less weight
  142. 142. 142 Slow Instance Fast Instance 100 ms 10 ms
  143. 143. 143 Slow Instance Fast Instance 100 ms 10 ms5 000 requests
  144. 144. 144 Slow Instance Fast Instance 100 ms 10 ms5 000 requests Round Robin Rule Slow: 2500 and Fast: 2500 Average time: 70
  145. 145. 145 Slow Instance Fast Instance 100 ms 10 ms5 000 requests Round Robin Rule Slow: 2500 and Fast: 2500 Average time: 70
  146. 146. 146 Slow Instance Fast Instance 100 ms 10 ms5 000 requests Round Robin Rule Slow: 2500 and Fast: 2500 Average time: 70 Weighted Rule Slow: 634 and Fast: 4366 Average time: 27
  147. 147. 147 Slow Instance Fast Instance 100 ms 10 ms1 000 requests Round Robin Rule Slow: 500 and Fast: 500 Average time: 70 Weighted Rule ? ?
  148. 148. 148 Slow Instance Fast Instance 100 ms 10 ms1 000 requests Round Robin Rule Slow: 500 and Fast: 500 Average time: 70 Weighted Rule Slow: 500 and Fast: 500 Average time: 72
  149. 149. 149 Slow Instance Fast Instance 100 ms 10 ms1 000 requests Round Robin Rule Slow: 500 and Fast: 500 Average time: 70 Weighted Rule Slow: 500 and Fast: 500 Average time: 72
  150. 150. test-service: #service name ribbon: #namespace ServerWeightTaskTimerInterval: 30000 #ms Let’s explain 150
  151. 151. test-service: #service name ribbon: #namespace ServerWeightTaskTimerInterval: 30000 #ms Weigths [0.0, 0.0] Let’s explain 151
  152. 152. test-service: #service name ribbon: #namespace ServerWeightTaskTimerInterval: 1000 #ms Let’s explain 152
  153. 153. test-service: #service name ribbon: #namespace ServerWeightTaskTimerInterval: 1000 #ms Weigths [12.285123016785462, 120.30885719400065] Let’s explain 153
  154. 154. IRule RoundRobin ZoneAvoidance Weighted Random BestAvailability AvailabilityFiltering 154
  155. 155. Best Available Rule LoadBalancerStats calculate chosen -> activeConnections == min(activeConnections) 155
  156. 156. Best Available Rule LoadBalancerStats calculate chosen -> activeConnections == min(activeConnections) 156 Less active connections -> more chance to success
  157. 157. 157 Slow Instance Fast Instance 100 ms 10 ms1 000 requests Round Robin Rule Slow: 500 and Fast: 500 Average time: 70 Weighted Rule Slow: 500 and Fast: 500 Average time: 72 Best Available Rule Slow: 152 and Fast: 847 Average time: 38
  158. 158. Don’t use round robin rule 158
  159. 159. IRule RoundRobin ZoneAvoidance Weighted Random BestAvailability AvailabilityFiltering 159
  160. 160. Availability Filtering Rule LoadBalancerStats calculate filtered -> activeConnections < maxActiveConnections filtered -> !isCircuitBreakerTripped Availability Predicate filter 160 Like a round robin
  161. 161. IRule RoundRobin ZoneAvoidance Weighted Random BestAvailability AvailabilityFiltering 161
  162. 162. Zone Avoidance Rule Composite Predicate filter Zone Predicate Availability Predicate 162
  163. 163. Zone Avoidance Rule Composite Predicate filter Zone Predicate Availability Predicate CompositePredicateBuilder int minimalFilteredServers = 1 float minimalFilteredPercentage = 0 predicate.filter(servers) 163
  164. 164. Zone Avoidance Rule Composite Predicate filter Zone Predicate Availability Predicate CompositePredicateBuilder int minimalFilteredServers = 1 float minimalFilteredPercentage = 0 int count = predicate.filter(servers).size() //2 164
  165. 165. Zone Avoidance Rule Composite Predicate filter Zone Predicate Availability Predicate CompositePredicateBuilder int minimalFilteredServers = 1 float minimalFilteredPercentage = 0 int count = predicate.filter(servers).size() //2 count >= minimalFilteredServers count >= minimalFilteredPercentage * count 165
  166. 166. Zone Avoidance Rule Composite Predicate filter Zone Predicate Availability Predicate CompositePredicateBuilder int minimalFilteredServers = 1 float minimalFilteredPercentage = 0 int count = predicate.filter(servers).size() //0 count >= minimalFilteredServers count >= minimalFilteredPercentage * count 166
  167. 167. Zone Avoidance Rule Composite Predicate filter Zone Predicate Availability Predicate next 167
  168. 168. triggeringLoadPerServerThreshold: 0.2 avoidZoneWithBlackoutPercetage: 0.99999d worstZone -> loadPerServer > max(loadPerServer) && loadPerServer > triggeringLoadPerServerThreshold zones.remove(worstZone) Zone Avoidance Rule Composite Predicate filter Zone Predicate Availability Predicate 168
  169. 169. triggeringLoadPerServerThreshold: 0.2 avoidZoneWithBlackoutPercetage: 0.99999d zoneToAvoid -> circuitBreakerTrippedCount / instanceCount >= avoidZoneWithBlackoutPercetage zones.remove(zoneToAvoid) Zone Avoidance Rule Composite Predicate filter Zone Predicate Availability Predicate 169
  170. 170. IRule RoundRobin ZoneAvoidance Weighted Random BestAvailability AvailabilityFiltering 170
  171. 171. If you don’t use zones then don’t use default rule 171
  172. 172. Deep Dive 1. Discovery 2. Balance it 3. Lifecycle 172
  173. 173. Service Service Service Service Service S2 S4 S2 LoadBalancerClient S1 S2 S3 S4 S5 S1 S2 S3 S4 S5 New Service register/deregister 173
  174. 174. How to do it? 3rd party registration pattern - dynamic - static Self-registration pattern (Lifecycle) 174
  175. 175. Docker Engine 175
  176. 176. Docker Engine Service register/deregister 176
  177. 177. Docker Engine Service register/deregister 177 Registrator emit event
  178. 178. Docker Engine Service register/deregister 178 Registrator emit event Service Registry native event
  179. 179. What is lifecycle? Allow automatically register and deregister service in service registry Implements Spring Lifecycle interface 179
  180. 180. SmartLifecycle DiscoveryLifecycle EurekaDiscoveryClientConfiguration ConsulLifecycle 180
  181. 181. DiscoveryLifecycle LifecycleProcessor autoStartup on refresh startBeans on start Service Registry register emit InstanceRegistered Event DiscoveryClientHealthIndicator 181
  182. 182. DiscoveryLifecycle LifecycleProcessor on RefreshScope event stopBeans on stop Service Registry deregister close or shutdown Real service discovery client 182
  183. 183. Something about docker 183
  184. 184. Docker container Internal IP External IP 184
  185. 185. > ifconfig lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280stf0: flags=0<> mtu 1280 en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 en1: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500 en2: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500 p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304 awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484 bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500 185
  186. 186. > ifconfig lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280stf0: flags=0<> mtu 1280 en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 en1: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500 en2: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500 p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304 awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484 bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500 ? 186
  187. 187. > ifconfig lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280stf0: flags=0<> mtu 1280 en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 en1: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500 en2: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500 p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304 awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484 bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500 Low index 187
  188. 188. Docker container Internal IP External IP 188
  189. 189. spring: cloud: consul: discovery: lifecycle: enabled: false 189 Registrator
  190. 190. spring: cloud: inetutils: ignored-interfaces: - vbox* - bridge* - lo* 190
  191. 191. spring: cloud: inetutils: ignored-interfaces: - vbox* - bridge* - lo* 191
  192. 192. spring: cloud: inetutils: ignored-interfaces: - vbox* - bridge* - lo* consul: discovery: preferIpAddress: true (false) 192
  193. 193. Instead of a conclusion 193
  194. 194. Own experience 194
  195. 195. Own experience 195 We use both patterns: server and client side • Consul + Registrator + Nginx • Marathon + MarathonLB • Eureka
  196. 196. Own experience Use client side pattern for API and Edge server Use server side for NodeJS front apps and non-standard API (Python) 196
  197. 197. Own experience Spring Cloud is production-ready and very customizable Minimum number of settings are needed to be changed, but for better results there are some of them that should be changed There are some issues that make you sad 197
  198. 198. 198 Spring Cloud Marathon (Proof of Concept) https://github.com/aatarasoff/spring-cloud-marathon Spring Cloud http://projects.spring.io/spring-cloud Service Discovery Patterns http://microservices.io/patterns/server-side-discovery.html http://microservices.io/patterns/client-side-discovery.html
  199. 199. /aatarasoff /aatarasoff habrahabr.ru/aatarasoff developerblog.info Questions and Answers Architect @ 199

×