אפליקציית Spring Spanner עם שירות Cloud Spanner

1. סקירה כללית

Cloud Spanner הוא שירות RDBMS עם זמינות גבוהה, יכולת התאמה לרוחב ומספר אזורים. במעבדת הקוד הזו ייעשה שימוש במופע הקטן ביותר של Cloud Spanner, אבל חשוב לזכור להשבית אותו בסיום.

מה תלמדו

  • איך משתמשים ב-Cloud Spanner כדי לשמור ולאחזר נתונים באמצעות Springboo

מה נדרש

  • פרויקט ב-Google Cloud Platform
  • דפדפן, כמו Chrome או Firefox

איך תשתמשו במדריך הזה?

לקריאה בלבד לקרוא אותו ולבצע את התרגילים

איזה דירוג מגיע לדעתך לחוויית השימוש בשירותי Google Cloud Platform?

מתחילים בינונית בקיאים

2. הגדרה ודרישות

הגדרת סביבה בקצב עצמאי

  1. נכנסים למסוף Cloud ויוצרים פרויקט חדש או עושים שימוש חוזר בפרויקט קיים. (אם עדיין אין לכם חשבון Gmail או G Suite, עליכם ליצור חשבון).

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

חשוב לזכור את מזהה הפרויקט, שם ייחודי לכל הפרויקטים ב-Google Cloud (השם שלמעלה כבר תפוס ולא מתאים לכם, סליחה). בהמשך ב-Codelab הזה, היא תיקרא PROJECT_ID.

  1. בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים של Google Cloud.

מעבר ב-Codelab הזה לא אמור לעלות הרבה, אם בכלל. חשוב לבצע את כל ההוראות בקטע 'ניקוי' שמסביר איך להשבית משאבים כדי שלא תצברו חיובים מעבר למדריך הזה. משתמשים חדשים ב-Google Cloud זכאים להשתתף בתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.

הפעלת Cloud Shell

  1. במסוף Cloud, לוחצים על Activate Cloud Shell H7JlbhKGHITmsxhQIcLwoe5HXZMhDlYue4K-SPszMxUxDjIeWfOHBfxDHYpmLQTzUmQ7Xx8o6OJUlANnQF0iBuUyfp1RWzVad_4nCwUyfp1RWzVad_4nCwlZUDZ5LtFCZUHBfxDHYpmLQTzUmQ7Xx8o6OJUlANnQF0iBuUyfp1RWzVad_4nCwZlZ5Lt.

zlNW0HehB_AFW1qZ4AyebSQUdWm95n7TbnOr7UVm3j9dFcg6oWApJRlC0jnU1Mvb-IQp-trP1Px8xKNwt6o3pP6fyih947sEhOFI4IRF0W7WZk6hFqZDUGXQQXrw21GuMm2ecHrbzQ

אם זו הפעם הראשונה שאתם מפעילים את Cloud Shell, יוצג לכם מסך ביניים (בחלק הנגלל) שמתאר מהו. במקרה כזה, לוחצים על המשך (וזה לא יקרה שוב). כך נראה המסך החד-פעמי:

kEPbNAo_w5C_pi9QvhFwWwky1cX8hr_xEMGWySNIoMCdi-Djx9AQRqWn-__DmEpC7vKgUtl-feTcv-wBxJ8NwzzAp7mY65-fi2LJo4twUoewT1SUjd6Y3h81RG3rKIkqhoVlFR-G7w

ההקצאה וההתחברות ל-Cloud Shell נמשכת כמה דקות.

pTv5mEKzWMWp5VBrg2eGcuRPv9dLInPToS-mohlrqDASyYGWnZ_SwE-MzOWHe76ZdCSmw0kgWogSJv27lrQE8pvA5OD6P1I47nz8vrAdK7yR1NseZKJvcxAZrPb8wRxoqyTpD-gbhA

למכונה הווירטואלית הזו נטען כל כלי הפיתוח הדרושים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר משמעותית את ביצועי הרשת והאימות. אם לא את כולן, ניתן לבצע חלק גדול מהעבודה ב-Codelab הזה באמצעות דפדפן או Chromebook.

אחרי ההתחברות ל-Cloud Shell, אתם אמורים לראות שכבר בוצע אימות ושהפרויקט כבר מוגדר למזהה הפרויקט שלכם.

  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שהאימות בוצע:
gcloud auth list

פלט הפקודה

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
gcloud config list project

