spring-cloud / spring-cloud-connectors

Library to let cloud applications connect to services
Apache License 2.0
185 stars 161 forks source link

How ServiceInfoCreators Work #29

Closed ryanjbaxter closed 10 years ago

ryanjbaxter commented 10 years ago

I am trying to use Spring Cloud within a Spring Boot application and I am deploying this to BlueMix. BlueMix has a an ElephantSQL and Clear DB as services in its catalog. When I bind either of these services to my Spring Boot application and call connectionFactory().dataSource() in my AbstractCloudConfig implementation I am getting an exception saying " No unique service matching interface javax.sql.DataSource found. Expected 1, found 0". After reading the code in CloudFoundryServiceInfoCreator.accept it looks like it will look for whatever tag name is passed into the constructor in a property called tags in the service details or it will look at the service label to see if it begins with the tag. If neither of these are true for the ElephantSQL and Clear DB services, could this result in the error I am seeing?

ramnivas commented 10 years ago

That sounds about right. Can you show the VCAP_SERVICES environment variable. May be we can do something to accommodate that format.

ryanjbaxter commented 10 years ago

screen shot 2014-05-07 at 2 37 17 pm

I am can also bring this up internally and see what we can do to make things work. However I agree having a way for consumers to configure how the library identifies the services would be good.

ramnivas commented 10 years ago

@ryanjbaxter Thanks for the info. @scottfrederick and I have been discussing how to deal with such payload and leaning towards adding (in addition to what we already have) uri/url-based detection similar to what we do for Heroku already (https://github.com/spring-projects/spring-cloud/blob/master/heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java#L21).

ryanjbaxter commented 10 years ago

OK cool. In the mean time I will bring this up internally and see if we can address it from a BlueMix perspective.

ryanjbaxter commented 10 years ago

@ramnivas is the detection of the services dependent on the auto-configuration functionality in the Java buildpack, or is spring cloud searching through the bound services itself?

scottfrederick commented 10 years ago

Detection is only based on the contents of VCAP_SERVICES. Auto-reconfig depends on Spring Cloud, Spring Cloud does not depend on auto-reconfig.

ramnivas commented 10 years ago

https://github.com/spring-projects/spring-cloud/pull/31/files (pending for review by @scottfrederick to ensure that the change in semantics for matching user-provided services is a non-issue)

ryanjbaxter commented 10 years ago

@ramnivas that pull request looks good to me, thanks for the quick turn around!

ramnivas commented 10 years ago

The PR is now merged.

ryanjbaxter commented 10 years ago

@ramnivas is there a snapshot build published that contains this pull request?

ramnivas commented 10 years ago

@ryanjbaxter 0.9.12.BUILD-SNAPSHOT has this change. Note that 0.9.12.BUILD-SNAPSHOT also changes the artifactId to prefix it with "spring-cloud-". So core becomes spring-cloud-core etc.

ryanjbaxter commented 10 years ago

Thanks! Looks like this is helping me get further but both the MySQL driver and PostgreSQL driver are running out of Connections when Tomcat is starting. I see some pool configuration classes in the spring-cloud but not sure how they come into play here. The MySQL driver is saying there were only 4 total connections available, the PostgreSQL driver didn't print that information in the exception. Is there something more I need to do? Or does this sound like a problem with my app and not related to spring-cloud?

P.S. I am using Spring Boot with embedded Tomcat

ramnivas commented 10 years ago

@ryanjbaxter Glad to see that it helped you get further.

Can you show how you are creating DataSource beans using spring-cloud.

ryanjbaxter commented 10 years ago

In my AbstractCloudConfig class I have

@Bean public DataSource dataSource() { return connectionFactory().dataSource("session-questions-sql"); }

Where session-questions-sql is the name of the MySQL/PostgresSQL service. (clear db or elephantsql)

ramnivas commented 10 years ago

@ryanjbaxter Consider passing the second parameter of the DataSourceConfig type (which in turn takes pool config) to limit the number of connection created.

Also, is this deployed to your own cloud or the CF plugin cloud?

ryanjbaxter commented 10 years ago

OK that worked. For some reason that config is required when using cleardb or elephantsql but when using the built in SQL service in CF it is not required.

I am deploying the app to BlueMix.

ramnivas commented 10 years ago

Great. It seems then the issue is how those services are configured. They are probably set with max connections per host too small.

ryanjbaxter commented 10 years ago

I guess I dont understand how services are configured in CF then. How can what I specify in my application effect the max connections configured for the service? I am not connecting the dots...

ramnivas commented 10 years ago

I don't know the precise mechanism, but I imagine (and in CF v1 dealt with this) the service broker must be limiting maximum simultaneous connections to conserve resources. If an application tries to acquire more than the allowed number of connections, it will receive an error during connection creation.

In your case, the pool that gets created at application startup must be asking for too many connections (as evidenced by supplying config to presumably reduce connections created resolved the problem) and thus fail. From the information supplied:

connections allowed by BlueMix < connection attempted by the default pool config < connection allowed by CF public cloud or default service.
ryanjbaxter commented 10 years ago

OK now i understand. It is the service limiting the connections, I see. Thanks for all your help!