win w/ Spring Boot, Spring Cloud and Cloud Foundry
win w/ Spring Boot, Spring Cloud and Cloud Foundry
The accompanying code for this workshop is on Github
microservices, for better or for worse, involve a lot of moving parts. Let's make sure we can run all those things in this lab.
mvn -DskipTests=true clean install to force the resolution of all those dependencies so you're not stalled later. Then, run mvn clean install to force the resolution of the test scoped dependencies. You may discard this project after you've run the commands. This will download whatever artifacts are most current to your local Maven repository (usually, .m2/repository)..sh scripts in the ./bin directory; run psql.sh after you've run postgresh.sh and confirm that they all complete and emit no obvious errorsIn this lab we'll take a look at building a basic Spring Boot application that uses JPA and Spring Data REST. We'll look at how to start a new project, how Spring Boot exposes functionality, and how testing works.
Web, JPA, H2, Actuator, Config Client, Eureka Discovery, Lombok, Zipkin Client, Stream Rabbit, Cloud Contract Verifier and Integration. Specify an artifactId of reservation-service.Generate and then unzip the archive. Change into the directory of the unzipped project and then run mvn clean install.pom.xml and comment out dependencies that we don't need, for the moment, including: org.springframework.cloud:spring-cloud-starter-stream-rabbit, org.springframework.cloud:spring-cloud-starter-config, org.springframework.cloud:spring-cloud-starter-zipkin, and org.springframework.cloud:spring-cloud-starter-eureka.Reservation) with an id field and a reservationName field. Use Lombok to synthesize getters/setters, all-argument and no-argument constructors.ReservationRepository)./mvnw) in the build to support reproducible builds.jars and not .wars? We've found that many organizations deploy only one, not many, application to one Tomcat/Jetty/whatever. They need to configure things like SSL, or GZIP compression, so they end up doing that in the container itself and - because they don't want the versioned configuration for the server to drift out of sync with the code, they end up version controlling the application server artifacts as well as the application itself! This implies a needless barrier between dev and ops which we struggle in every other place to remove.by-name search endpoint? Follow the links! visit http://localhost:8080/reservations and scroll down and you'll see links that connect you to related resources. You'll see one for search. Follow it, find the relevant finder method, and then follow its link.(Multi-day workshops only)
Code complete != production ready! If you've ever read Michael Nygard's amazing tome, Release It!, then you know that the last mile between being code complete and being to production is much longer than anyone ever anticipates. In this lab, we'll look at how Spring Boot is optimized for the continuous delivery of applications into production.
org.springframework.boot:spring-boot-starter-actuatorHealthEndpoint by contributing a custom HealthIndicator./bin/graphite.shGRAPHITE_HOST (export GRAPHITE_HOST="$DOCKER_IP") and GRAPHITE_PORT (2003) (you may need to restart your IDE to see these new environment variables)GraphiteReporter beanio.dropwizard.metrics:metrics-graphite.jar (UNIX-specific) using the `` configuration flagorg.springframework.data:spring-data-rest-hal-browser and view the Actuator endpoints using thatpom.xml in all existing and subsequent pom.xmls, or extract out a common parent pom.xml that all modules may extend.[email protected]@ and [email protected]@ to application.properties.@RepositoryEventHandler and @Component. Provide handlers for @HandleAfterCreate, @HandleAfterSave, and @HandleAfterDelete. Extract common counters to a shared methodCounterService and observe the histogram in GraphiteThe 12 Factor manifesto talks about externalizing that which changes from one environment to another - hosts, locators, passwords, etc. - from the application itself. Spring Boot readily supports this pattern, but it's not enough. In this lab, we'll look at how to centralize, externalize, and dynamically update application configuration with the Spring Cloud Config Server.
artifactId of config-service and add Config Server from the list of dependencies.git clone the Git repository for this workshop - https://github.com/joshlong/bootiful-microservices-configapplication.properties, specify that it should run on port 8888 (server.port=8888) and that it should manage the Git repository of configuration that lives in the root directory of the git clone'd configuration. (spring.cloud.config.server.git.uri=...).@EnableConfigServer to the config-service's root applicationserver.port=8888 to the application.properties to ensure that the Config Server is running on the right port for service to find it.reservation-service.We will need to modify the reservation-service's pom.xml in order to make it a config client. To do this, add the following to your pom.xml of the reservation-service from step #1.
Example:
...
org.springframework.cloud
spring-cloud-starter-parent
Brixton.RELEASE
pom
importIMPORTANT: Make sure that you make this modification in the `` block. There are two places where Maven dependencies are added in a pom.xml and some people tend to get confused at this step. If you need help, please raise your hand and flag down an instructor.
Next, add org.springframework.cloud:spring-cloud-starter-config to the reservation-service. We'll add this dependency declaration to the general dependencies tag, unlike the previous modification to ``.
Example:
org.springframework.cloud
spring-cloud-starter-config
..Next:
Create a boostrap.properties that lives in the same place as application.properties and discard the application.properties file. Now we need only to tell the Spring application where to find the Config Server, with the property [email protected]:http://localhost:8888@, and how to identify itself to the Config Server and other services, later, with spring.application.name.
Now, run the Config Server:
We'll copy and paste
bootstrap.propertiesfor each subsequent module, changing only thespring.application.nameas appropriate.
In the reservation-service, create a MessageRestController and annotate it with @RefreshScope. Inject the ${message} key and expose it as a REST endpoint, /message.
Trigger a refresh of the message using the /refresh endpoint.
EXTRA CREDIT: Install RabbitMQ server and connect the microservice to the the Spring Cloud Stream-based event bus and then triggering the refresh using the /bus/refresh.
In the cloud, services are often ephemeral and it's important to be able to talk to these services abstractly, without worrying about the host and ports for these services. At first blush, this seems like a use-case for DNS, but DNS fails in several key situations. How do we know if there's a service waiting on the other end of a DNS-mapped service that can respond? How do we support more sophisticated load-balancing than DNS + a typical loadbalancer can handle (e.g.: round-robin)? How do we avoid the extra hop outside of most cloud environments required to resolve DNS? For all of these and more, we want the effect of DNS - a dispatch table - without being coupled to DNS. We'll use a service registry and Spring Cloud's
DiscoveryClientabstraction.
Eureka Server (this brings in org.springframework.cloud:spring-cloud-starter-eureka-server) checkbox, name it eureka-service and then add @EnableEurekaServer to the DemoApplication class.org.springframework.cloud:spring-cloud-starter-config.org.springframework.cloud:spring-cloud-starter-eureka to the reservation-service@EnableDiscoveryClient to the reservation-service's DemoApplication and restart the process, and then confirm its appearance in the Eureka Server at http://localhost:8761you have a service registry and now you have a single service registered and advertising its presence. Let's take advantage of that in an edge service, which we'll call
reservation-client.
reservation-client, with the Web, Lombok, Feign, Zuul, Hystrix, Stream Rabbit, Eureka Discovery, Config Client, Cloud OAuth2, and Zipkin Client dependencies.pom.xml and comment out the dependencies that are neither needed nor workable without some extra configuration (which we'll get to later): org.springframework.cloud:spring-cloud-starter-oauth2, org.springframework.cloud:spring-cloud-starter-stream-rabbit, and org.springframework.cloud:spring-cloud-starter-zipkin.bootstrap.properties, just as with the other modules, but name this one reservation-client.No open issues yet, or sync has not completed.