פלט הפקודה

[core]
project = <PROJECT_ID>

אם היא לא נמצאת שם, תוכלו להגדיר אותה באמצעות הפקודה הבאה:

gcloud config set project <PROJECT_ID>

פלט הפקודה

Updated property [core/project].

3. אתחול של Cloud Spanner

מפעילים את Cloud Spanner API באמצעות ה-CLI של gcloud:

gcloud services enable spanner.googleapis.com

יוצרים מכונה של Cloud Spanner:

gcloud spanner instances create spanner-instance \
 --config=regional-us-central1 \
 --nodes=1 --description="A Spanner Instance"

יוצרים מסד נתונים בתוך המכונה:

gcloud spanner databases create orders \
  --instance=spanner-instance

יוצרים קובץ schema.ddl כדי לתאר את סכימת הנתונים:

cat << EOF > schema.ddl
CREATE TABLE orders (
  order_id STRING(36) NOT NULL,
  description STRING(255),
  creation_timestamp TIMESTAMP,
) PRIMARY KEY (order_id);

CREATE TABLE order_items (
  order_id STRING(36) NOT NULL,
  order_item_id STRING(36) NOT NULL,
  description STRING(255),
  quantity INT64,
) PRIMARY KEY (order_id, order_item_id),
  INTERLEAVE IN PARENT orders ON DELETE CASCADE;
EOF

מחילים את הסכימה על מסד הנתונים של Cloud Spanner:

gcloud spanner databases ddl update orders \
  --instance=spanner-instance \
  --ddl="$(<schema.ddl)"

4. אתחול אפליקציית Spring Boot Java חדשה

בסביבת Cloud Shell, משתמשים בפקודה הבאה כדי לאתחל ולהפעיל אפליקציית Spring Boot חדשה:

$ curl https://start.spring.io/starter.tgz \
  -d packaging=jar \
  -d dependencies=cloud-gcp,web,lombok \
  -d baseDir=spanner-example \
  -d type=maven-project \
  -d bootVersion=3.2.6 | tar -xzvf -

$ cd spanner-example

הפעולה הזו תיצור ספריית spanner-example/ חדשה עם פרויקט Maven חדש, וגם pom.xml של Maven, wrapper של Maven ונקודת כניסה לאפליקציה.

בקובץ pom.xml, מוסיפים את הסימן לתחילת פעולה ב-Spring Data Cloud Spanner.

spanner-example/pom.xml

<project>
  ...
  <dependencies>
        ...
        <!-- Add Spring Cloud GCP Spanner Starter -->
        <dependency>
                <groupId>com.google.cloud</groupId>
                <artifactId>spring-cloud-gcp-starter-data-spanner</artifactId>
        </dependency>

        ...

  </dependencies>

  ...
</project>

ב- application.properties, מגדירים את פרטי החיבור למסד הנתונים של Spanner:

spanner-example/src/main/resources/application.properties

spring.cloud.gcp.spanner.instance-id=spanner-instance
spring.cloud.gcp.spanner.database=orders

מוודאים שבמכשיר JAVA_HOME מותקנת הגרסה הנכונה:

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/

צריך ליצור מחדש את האפליקציה כדי לוודא שההגדרה של Maven נכונה:

./mvnw package

5. יצירת הישויות

בעזרת התמיכה ב-Spring Data Spanner של Spring Cloud GCP, אפשר ליצור בקלות אובייקט Java ולמפות ORM אידיומטי לטבלת Spanner באמצעות נתוני Spring.

קודם צריך ליצור מחלקה של הפריט בהזמנה.

spanner-example/src/main/java/com/example/demo/OrderItem.java

package com.example.demo;

import com.google.cloud.spring.data.spanner.core.mapping.Column;
import com.google.cloud.spring.data.spanner.core.mapping.PrimaryKey;
import com.google.cloud.spring.data.spanner.core.mapping.Table;

@Table(name="order_items")
@Data
class OrderItem {
  @PrimaryKey(keyOrder = 1)
  @Column(name="order_id")
  private String orderId;

  @PrimaryKey(keyOrder = 2)
  @Column(name="order_item_id")
  private String orderItemId;

  private String description;
  private Long quantity;
}

בקשרים של הורה/ילד ב-Spanner, צריך להשתמש במפתח ראשי מורכב. בדוגמה הזו, המפתח המורכב הוא order_id ו-order_item_id.

בשלב הבא, יוצרים מחלקה מסוג Order:

