You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ke...@apache.org on 2021/11/04 04:34:38 UTC

[skywalking-showcase] 05/12: Add Python service

This is an automated email from the ASF dual-hosted git repository.

kezhenxu94 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-showcase.git

commit 28db6046d8f9675d38419027d83e086821ac80ae
Author: kezhenxu94 <ke...@apache.org>
AuthorDate: Fri Oct 29 14:41:02 2021 +0800

    Add Python service
---
 .gitignore                                         |  2 +-
 Makefile                                           | 26 ++++++++++----
 Makefile.in                                        |  6 ++++
 deploy/platform/docker/.env                        |  3 --
 deploy/platform/docker/Makefile                    |  6 +---
 deploy/platform/docker/docker-compose.yaml         | 22 +++++++++---
 services/camry-music/package.json                  | 10 ++++++
 .../src/main/resources/application.yaml            |  4 +++
 services/recommendation-service/.dockerignore      |  2 ++
 services/recommendation-service/Dockerfile         | 11 ++++++
 .../recommendation-service/Makefile                | 16 +++++++--
 services/recommendation-service/requirements.txt   |  2 ++
 services/recommendation-service/src/app.py         | 40 ++++++++++++++++++++++
 .../services/song/SongServiceApplication.java      | 17 +++++++--
 .../services/song/controller/SongController.java   | 19 ++++++++++
 .../showcase/services/song/entity/Song.java        |  3 ++
 .../showcase/services/song/repo/SongsRepo.java     |  2 ++
 .../showcase/services/song/vo/TrendingList.java    | 11 ++++++
 services/songs-service/src/main/resources/data.sql |  8 +++--
 19 files changed, 181 insertions(+), 29 deletions(-)

diff --git a/.gitignore b/.gitignore
index b14baaa..6388ee9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,7 +21,7 @@
 # Ignore Gradle build output directory
 build
 
-.venv
+venv
 
 .DS_Store
 
diff --git a/Makefile b/Makefile
index afe2e86..2ccce23 100644
--- a/Makefile
+++ b/Makefile
@@ -16,18 +16,30 @@
 # under the License.
 #
 
