diff --git a/DistirbutedTracing/CreditInfo/README.md b/DistirbutedTracing/CreditInfo/README.md new file mode 100644 index 0000000..5b2dd41 --- /dev/null +++ b/DistirbutedTracing/CreditInfo/README.md @@ -0,0 +1,13 @@ +Credit Info +----------- +Gives Credit Info + +http://localhost:8091/credit + +### Run + +```bash +cd CreditInfo +spring run . +``` + diff --git a/DistirbutedTracing/CreditInfo/app.groovy b/DistirbutedTracing/CreditInfo/app.groovy new file mode 100755 index 0000000..ce94b50 --- /dev/null +++ b/DistirbutedTracing/CreditInfo/app.groovy @@ -0,0 +1,25 @@ +@Grab("org.springframework.kafka:spring-kafka:1.1.1.RELEASE") +@Grab("org.springframework.integration:spring-integration-kafka:2.1.0.RELEASE") +@Grab("org.apache.kafka:kafka_2.11:0.10.0.0") +@GrabExclude("org.slf4j:slf4j-log4j12") +@Grab("spring-cloud-starter-bus-kafka") +@Grab("spring-cloud-sleuth-stream") +@Grab("spring-cloud-starter-consul-discovery") + +@EnableDiscoveryClient +@EnableCircuitBreaker +@RestController +@Log +class Application { + + + int credit = 700 + + @RequestMapping(value = "/credit", produces = "application/json") + String getCredit() { + credit = 1000 * Math.random() + log.info("Produced a value: ${credit}") + + "{\"value\": ${credit}}" + } +} \ No newline at end of file diff --git a/DistirbutedTracing/CreditInfo/bootstrap.yml b/DistirbutedTracing/CreditInfo/bootstrap.yml new file mode 100755 index 0000000..109bf1a --- /dev/null +++ b/DistirbutedTracing/CreditInfo/bootstrap.yml @@ -0,0 +1,42 @@ +server: + port: 8091 + +spring: + application: + name: CreditInfo + cloud: + config: + enabled: false + discovery: + enabled: false + serviceId: CONFIG + consul: + host: localhost + port: 8500 + #acl-token: 2ee647bd-bd69-4118-9f34-b9a6e9e60746 + discovery: + instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} + #health-check-url: http://127.0.0.1:${server.port}/health + enabled: true + preferIpAddress: true + ip-address: 127.0.0.1 + + sleuth: + sampler: + percentage: 1.0 + +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG + +eureka: + # instance: + # nonSecurePort: ${server.port:8085} + client: + register-with-eureka: false + fetch-registry: false + #serviceUrl: + #defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/DistirbutedTracing/GetAddress/README.md b/DistirbutedTracing/GetAddress/README.md new file mode 100644 index 0000000..43c3774 --- /dev/null +++ b/DistirbutedTracing/GetAddress/README.md @@ -0,0 +1,12 @@ +Get Address +----------- + +http://localhost:8092/add + +### Run + +```bash +cd DistributedTracing/GetAddress +spring run . +``` + diff --git a/DistirbutedTracing/GetAddress/app.groovy b/DistirbutedTracing/GetAddress/app.groovy new file mode 100755 index 0000000..272d6bf --- /dev/null +++ b/DistirbutedTracing/GetAddress/app.groovy @@ -0,0 +1,25 @@ +@Grab("org.springframework.kafka:spring-kafka:1.1.1.RELEASE") +@Grab("org.springframework.integration:spring-integration-kafka:2.1.0.RELEASE") +@Grab("org.apache.kafka:kafka_2.11:0.10.0.0") +@GrabExclude("org.slf4j:slf4j-log4j12") +@Grab("spring-cloud-starter-bus-kafka") +@Grab("spring-cloud-sleuth-stream") +@Grab("spring-cloud-starter-consul-discovery") +@EnableDiscoveryClient +@EnableCircuitBreaker +@RestController +@Log +class Application { + + + String address = "california usa" + + @RequestMapping(value = "/add", produces = "application/json") + String getAddress() { + + log.info("Address is : ${address}") + + "{\"value\": ${address}}" + } +} + diff --git a/DistirbutedTracing/GetAddress/bootstrap.yml b/DistirbutedTracing/GetAddress/bootstrap.yml new file mode 100755 index 0000000..8837b7b --- /dev/null +++ b/DistirbutedTracing/GetAddress/bootstrap.yml @@ -0,0 +1,41 @@ +server: + port: 8092 + +spring: + application: + name: GetAddress + cloud: + config: + enabled: false + discovery: + enabled: false + serviceId: CONFIG + consul: + host: localhost + port: 8500 + #acl-token: 2ee647bd-bd69-4118-9f34-b9a6e9e60746 + discovery: + instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} + #health-check-url: http://127.0.0.1:${server.port}/health + enabled: true + preferIpAddress: true + ip-address: 127.0.0.1 + sleuth: + sampler: + percentage: 1.0 + +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG + +eureka: + # instance: + # nonSecurePort: ${server.port:8085} + client: + register-with-eureka: false + fetch-registry: false + #serviceUrl: + #defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/DistirbutedTracing/GetCaption/README.md b/DistirbutedTracing/GetCaption/README.md new file mode 100644 index 0000000..0d8a790 --- /dev/null +++ b/DistirbutedTracing/GetCaption/README.md @@ -0,0 +1,13 @@ +Caption +------- + + +http://localhost:8094/caption + +### Run + +```bash +cd DistributedTracing/GetCaption +spring run . +``` + diff --git a/DistirbutedTracing/GetCaption/app.groovy b/DistirbutedTracing/GetCaption/app.groovy new file mode 100755 index 0000000..50f7044 --- /dev/null +++ b/DistirbutedTracing/GetCaption/app.groovy @@ -0,0 +1,24 @@ +@Grab("org.springframework.kafka:spring-kafka:1.1.1.RELEASE") +@Grab("org.springframework.integration:spring-integration-kafka:2.1.0.RELEASE") +@Grab("org.apache.kafka:kafka_2.11:0.10.0.0") +@GrabExclude("org.slf4j:slf4j-log4j12") +@Grab("spring-cloud-starter-bus-kafka") +@Grab("spring-cloud-sleuth-stream") +@Grab("spring-cloud-starter-consul-discovery") +@EnableDiscoveryClient +@EnableCircuitBreaker +@RestController +@Log +class Application { + + String caption = "All is well" + + @RequestMapping(value = "/caption", produces = "application/json") + String getCaption() { + + log.info("Caption is : ${caption}") + + "{\"value\": ${caption}}" + } + +} \ No newline at end of file diff --git a/DistirbutedTracing/GetCaption/bootstrap.yml b/DistirbutedTracing/GetCaption/bootstrap.yml new file mode 100755 index 0000000..2536ceb --- /dev/null +++ b/DistirbutedTracing/GetCaption/bootstrap.yml @@ -0,0 +1,41 @@ +server: + port: 8093 + +spring: + application: + name: GetCaption + cloud: + config: + enabled: false + discovery: + enabled: false + serviceId: CONFIG + consul: + host: localhost + port: 8500 + #acl-token: 2ee647bd-bd69-4118-9f34-b9a6e9e60746 + discovery: + instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} + #health-check-url: http://127.0.0.1:${server.port}/health + enabled: true + preferIpAddress: true + ip-address: 127.0.0.1 + sleuth: + sampler: + percentage: 1.0 + +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG + +eureka: + # instance: + # nonSecurePort: ${server.port:8085} + client: + register-with-eureka: false + fetch-registry: false + #serviceUrl: + #defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/DistirbutedTracing/GetInterest/README.md b/DistirbutedTracing/GetInterest/README.md new file mode 100644 index 0000000..b0eb83b --- /dev/null +++ b/DistirbutedTracing/GetInterest/README.md @@ -0,0 +1,13 @@ +Get Interests +------------- + +http://localhost:8094/getInterest + + +### Run + +```bash +cd DistributedTracing/GetInterest +spring run . +``` + diff --git a/DistirbutedTracing/GetInterest/app.groovy b/DistirbutedTracing/GetInterest/app.groovy new file mode 100755 index 0000000..1c01574 --- /dev/null +++ b/DistirbutedTracing/GetInterest/app.groovy @@ -0,0 +1,25 @@ +@Grab("org.springframework.kafka:spring-kafka:1.1.1.RELEASE") +@Grab("org.springframework.integration:spring-integration-kafka:2.1.0.RELEASE") +@Grab("org.apache.kafka:kafka_2.11:0.10.0.0") +@GrabExclude("org.slf4j:slf4j-log4j12") +@Grab("spring-cloud-starter-bus-kafka") +@Grab("spring-cloud-sleuth-stream") +@Grab("spring-cloud-starter-consul-discovery") + +@EnableDiscoveryClient +@EnableCircuitBreaker +@RestController +@Log +class Application { + + String interests = "Cricket, Movies, Music" + + @RequestMapping(value = "/getInterest", produces = "application/json") + String getInterest() { + + log.info("Interests are: ${interests}") + + "{\"value\": ${interests}}" + } +} + diff --git a/DistirbutedTracing/GetInterest/bootstrap.yml b/DistirbutedTracing/GetInterest/bootstrap.yml new file mode 100755 index 0000000..162598a --- /dev/null +++ b/DistirbutedTracing/GetInterest/bootstrap.yml @@ -0,0 +1,41 @@ +server: + port: 8094 + +spring: + application: + name: GetInterests + cloud: + config: + enabled: false + discovery: + enabled: false + serviceId: CONFIG + consul: + host: localhost + port: 8500 + #acl-token: 2ee647bd-bd69-4118-9f34-b9a6e9e60746 + discovery: + instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} + #health-check-url: http://127.0.0.1:${server.port}/health + enabled: true + preferIpAddress: true + ip-address: 127.0.0.1 + sleuth: + sampler: + percentage: 1.0 + +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG + +eureka: + # instance: + # nonSecurePort: ${server.port:8085} + client: + register-with-eureka: false + fetch-registry: false + #serviceUrl: + #defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/DistirbutedTracing/GetPromotion/README.md b/DistirbutedTracing/GetPromotion/README.md new file mode 100644 index 0000000..799e089 --- /dev/null +++ b/DistirbutedTracing/GetPromotion/README.md @@ -0,0 +1,12 @@ +Promo +----- + +http://localhost:8095/promo + + +### Run + +```bash +cd DistributedTracing/GetPromotion +spring run . +``` diff --git a/DistirbutedTracing/GetPromotion/app.groovy b/DistirbutedTracing/GetPromotion/app.groovy new file mode 100755 index 0000000..4e910d9 --- /dev/null +++ b/DistirbutedTracing/GetPromotion/app.groovy @@ -0,0 +1,23 @@ +@Grab("org.springframework.kafka:spring-kafka:1.1.1.RELEASE") +@Grab("org.springframework.integration:spring-integration-kafka:2.1.0.RELEASE") +@Grab("org.apache.kafka:kafka_2.11:0.10.0.0") +@GrabExclude("org.slf4j:slf4j-log4j12") +@Grab("spring-cloud-starter-bus-kafka") +@Grab("spring-cloud-sleuth-stream") +@Grab("spring-cloud-starter-consul-discovery") +@EnableDiscoveryClient +@EnableCircuitBreaker +@RestController +@Log +class Application { + + String promo = "No promo available" + + @RequestMapping(value = "/promo", produces = "application/json") + String promo() { + + "{\"value\": ${promo}}" + } + +} + diff --git a/DistirbutedTracing/GetPromotion/bootstrap.yml b/DistirbutedTracing/GetPromotion/bootstrap.yml new file mode 100755 index 0000000..54ef16b --- /dev/null +++ b/DistirbutedTracing/GetPromotion/bootstrap.yml @@ -0,0 +1,41 @@ +server: + port: 8095 + +spring: + application: + name: Promo + cloud: + config: + enabled: false + discovery: + enabled: false + serviceId: CONFIG + consul: + host: localhost + port: 8500 + #acl-token: 2ee647bd-bd69-4118-9f34-b9a6e9e60746 + discovery: + instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} + #health-check-url: http://127.0.0.1:${server.port}/health + enabled: true + preferIpAddress: true + ip-address: 127.0.0.1 + sleuth: + sampler: + percentage: 1.0 + +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG + +eureka: + # instance: + # nonSecurePort: ${server.port:8085} + client: + register-with-eureka: false + fetch-registry: false + #serviceUrl: + #defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/DistirbutedTracing/Recommendation/README.md b/DistirbutedTracing/Recommendation/README.md new file mode 100644 index 0000000..237d89c --- /dev/null +++ b/DistirbutedTracing/Recommendation/README.md @@ -0,0 +1,12 @@ +Reco +---- + +http://localhost:8096/reco + + +### Run + +```bash +cd DistributedTracing/Recommendation +spring run . +``` diff --git a/DistirbutedTracing/Recommendation/app.groovy b/DistirbutedTracing/Recommendation/app.groovy new file mode 100755 index 0000000..e7b678c --- /dev/null +++ b/DistirbutedTracing/Recommendation/app.groovy @@ -0,0 +1,23 @@ +@Grab("org.springframework.kafka:spring-kafka:1.1.1.RELEASE") +@Grab("org.springframework.integration:spring-integration-kafka:2.1.0.RELEASE") +@Grab("org.apache.kafka:kafka_2.11:0.10.0.0") +@GrabExclude("org.slf4j:slf4j-log4j12") +@Grab("spring-cloud-starter-bus-kafka") +@Grab("spring-cloud-sleuth-stream") +@Grab("spring-cloud-starter-consul-discovery") +@EnableDiscoveryClient +@EnableCircuitBreaker +@RestController +@Log +class Application { + + + String reco = "Shawshank Redemption" + + @RequestMapping(value = "/reco", produces = "application/json") + String reco() { + + "{\"value\": ${reco}}" + } + +} \ No newline at end of file diff --git a/DistirbutedTracing/Recommendation/bootstrap.yml b/DistirbutedTracing/Recommendation/bootstrap.yml new file mode 100755 index 0000000..c1ee08a --- /dev/null +++ b/DistirbutedTracing/Recommendation/bootstrap.yml @@ -0,0 +1,41 @@ +server: + port: 8096 + +spring: + application: + name: Reco + cloud: + config: + enabled: false + discovery: + enabled: false + serviceId: CONFIG + consul: + host: localhost + port: 8500 + #acl-token: 2ee647bd-bd69-4118-9f34-b9a6e9e60746 + discovery: + instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} + #health-check-url: http://127.0.0.1:${server.port}/health + enabled: true + preferIpAddress: true + ip-address: 127.0.0.1 + sleuth: + sampler: + percentage: 1.0 + +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG + +eureka: + # instance: + # nonSecurePort: ${server.port:8085} + client: + register-with-eureka: false + fetch-registry: false + #serviceUrl: + #defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/README.md b/README.md index c2c3823..0e6fbba 100644 --- a/README.md +++ b/README.md @@ -19,17 +19,19 @@ Spring Cloud focuses on providing good out of box experience for typical use cas ### Infrastructure Services -* **Netflix Eureka:** Service registry & discovery +* **Consul:** Service registry & discovery * **Netflix Hystrix:** Resiliency - Circuit breaker, Fallback, Concurrency, RxJava * **Netflix Hystrix Dashboard:** Monitoring and metrics dashboard * **Netflix Turbine:** Aggregate hystrix streams * **Netflix Ribbon:** Client-side load-balancing * **Netflix Zuul:** Reverse proxy for API gateway -* **Spring Cloud Config:** Centralized configuration -* **Spring Cloud Bus:** PubSub messaging over RabbitMQ -* **Spring Cloud Security:** SSO for APIs - OAuth/JWT -* **Logging:** Centralized logging - Logstash, ES, Kibana (LEK) -* **Swagger:** API Docs +* **Spring Cloud Consul Config:** Centralized configuration +* **Spring Cloud Vault:** Managing secrets +* **Spring Cloud Bus:** PubSub messaging over Kafka +* **Zipkin:** Distributed Tracing +* **Spring Cloud Security:** SSO for APIs - OAuth/JWT -- coming soon +* **Logging:** Centralized logging - Logstash, ES, Kibana (LEK) -- coming soon +* **Swagger:** API Docs -- coming soon ![](./presentation/images/system-landscape.png) @@ -43,7 +45,7 @@ Spring Cloud focuses on providing good out of box experience for typical use cas #### Start on Local Machine Starting Order -> Kafka -> Euraka -> Config -> (Producer, GORM, ...), -> (Zuul, Turbine, Hystrix Dashboard) +> zk -> Kafka -> Consul -> Git2Consul -> Vault -> zipking -> (Producer, ...), -> (Hystrix Dashboard) #### Quickstart examples > start following two apps, one at a time as they use same port. @@ -62,15 +64,10 @@ spring run . #### Full-stack cloud native examples -Starting Eureka Server -``` -cd eureka -spring run . -``` -Starting Config Server +Starting Zipkin Service ``` -cd config +cd Zipkin spring run . ``` @@ -78,12 +75,8 @@ Start up Producer Service ``` cd producer spring run . -``` -Starting Gorm Service -``` -cd gorm -spring run . +Start other services under Distributed Tracing folder ``` Starting Monitoring App @@ -101,13 +94,6 @@ Starting Aggregate Service > Follow instructions [aggregator](./aggregator/) -Starting API Gateway -``` -cd zuul -spring run . -``` - -Starting Blog App diff --git a/aggregator/build.gradle b/aggregator/build.gradle index ca49573..84c858c 100644 --- a/aggregator/build.gradle +++ b/aggregator/build.gradle @@ -12,8 +12,11 @@ dependencies { compile "org.springframework.boot:spring-boot-starter-web" compile "org.springframework.boot:spring-boot-starter-actuator" compile "org.springframework.cloud:spring-cloud-starter-bus-kafka" - compile 'org.springframework.cloud:spring-cloud-starter-eureka' + //compile 'org.springframework.cloud:spring-cloud-starter-eureka' + compile "org.springframework.cloud:spring-cloud-starter-consul-discovery" compile "org.springframework.cloud:spring-cloud-starter-feign" + compile "org.springframework.cloud:spring-cloud-sleuth-stream" + compile "org.springframework.boot:spring-boot-starter-aop" testCompile "com.nhaarman:mockito-kotlin:$mockitoKotlinVersion" testCompile "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" diff --git a/aggregator/src/main/kotlin/com/sumo/cloudnative/aggregator/App.kt b/aggregator/src/main/kotlin/com/sumo/cloudnative/aggregator/App.kt index cc7c90d..6bf887c 100644 --- a/aggregator/src/main/kotlin/com/sumo/cloudnative/aggregator/App.kt +++ b/aggregator/src/main/kotlin/com/sumo/cloudnative/aggregator/App.kt @@ -9,20 +9,20 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.cloud.client.discovery.EnableDiscoveryClient import org.springframework.cloud.netflix.feign.EnableFeignClients import org.springframework.cloud.netflix.feign.FeignClient +import org.springframework.cloud.sleuth.Sampler +import org.springframework.cloud.sleuth.Span import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.http.MediaType import org.springframework.web.bind.annotation.* import org.springframework.web.servlet.config.annotation.CorsRegistry -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter import org.springframework.web.bind.annotation.RequestMethod.GET @EnableDiscoveryClient @SpringBootApplication @EnableFeignClients -open class App: CommandLineRunner { +open class App : CommandLineRunner { companion object { private val log = LoggerFactory.getLogger(App::class.java) } @@ -77,22 +77,69 @@ interface ProducerClient { fun home(): String } +@FeignClient("promo") +interface PromoClient { + @RequestMapping(value = "/promo", method = arrayOf(GET)) + fun promo(): String +} + +@FeignClient("reco") +interface RecoClient { + @RequestMapping(value = "/reco", method = arrayOf(GET)) + fun reco(): String +} + +@FeignClient("GetAddress") +interface AddClient { + @RequestMapping(value = "/add", method = arrayOf(RequestMethod.GET)) + fun add(): String +} @RestController -class AggregatorController @Autowired constructor(val mybatis: MybatisClient, val producer: ProducerClient) { +class AggregatorController @Autowired constructor(val mybatis: MybatisClient, + val producer: ProducerClient, + val promo: PromoClient, + val reco: RecoClient, + val addClient: AddClient) { @GetMapping("/") fun hello(): String { - return mybatis.hello(); + reco.reco(); + return producer.home(); } @GetMapping("members") - fun members(): List { + fun members(): List { + addClient.add(); + promo.promo(); + reco.reco(); + producer.home() return mybatis.members(); } @GetMapping("home") - fun home(): String { + fun home(): String { + addClient.add(); + promo.promo(); + reco.reco(); return producer.home(); } } + +@Configuration +open class CustomSampler : Sampler { + override fun isSampled(span: Span) : Boolean + { + + print("span name " + span.name); + if(span.name.contains("catalog-services-watch", ignoreCase = false)) + { + print("no stream"); + return false; + } + print("stream to zipkin"); + return true; + } + } + + diff --git a/aggregator/src/main/resources/application.yml b/aggregator/src/main/resources/application.yml index be88d37..53f8b69 100644 --- a/aggregator/src/main/resources/application.yml +++ b/aggregator/src/main/resources/application.yml @@ -1,2 +1,10 @@ server: - port: 8085 \ No newline at end of file + port: 8085 + +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG + diff --git a/aggregator/src/main/resources/bootstrap.yml b/aggregator/src/main/resources/bootstrap.yml index 6d94edd..1d14d0a 100644 --- a/aggregator/src/main/resources/bootstrap.yml +++ b/aggregator/src/main/resources/bootstrap.yml @@ -4,16 +4,28 @@ server: spring: application: name: aggregator + sleuth: + sampler: + percentage: 1.0 + cloud: - config: - enabled: true +# config: +# enabled: true +# discovery: +# enabled: true +# serviceId: CONFIG + consul: + host: localhost + port: 8500 discovery: + instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} enabled: true - serviceId: CONFIG + preferIpAddress: true + ip-address: 127.0.0.1 -eureka: - instance: - nonSecurePort: ${server.port:8085} - client: - serviceUrl: - defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file +#eureka: +# instance: +# nonSecurePort: ${server.port:8085} +# client: +# serviceUrl: +# defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/hystrix-dashboard/app.groovy b/hystrix-dashboard/app.groovy index 4336400..b74dfa8 100644 --- a/hystrix-dashboard/app.groovy +++ b/hystrix-dashboard/app.groovy @@ -1,4 +1,12 @@ +@Grab("org.springframework.kafka:spring-kafka:1.1.1.RELEASE") +@Grab("org.springframework.integration:spring-integration-kafka:2.1.0.RELEASE") +@Grab("org.apache.kafka:kafka_2.11:0.10.0.0") +@GrabExclude("org.slf4j:slf4j-log4j12") @Grab("spring-cloud-starter-bus-kafka") +@Grab("spring-cloud-sleuth-stream") +@Grab("spring-cloud-starter-consul-discovery") +@Grab("spring-cloud-starter-hystrix") +//@Grab("spring-cloud-starter-consul-config") @Grab("spring-cloud-starter-hystrix-dashboard") @groovy.transform.CompileStatic @EnableDiscoveryClient diff --git a/hystrix-dashboard/bootstrap.yml b/hystrix-dashboard/bootstrap.yml index 6f1b30b..5eaa76f 100644 --- a/hystrix-dashboard/bootstrap.yml +++ b/hystrix-dashboard/bootstrap.yml @@ -5,17 +5,31 @@ spring: application: name: hystrix-dashboard cloud: - config: - enabled: true + consul: + host: localhost + port: 8500 + #acl-token: 2ee647bd-bd69-4118-9f34-b9a6e9e60746 discovery: + instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} + #health-check-url: http://127.0.0.1:${server.port}/health enabled: true + preferIpAddress: true + ip-address: 127.0.0.1 +# config: +# enabled: true +# prefix: config/master +# format: FILES + config: + enabled: false + discovery: + enabled: false serviceId: CONFIG eureka: - instance: - nonSecurePort: ${server.port:8989} -# metadataMap: -# instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${server.port}}} + # instance: + # nonSecurePort: ${server.port:8085} client: - serviceUrl: - defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file + register-with-eureka: false + fetch-registry: false + #serviceUrl: + #defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/mybatis/build.gradle b/mybatis/build.gradle index 2613685..ab850ff 100644 --- a/mybatis/build.gradle +++ b/mybatis/build.gradle @@ -13,8 +13,12 @@ dependencies { compile "org.springframework.boot:spring-boot-starter-web" compile "org.springframework.cloud:spring-cloud-starter-bus-kafka" // compile "org.springframework.cloud:spring-cloud-starter-config" - compile 'org.springframework.cloud:spring-cloud-starter-eureka' + // compile 'org.springframework.cloud:spring-cloud-starter-eureka' // compile "org.springframework.boot:spring-boot-devtools" + compile "org.springframework.cloud:spring-cloud-starter-consul-discovery" + compile "org.springframework.cloud:spring-cloud-sleuth-stream" + compile "org.springframework.boot:spring-boot-starter-aop" + compile "org.springframework.cloud:spring-cloud-starter-feign" // runtime "mysql:mysql-connector-java" runtime "com.h2database:h2" diff --git a/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/App.kt b/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/App.kt index 4649ec7..6881c3f 100644 --- a/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/App.kt +++ b/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/App.kt @@ -5,11 +5,15 @@ import org.springframework.boot.CommandLineRunner import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.builder.SpringApplicationBuilder import org.springframework.cloud.client.discovery.EnableDiscoveryClient - +import org.springframework.cloud.netflix.feign.EnableFeignClients +import org.springframework.cloud.netflix.feign.FeignClient +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestMethod @EnableDiscoveryClient @SpringBootApplication +@EnableFeignClients open class App: CommandLineRunner { companion object { private val log = LoggerFactory.getLogger(App::class.java) @@ -24,3 +28,21 @@ fun main(vararg args: String) { SpringApplicationBuilder(App::class.java) .registerShutdownHook(true).run(*args) } + +@FeignClient("GetCaption") +interface CaptionClient { + @RequestMapping(value = "/caption", method = arrayOf(RequestMethod.GET)) + fun caption(): String +} + +@FeignClient("GetInterests") +interface IntClient { + @RequestMapping(value = "/getInterest", method = arrayOf(RequestMethod.GET)) + fun int(): String +} + +@FeignClient("GetAddress") +interface AddClient { + @RequestMapping(value = "/add", method = arrayOf(RequestMethod.GET)) + fun add(): String +} \ No newline at end of file diff --git a/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/controllers/MemberController.kt b/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/controllers/MemberController.kt index 6509aaa..68fca5f 100644 --- a/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/controllers/MemberController.kt +++ b/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/controllers/MemberController.kt @@ -2,29 +2,44 @@ package com.sumo.cloudnative.mybatis import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMethod import org.springframework.web.bind.annotation.RestController import org.springframework.beans.factory.annotation.Autowired import org.springframework.cloud.client.discovery.DiscoveryClient +import org.springframework.cloud.netflix.feign.FeignClient + @RestController -class MemberController @Autowired constructor(var client: DiscoveryClient, val service: MemberService) { +class MemberController @Autowired constructor(var client: DiscoveryClient, + val service: MemberService, + val captionClient: CaptionClient, + val intClient: IntClient, + val addClient: AddClient) { @RequestMapping("/") fun hello(): String { val localInstance = client.localServiceInstance + captionClient.caption(); + intClient.int(); return "MyBatis: " + localInstance.serviceId + ":" + localInstance.host + ":" + localInstance.port } - @RequestMapping("members", method = arrayOf(RequestMethod.GET)) + //@RequestMapping("members", method = arrayOf(RequestMethod.GET)) + @GetMapping("members") fun members(): List { + intClient.int(); + captionClient.caption(); + addClient.add(); return service.findAll(); } - @RequestMapping("members/{id}", method = arrayOf(RequestMethod.GET)) + @GetMapping("members/{id}") fun member(@PathVariable id: Int): Member { print(id) + intClient.int(); + captionClient.caption(); return service.findById(id); } } diff --git a/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/services/MemberService.kt b/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/services/MemberService.kt index 45feaac..3ac05af 100644 --- a/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/services/MemberService.kt +++ b/mybatis/src/main/kotlin/com/sumo/cloudnative/mybatis/services/MemberService.kt @@ -6,6 +6,8 @@ import org.apache.ibatis.annotations.Mapper import org.apache.ibatis.annotations.Select import org.springframework.stereotype.Service import org.springframework.beans.factory.annotation.Autowired +import org.springframework.cloud.sleuth.Span +import org.springframework.cloud.sleuth.Tracer @Mapper public interface MemberMapper { @@ -22,12 +24,25 @@ public interface MemberMapper { } @Service -class MemberService @Autowired constructor(val mapper: MemberMapper) { +class MemberService @Autowired constructor(val mapper: MemberMapper, + var tracer: Tracer) { fun findAll() : List { return mapper.findAll() ; } fun findById(id: Int) : Member { - return mapper.findById(id) ; + var span = tracer.createSpan("Lookup member"); + + tracer.addTag("memberId", id.toString()); + + span.logEvent("DB query started"); + + var member = mapper.findById(id) ; + + span.logEvent("DB query ended"); + + tracer.close(span); + + return member ; } } diff --git a/mybatis/src/main/resources/application.yml b/mybatis/src/main/resources/application.yml index 201b45c..bfa7c86 100644 --- a/mybatis/src/main/resources/application.yml +++ b/mybatis/src/main/resources/application.yml @@ -1,8 +1,16 @@ server: port: 8083 -spring: + h2: console: enabled: true - path: /console \ No newline at end of file + path: /console + + +logging: + level: + org: + springframework: + cloud: + sleuth: DEBUG \ No newline at end of file diff --git a/mybatis/src/main/resources/bootstrap.yml b/mybatis/src/main/resources/bootstrap.yml index e71604a..7a6cf88 100644 --- a/mybatis/src/main/resources/bootstrap.yml +++ b/mybatis/src/main/resources/bootstrap.yml @@ -5,15 +5,27 @@ spring: application: name: mybatis cloud: - config: - enabled: true +# config: +# enabled: true +# discovery: +# enabled: true +# serviceId: CONFIG + consul: + host: localhost + port: 8500 discovery: + instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} enabled: true - serviceId: CONFIG + preferIpAddress: true + ip-address: 127.0.0.1 -eureka: - instance: - nonSecurePort: ${server.port:8083} - client: - serviceUrl: - defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file + sleuth: + sampler: + percentage: 1.0 + +#eureka: +# instance: +# nonSecurePort: ${server.port:8083} +# client: +# serviceUrl: +# defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/producer/app.groovy b/producer/app.groovy index 4ef696d..9114226 100755 --- a/producer/app.groovy +++ b/producer/app.groovy @@ -1,14 +1,41 @@ //@Grab("spring-cloud-netflix-hystrix-stream") +@Grab("org.springframework.kafka:spring-kafka:1.1.1.RELEASE") +@Grab("org.springframework.integration:spring-integration-kafka:2.1.0.RELEASE") +@Grab("org.apache.kafka:kafka_2.11:0.10.0.0") +@GrabExclude("org.slf4j:slf4j-log4j12") @Grab("spring-cloud-starter-bus-kafka") -@EnableDiscoveryClient -@EnableCircuitBreaker +@Grab("spring-cloud-sleuth-stream") +@Grab("spring-cloud-starter-consul-discovery") +@Grab("spring-cloud-starter-consul-config") +@Grab(group='org.springframework.cloud', module='spring-cloud-vault-starter-config', version='1.0.0.M1') +@Grab(group='org.springframework.cloud', module='spring-cloud-vault-config-databases', version='1.0.0.M1') +//@Grab(group='org.springframework.cloud', module='spring-cloud-vault-config-consul', version='1.0.0.M1') +@Grab("spring-cloud-starter-hystrix") +@Grab("spring-boot-starter-jdbc") +@Grab("mysql:mysql-connector-java:5.1.32") + + + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; + +import javax.sql.DataSource; +import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; + + @RestController @Log +@EnableDiscoveryClient +@EnableCircuitBreaker class Application { @Autowired Greeter greeter + @Autowired + DataSource dataSource; + int counter = 0 @RequestMapping(value = "/counter", produces = "application/json") @@ -19,9 +46,32 @@ class Application { "{\"value\": ${counter}}" } + @RequestMapping("/greet") + String greet() { + + "${greeter.greeting} World!" + } + @RequestMapping("/") String home() { - "${greeter.greeting} World!" + + + log.info("##########################"); + + Connection connection = dataSource.getConnection() + Statement statement = connection.createStatement() + + ResultSet resultSet = statement.executeQuery("SELECT * from test;"); + resultSet.next(); + + String val = resultSet.getString(1); + + + resultSet.close(); + + log.info("##########################"); + + "Connection works with User: " + val } @RequestMapping(value = '/questions/{questionId}') diff --git a/producer/bootstrap.yml b/producer/bootstrap.yml index fa31985..354470f 100755 --- a/producer/bootstrap.yml +++ b/producer/bootstrap.yml @@ -4,18 +4,64 @@ server: spring: application: name: producer + datasource: + url: jdbc:mysql://localhost:3306/Producer cloud: - config: - enabled: true + consul: + host: localhost + port: 8500 + #acl-token: 2ee647bd-bd69-4118-9f34-b9a6e9e60746 discovery: + instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}} + #health-check-url: http://127.0.0.1:${server.port}/health + enabled: true + preferIpAddress: true + ip-address: 127.0.0.1 + config: enabled: true + prefix: config/master + format: FILES + config: + enabled: false + discovery: + enabled: false serviceId: CONFIG + vault: + host: localhost + port: 8200 + scheme: https + connection-timeout: 5000 + read-timeout: 15000 + config: + order: -10 + token: c67f9d8d-5647-b65a-7d81-d7c62bd00d0e + ssl: + trust-store: file:../infra/vault/work/keystore.jks + consul: + enabled: true + role: readonly + mysql: + enabled: true + role: readonly + + + + sleuth: + sampler: + percentage: 1.0 + +#logging: +# level: +# org: +# springframework: +# cloud: +# sleuth: DEBUG eureka: - instance: - nonSecurePort: ${server.port:8081} -# metadataMap: -# instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${server.port}}} + # instance: + # nonSecurePort: ${server.port:8085} client: - serviceUrl: - defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file + register-with-eureka: false + fetch-registry: false + #serviceUrl: + #defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/zipkin/README.md b/zipkin/README.md new file mode 100644 index 0000000..c6ed049 --- /dev/null +++ b/zipkin/README.md @@ -0,0 +1,18 @@ +Zipkin Server +------------- + +To start zipkin server + +cd zipkin +spring run . + +http://localhost:8988 + +To experiment with zipkin + +Start the below apps in the specified order + +zookeeper > kafka > eureka > config > zipkin > producer > creditinfo > +getaddress > promo > reco > hystrix > mybatis > aggregator + +p.s find projects under Distributed tracing folder \ No newline at end of file diff --git a/zipkin/app.groovy b/zipkin/app.groovy new file mode 100644 index 0000000..eb27fe0 --- /dev/null +++ b/zipkin/app.groovy @@ -0,0 +1,16 @@ +@Grab("org.springframework.kafka:spring-kafka:1.1.1.RELEASE") +@Grab("org.springframework.integration:spring-integration-kafka:2.1.0.RELEASE") +@Grab("org.apache.kafka:kafka_2.11:0.10.0.0") +@GrabExclude("org.slf4j:slf4j-log4j12") +@Grab("spring-cloud-starter-bus-kafka") +@Grab("zipkin-server") +@Grab("zipkin-autoconfigure-ui") +@Grab("spring-cloud-sleuth-zipkin-stream") + +import org.springframework.cloud.sleuth.zipkin.stream.EnableZipkinStreamServer + + + +@EnableZipkinStreamServer +class ZipKinServer { +} \ No newline at end of file diff --git a/zipkin/bootstrap.yml b/zipkin/bootstrap.yml new file mode 100644 index 0000000..5f15c55 --- /dev/null +++ b/zipkin/bootstrap.yml @@ -0,0 +1,6 @@ +server: + port: 8988 + +spring: + application: + name: ZipkinServer