spanner-example/src/main/java/com/example/demo/Order.java

package com.example.demo;

import java.time.LocalDateTime;
import java.util.List;
import lombok.Data;
import com.google.cloud.spring.data.spanner.core.mapping.Column;
import com.google.cloud.spring.data.spanner.core.mapping.Interleaved;
import com.google.cloud.spring.data.spanner.core.mapping.PrimaryKey;
import com.google.cloud.spring.data.spanner.core.mapping.Table;

@Table(name="orders")
@Data
public class Order {
  @PrimaryKey
  @Column(name="order_id")
  private String id;

  private String description;

  @Column(name="creation_timestamp")
  private LocalDateTime timestamp;

  @Interleaved
  private List<OrderItem> items;
}

הכיתה הזו משתמשת בהערה @Interleaved כדי ליצור קשר אחד או יותר עם פריטי ההזמנה.

6. יצירת הממשק של OrderRepository

יוצרים את הכיתה OrderRepository עם התוכן הבא:

spanner-example/src/main/java/com/example/demo/OrderRepository.java

package com.example.demo;

import com.google.cloud.spring.data.spanner.repository.SpannerRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderRepository extends SpannerRepository<Order, String> {
}

הממשק מתרחב של SpannerRepository<Order, String> כאשר Order הוא מחלקת הדומיין ו-String הוא סוג המפתח הראשי. נתוני Spring Data יאפשרו באופן אוטומטי גישת CRUD דרך הממשק הזה, ולא תצטרכו ליצור קוד נוסף.

7. יצירת בקר REST לפעולות בסיסיות

פותחים את המחלקה הראשית DemoApplication של האפליקציה ומשנים אותה כך שייראה כך:

spanner-example/src/main/java/com/example/demo/DemoApplication.java

package com.example.demo;

import java.time.LocalDateTime;
import java.util.UUID;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

@SpringBootApplication
public class DemoApplication {
        public static void main(String[] args) {
                SpringApplication.run(DemoApplication.class, args);
        }
}

@RestController
class OrderController {
  private final OrderRepository orderRepository;

        OrderController(OrderRepository orderRepository) {
                this.orderRepository = orderRepository;
        }

        @GetMapping("/api/orders/{id}")
        public Order getOrder(@PathVariable String id) {
          return orderRepository.findById(id)
                                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, id + " not found"));
        }

        @PostMapping("/api/orders")
        public String createOrder(@RequestBody Order order) {
                // Spanner currently does not auto generate IDs
                // Generate UUID on new orders
                order.setId(UUID.randomUUID().toString());
                order.setTimestamp(LocalDateTime.now());

                order.getItems().forEach(item -> {
                        // Assign parent ID, and also generate child ID
                        item.setOrderId(order.getId());
                        item.setOrderItemId(UUID.randomUUID().toString());
                });

          Order saved = orderRepository.save(order);
          return saved.getId();
        }
}

8. הפעלת האפליקציה

בונים ומפעילים מחדש את האפליקציה

./mvnw spring-boot:run

הפעולה הזו אמורה להתחיל כראוי ולהאזין ביציאה 8080.

אפשר לפרסם רשומת הזמנה בנקודת הקצה:

curl -H"Content-Type: application/json" -d'{"description": "My orders", "items": [{"description": "Android Phone", "quantity": "1"}]}' \
  http://localhost:8080/api/orders

התגובה צריכה לכלול את UUID של ההזמנה.

לאחר מכן אפשר לאחזר את ההזמנה באמצעות UUID:

curl http://localhost:8080/api/orders/REPLACE_WITH_ORDER_UUID

כדי לראות איך הנתונים מאוחסנים ב-Cloud Spanner, עוברים למסוף Cloud ועוברים אל Spanner ← Spanner Instance ← מסד נתונים של הזמנות ← טבלת הזמנות ← נתונים.

780f4947e4a864f6.png

9. הסרת המשאבים

כדי למחוק את המופע, צריך למחוק את המכונה של Spanner כדי שלא יצטברו יותר חיובים.

gcloud spanner instances delete spanner-instance -q

10. מעולה!

ב-Codelab הזה יצרתם אפליקציית CLI אינטראקטיבית שיכולה לאחסן ולאחזר נתונים מ-Cloud Spanner!

מידע נוסף

רישיון

היצירה הזו בשימוש ברישיון Creative Commons Attribution 2.0 גנרי.