+# Build each project under services/*
+
+services = $(wildcard services/*)
+
+.PHONY: $(services)
+$(services):
+	$(MAKE) -C $@ build
+
 .PHONY: build
-build:
-	$(MAKE) -C services/gateway-service build
-	$(MAKE) -C services/songs-service build
+build: $(services)
+
+# Build Docker images
+
+services_docker = $(foreach svc,$(services),$(svc).docker.build)
 
 .PHONY: docker
-docker: docker.build
+docker: $(services_docker)
+
+.PHONY: $(services_docker)
+$(services_docker): %.docker.build: %
+	$(MAKE) -C $< docker.build
 
 .PHONY: docker.build
-docker.build:
-	$(MAKE) -C services/gateway-service docker.build
-	$(MAKE) -C services/songs-service docker.build
+docker.build: $(services_docker)
 
 .PHONY: deploy.docker
 deploy.docker: undeploy.docker docker.build
diff --git a/Makefile.in b/Makefile.in
index 1a32095..800ad9a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -16,5 +16,11 @@
 # under the License.
 #
 
+.EXPORT_ALL_VARIABLES:
+
 HUB ?= ghcr.io/apache/skywalking-showcase
 TAG ?= $(shell git rev-parse --short HEAD)
+
+ES_VERSION ?= 7.10.0
+OAP_IMAGE ?= ghcr.io/apache/skywalking/oap:c9bd79e8bb974e404766e3490c00c7404b9baf1e
+ROCKET_BOT_IMAGE ?= ghcr.io/apache/skywalking/ui:c9bd79e8bb974e404766e3490c00c7404b9baf1e
diff --git a/deploy/platform/docker/.env b/deploy/platform/docker/.env
deleted file mode 100644
index 977da00..0000000
--- a/deploy/platform/docker/.env
+++ /dev/null
@@ -1,3 +0,0 @@
-ES_VERSION=7.10.0
-OAP_IMAGE=ghcr.io/apache/skywalking/oap:c9bd79e8bb974e404766e3490c00c7404b9baf1e
-ROCKET_BOT_IMAGE=ghcr.io/apache/skywalking/ui:c9bd79e8bb974e404766e3490c00c7404b9baf1e
diff --git a/deploy/platform/docker/Makefile b/deploy/platform/docker/Makefile
index 06547b7..f0b5f4b 100644
--- a/deploy/platform/docker/Makefile
+++ b/deploy/platform/docker/Makefile
@@ -2,12 +2,8 @@ include ../../../Makefile.in
 
 .PHONY: deploy
 deploy:
-	export HUB=$(HUB); \
-	export TAG=$(TAG); \
 	docker-compose up -d
 
 .PHONY: undeploy
 undeploy:
-	export HUB=$(HUB); \
-	export TAG=$(TAG); \
-	docker-compose down
+	docker-compose --log-level ERROR down
diff --git a/deploy/platform/docker/docker-compose.yaml b/deploy/platform/docker/docker-compose.yaml
index 201a8d6..f23f0d3 100644
--- a/deploy/platform/docker/docker-compose.yaml
+++ b/deploy/platform/docker/docker-compose.yaml
@@ -55,8 +55,6 @@ services:
     environment:
       SW_AGENT_NAME: gateway
       SW_AGENT_COLLECTOR_BACKEND_SERVICES: oap:11800
-    ports:
-      - "7389:80"
     healthcheck:
       test: [ "CMD-SHELL", "wget http://localhost/actuator/health" ]
       interval: 30s
@@ -74,8 +72,6 @@ services:
     environment:
       SW_AGENT_NAME: songs
       SW_AGENT_COLLECTOR_BACKEND_SERVICES: oap:11800
-    ports:
-      - "7390:80"
     healthcheck:
       test: [ "CMD-SHELL", "wget http://localhost/actuator/health" ]
       interval: 30s
@@ -85,6 +81,21 @@ services:
       oap:
         condition: service_healthy
 
+  rcmd:
+    image: ${HUB}/recommendation-service:${TAG}
+    networks: [ sw ]
+    environment:
+      SW_AGENT_NAME: recommendation
+      SW_AGENT_COLLECTOR_BACKEND_SERVICES: oap:11800
+    healthcheck:
+      test: [ "CMD-SHELL", "curl http://localhost/health" ]
+      interval: 30s
+      timeout: 10s
+      retries: 3
+    depends_on:
+      oap:
+        condition: service_healthy
+
   loadgen:
     image: curlimages/curl
     networks: [ sw ]
@@ -96,7 +107,8 @@ services:
       - -c
       - |
         while true; do
-          curl http://gateway/songs
+          curl http://gateway/songs/top
+          curl http://gateway/songs/favorites
           sleep 3
         done
 
diff --git a/services/camry-music/package.json b/services/camry-music/package.json
new file mode 100644
index 0000000..6e45e8b
--- /dev/null
+++ b/services/camry-music/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "camry-music",
+  "version": "1.0.0",
+  "description": "The entrypoint of the showcase application",
+  "main": "index.js",
+  "scripts": {
+  },
+  "author": "kezhenxu94",
+  "license": "Apache-2.0"
+}
diff --git a/services/gateway-service/src/main/resources/application.yaml b/services/gateway-service/src/main/resources/application.yaml
index 582dff9..4fa9a53 100644
--- a/services/gateway-service/src/main/resources/application.yaml
+++ b/services/gateway-service/src/main/resources/application.yaml
@@ -10,3 +10,7 @@ spring:
           uri: http://songs
           predicates:
             - Path=/songs/**
+        - id: recommendation-service
+          uri: http://rcmd
+          predicates:
+            - Path=/rcmd/**
diff --git a/services/recommendation-service/.dockerignore b/services/recommendation-service/.dockerignore
new file mode 100644
index 0000000..a415184
--- /dev/null
+++ b/services/recommendation-service/.dockerignore
@@ -0,0 +1,2 @@
+venv
+.venv
diff --git a/services/recommendation-service/Dockerfile b/services/recommendation-service/Dockerfile
new file mode 100644
index 0000000..bff98f7
--- /dev/null
+++ b/services/recommendation-service/Dockerfile
@@ -0,0 +1,11 @@
+FROM apache/skywalking-python:0.7.0-grpc-py3.9
+
+WORKDIR /workspace
+
+COPY requirements.txt .
+
+RUN pip install -r requirements.txt
+
+COPY src .
+
+CMD python app.py
diff --git a/Makefile.in b/services/recommendation-service/Makefile
similarity index 74%
copy from Makefile.in
copy to services/recommendation-service/Makefile
index 1a32095..3395621 100644
--- a/Makefile.in
+++ b/services/recommendation-service/Makefile
@@ -16,5 +16,17 @@
 # under the License.
 #
 
-HUB ?= ghcr.io/apache/skywalking-showcase
-TAG ?= $(shell git rev-parse --short HEAD)
+include ../../Makefile.in
+
+.PHONY: build
+build: docker.build
+
+.PHONY: docker docker.build docker.push
+
+docker: docker.push
+
+docker.build:
+	docker build . -t $(HUB)/recommendation-service:$(TAG)
+
+docker.push: docker.build
+	docker push $(HUB)/recommendation-service:$(TAG)
diff --git a/services/recommendation-service/requirements.txt b/services/recommendation-service/requirements.txt
new file mode 100644
index 0000000..50691c2
--- /dev/null
+++ b/services/recommendation-service/requirements.txt
@@ -0,0 +1,2 @@
+Flask==2.0.2
+requests==2.26.0
diff --git a/services/recommendation-service/src/app.py b/services/recommendation-service/src/app.py
new file mode 100644
index 0000000..64aa0b1
--- /dev/null
+++ b/services/recommendation-service/src/app.py
@@ -0,0 +1,40 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import os
+
+import requests
+
+if __name__ == '__main__':
+    from flask import Flask, jsonify
+
+    app = Flask(__name__)
+
+
+    @app.route('/health', methods=['GET'])
+    def health():
+        return 'OK'
+
+
+    @app.route('/rcmd', methods=['GET'])
+    def application():
+        r = requests.get('http://gateway/songs')
+        recommendations = r.json()
+        return jsonify(recommendations)
+
+
+    PORT = os.getenv('PORT', 80)
+    app.run(host='0.0.0.0', port=PORT)
diff --git a/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/SongServiceApplication.java b/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/SongServiceApplication.java
index 034a90f..3040714 100644
--- a/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/SongServiceApplication.java
+++ b/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/SongServiceApplication.java
@@ -17,16 +17,27 @@
  * under the License.
  *
  */
+
 package org.apache.skywalking.showcase.services.song;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.DefaultUriTemplateHandler;
 
 @SpringBootApplication
 public class SongServiceApplication {
+    @Bean
+    public RestTemplate restTemplate() {
+        return new RestTemplateBuilder()
+            .rootUri("http://gateway")
+            .build();
+    }
 
-	public static void main(String[] args) {
-		SpringApplication.run(SongServiceApplication.class, args);
-	}
+    public static void main(String[] args) {
+        SpringApplication.run(SongServiceApplication.class, args);
+    }
 
 }
diff --git a/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/controller/SongController.java b/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/controller/SongController.java
index 6dcafb2..4fcbbb2 100644
--- a/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/controller/SongController.java
+++ b/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/controller/SongController.java
@@ -22,18 +22,37 @@ import java.util.List;
 import lombok.RequiredArgsConstructor;
 import org.apache.skywalking.showcase.services.song.entity.Song;
 import org.apache.skywalking.showcase.services.song.repo.SongsRepo;
+import org.apache.skywalking.showcase.services.song.vo.TrendingList;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
 
 @RestController
 @RequiredArgsConstructor
 @RequestMapping("/songs")
 public class SongController {
     private final SongsRepo songsRepo;
+    private final RestTemplate restTemplate;
 
     @GetMapping
     public List<Song> songs() {
         return songsRepo.findAll();
     }
+
+    @GetMapping("/top")
+    public TrendingList top() {
+        final List<Song> top = songsRepo.findByLikedGreaterThan(1000);
+        final ResponseEntity<List<Song>> res = restTemplate.exchange(
+            "/rcmd", HttpMethod.GET, null, new ParameterizedTypeReference<List<Song>>() {
+            });
+        if (res.getStatusCode() != HttpStatus.OK) {
+            throw new RuntimeException("Failed to get recommendations");
+        }
+        return new TrendingList(top, res.getBody());
+    }
 }
diff --git a/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/entity/Song.java b/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/entity/Song.java
index 7d5a57a..10c683c 100644
--- a/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/entity/Song.java
+++ b/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/entity/Song.java
@@ -43,4 +43,7 @@ public class Song {
 
     @Column
     private String genre;
+
+    @Column(nullable = false)
+    private long liked = 0;
 }
diff --git a/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/repo/SongsRepo.java b/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/repo/SongsRepo.java
index 7e12707..756053b 100644
--- a/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/repo/SongsRepo.java
+++ b/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/repo/SongsRepo.java
@@ -18,10 +18,12 @@
 
 package org.apache.skywalking.showcase.services.song.repo;
 
+import java.util.List;
 import org.apache.skywalking.showcase.services.song.entity.Song;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
 
 @Repository
 public interface SongsRepo extends JpaRepository<Song, Integer> {
+    List<Song> findByLikedGreaterThan(long count);
 }
diff --git a/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/vo/TrendingList.java b/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/vo/TrendingList.java
new file mode 100644
index 0000000..cc4438e
--- /dev/null
+++ b/services/songs-service/src/main/java/org/apache/skywalking/showcase/services/song/vo/TrendingList.java
@@ -0,0 +1,11 @@
+package org.apache.skywalking.showcase.services.song.vo;
+
+import java.util.List;
+import lombok.Data;
+import org.apache.skywalking.showcase.services.song.entity.Song;
+
+@Data
+public class TrendingList {
+    private final List<Song> top;
+    private final List<Song> recommendations;
+}
diff --git a/services/songs-service/src/main/resources/data.sql b/services/songs-service/src/main/resources/data.sql
index 0bda17a..2942750 100644
--- a/services/songs-service/src/main/resources/data.sql
+++ b/services/songs-service/src/main/resources/data.sql
@@ -27,7 +27,9 @@
 --
 
 insert into song
-    (id, name, artist, genre)
-values (1, '倩女幽魂', '张国荣', 'HK-POP'),
-       (2, '沉默是金', '张国荣', 'HK-POP')
+    (id, name, artist, genre, liked)
+values (1, '倩女幽魂', '张国荣', 'HK-POP', 999),
+       (2, '沉默是金', '张国荣', 'HK-POP', 1000),
+       (3, '风继续吹', '张国荣', 'HK-POP', 1002),
+       (4, '灰色轨迹', 'Beyond', 'HK-POP', 9000)
 ;