1. بررسی اجمالی
در اولین آزمایشگاه کد، تصاویر را در یک سطل ذخیره خواهید کرد. این یک رویداد ایجاد فایل ایجاد می کند که توسط یک سرویس مستقر در Cloud Run مدیریت می شود. این سرویس با Vision API تماس می گیرد تا تجزیه و تحلیل تصویر را انجام دهد و نتایج را در یک دیتا استور ذخیره کند.
چیزی که یاد خواهید گرفت
- فضای ذخیره سازی ابری
- Cloud Run
- Cloud Vision API
- Cloud Firestore
2. راه اندازی و الزامات
تنظیم محیط خود به خود
- به Google Cloud Console وارد شوید و یک پروژه جدید ایجاد کنید یا از یک موجود استفاده مجدد کنید. اگر قبلاً یک حساب Gmail یا Google Workspace ندارید، باید یک حساب ایجاد کنید .
- نام پروژه نام نمایشی برای شرکت کنندگان این پروژه است. این یک رشته کاراکتری است که توسط API های Google استفاده نمی شود. شما می توانید آن را در هر زمان به روز کنید.
- شناسه پروژه باید در تمام پروژههای Google Cloud منحصربهفرد باشد و تغییرناپذیر باشد (پس از تنظیم نمیتوان آن را تغییر داد). Cloud Console به طور خودکار یک رشته منحصر به فرد تولید می کند. معمولاً برای شما مهم نیست که چیست. در اکثر کدها، باید به شناسه پروژه ارجاع دهید (معمولاً به عنوان
PROJECT_ID
شناخته می شود). اگر شناسه تولید شده را دوست ندارید، ممکن است یک شناسه تصادفی دیگر ایجاد کنید. از طرف دیگر، میتوانید خودتان را امتحان کنید و ببینید آیا در دسترس است یا خیر. پس از این مرحله نمی توان آن را تغییر داد و در طول مدت پروژه باقی می ماند. - برای اطلاع شما، یک مقدار سوم وجود دارد، یک شماره پروژه که برخی از API ها از آن استفاده می کنند. در مورد هر سه این مقادیر در مستندات بیشتر بیاموزید.
- در مرحله بعد، برای استفاده از منابع Cloud/APIها باید صورتحساب را در کنسول Cloud فعال کنید . اجرا کردن از طریق این کد لبه نباید هزینه زیادی داشته باشد، اگر اصلاً باشد. برای اینکه منابع را خاموش کنید تا بیش از این آموزش متحمل صورتحساب نشوید، می توانید منابعی را که ایجاد کرده اید حذف کنید یا کل پروژه را حذف کنید. کاربران جدید Google Cloud واجد شرایط برنامه آزمایشی رایگان 300 دلاری هستند.
Cloud Shell را راه اندازی کنید
در حالی که Google Cloud را می توان از راه دور از لپ تاپ شما کار کرد، در این کد لبه از Google Cloud Shell استفاده خواهید کرد، یک محیط خط فرمان که در Cloud اجرا می شود.
از Google Cloud Console ، روی نماد Cloud Shell در نوار ابزار بالا سمت راست کلیک کنید:
تهیه و اتصال به محیط فقط چند لحظه طول می کشد. وقتی تمام شد، باید چیزی شبیه به این را ببینید:
این ماشین مجازی با تمام ابزارهای توسعه که شما نیاز دارید بارگذاری شده است. این یک فهرست اصلی 5 گیگابایتی دائمی را ارائه می دهد و در Google Cloud اجرا می شود و عملکرد و احراز هویت شبکه را تا حد زیادی افزایش می دهد. تمام کارهای شما در این کد لبه را می توان در یک مرورگر انجام داد. شما نیازی به نصب چیزی ندارید.
3. API ها را فعال کنید
برای این آزمایشگاه، از Cloud Functions و Vision API استفاده خواهید کرد، اما ابتدا باید آنها را یا در Cloud Console یا با gcloud
فعال کنید.
برای فعال کردن Vision API در Cloud Console، Cloud Vision API
را در نوار جستجو جستجو کنید:
شما در صفحه Cloud Vision API قرار خواهید گرفت:
روی دکمه ENABLE
کلیک کنید.
همچنین میتوانید با استفاده از ابزار خط فرمان gcloud آن را فعال کنید.
در داخل Cloud Shell، دستور زیر را اجرا کنید:
gcloud services enable vision.googleapis.com
برای اتمام موفقیت آمیز باید عملیات را مشاهده کنید:
Operation "operations/acf.12dba18b-106f-4fd2-942d-fea80ecc5c1c" finished successfully.
Cloud Run و Cloud Build را نیز فعال کنید:
gcloud services enable cloudbuild.googleapis.com \ run.googleapis.com
4. ایجاد سطل (کنسول)
یک سطل ذخیره سازی برای تصاویر ایجاد کنید. می توانید این کار را از کنسول Google Cloud Platform ( consol.cloud.google.com ) یا با ابزار خط فرمان gsutil از Cloud Shell یا محیط توسعه محلی خود انجام دهید.
به Storage بروید
از منوی "همبرگر" (☰)، به صفحه Storage
بروید.
سطل خود را نام ببرید
روی دکمه CREATE BUCKET
کلیک کنید.
CONTINUE
کلیک کنید.
مکان را انتخاب کنید
یک سطل چند منطقه ای در منطقه مورد نظر خود ایجاد کنید (اینجا Europe
).
CONTINUE
کلیک کنید.
کلاس ذخیره سازی پیش فرض را انتخاب کنید
کلاس ذخیره سازی Standard
را برای داده های خود انتخاب کنید.
CONTINUE
کلیک کنید.
کنترل دسترسی را تنظیم کنید
از آنجایی که با تصاویر در دسترس عموم کار می کنید، می خواهید همه تصاویر ذخیره شده ما در این سطل کنترل دسترسی یکسانی داشته باشند.
گزینه Uniform
Access Control را انتخاب کنید.
CONTINUE
کلیک کنید.
حفاظت/رمزگذاری را تنظیم کنید
پیش فرض ( Google-managed key)
را حفظ کنید، زیرا از کلیدهای رمزگذاری خود استفاده نخواهید کرد.
روی CREATE
کلیک کنید تا در نهایت ایجاد سطل ما نهایی شود.
allUsers را به عنوان نمایشگر ذخیره سازی اضافه کنید
به برگه Permissions
بروید:
یک عضو allUsers
را با نقش Storage > Storage Object Viewer
به سطل اضافه کنید:
روی SAVE
کلیک کنید.
5. سطل (gsutil) را ایجاد کنید
همچنین می توانید از ابزار خط فرمان gsutil
در Cloud Shell برای ایجاد سطل استفاده کنید.
در Cloud Shell، یک متغیر برای نام سطل یکتا تنظیم کنید. Cloud Shell قبلاً GOOGLE_CLOUD_PROJECT
را روی شناسه پروژه منحصر به فرد شما تنظیم کرده است. می توانید آن را به نام سطل اضافه کنید.
به عنوان مثال:
export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
ایجاد یک منطقه استاندارد چند منطقه ای در اروپا:
gsutil mb -l EU gs://${BUCKET_PICTURES}
از دسترسی یکنواخت به سطح سطل اطمینان حاصل کنید:
gsutil uniformbucketlevelaccess set on gs://${BUCKET_PICTURES}
سطل را عمومی کنید:
gsutil iam ch allUsers:objectViewer gs://${BUCKET_PICTURES}
اگر به بخش Cloud Storage
کنسول بروید، باید یک سطل uploaded-pictures
عمومی داشته باشید:
تست کنید که می توانید تصاویر را در سطل آپلود کنید و تصاویر آپلود شده برای عموم در دسترس هستند، همانطور که در مرحله قبل توضیح داده شد.
6. دسترسی عمومی به سطل را آزمایش کنید
با بازگشت به مرورگر ذخیره سازی، سطل خود را با دسترسی «عمومی» (شامل یک علامت هشدار که به شما یادآوری می کند که هر کسی به محتوای آن سطل دسترسی دارد) را در لیست می بینید.
اکنون سطل شما برای دریافت تصاویر آماده است.
اگر روی نام سطل کلیک کنید، جزئیات سطل را مشاهده خواهید کرد.
در آنجا، میتوانید دکمه Upload files
را امتحان کنید تا آزمایش کنید که میتوانید تصویری را به سطل اضافه کنید. یک پنجره انتخابگر فایل از شما می خواهد که یک فایل را انتخاب کنید. پس از انتخاب، در سطل شما آپلود می شود و دوباره دسترسی public
را که به طور خودکار به این فایل جدید نسبت داده شده است، خواهید دید.
در کنار برچسب دسترسی Public
، نماد پیوند کوچکی را نیز مشاهده خواهید کرد. وقتی روی آن کلیک می کنید، مرورگر شما به آدرس عمومی آن تصویر می رود که به شکل زیر خواهد بود:
https://storage.googleapis.com/BUCKET_NAME/PICTURE_FILE.png
با BUCKET_NAME
نام منحصربهفرد جهانی است که برای سطل خود انتخاب کردهاید، و سپس نام فایل تصویرتان.
با کلیک بر روی کادر کنار نام تصویر، دکمه DELETE
فعال می شود و می توانید این تصویر اول را حذف کنید.
7. پایگاه داده را آماده کنید
شما اطلاعات مربوط به تصویر ارائه شده توسط Vision API را در پایگاه داده Cloud Firestore ، یک پایگاه داده اسناد NoSQL سریع، کاملا مدیریت شده، بدون سرور و بومی ابری ذخیره خواهید کرد. با رفتن به بخش Firestore
در Cloud Console پایگاه داده خود را آماده کنید:
دو گزینه ارائه می شود: Native mode
یا Datastore mode
. از حالت بومی استفاده کنید، که ویژگیهای اضافی مانند پشتیبانی آفلاین و همگامسازی بلادرنگ را ارائه میدهد.
روی SELECT NATIVE MODE
کلیک کنید.
یک منطقه چندگانه (اینجا در اروپا، اما در حالت ایده آل حداقل همان منطقه ای که عملکرد و سطل ذخیره سازی شما هستند) انتخاب کنید.
روی دکمه CREATE DATABASE
کلیک کنید.
پس از ایجاد پایگاه داده، باید موارد زیر را مشاهده کنید:
با کلیک بر روی دکمه + START COLLECTION
یک مجموعه جدید ایجاد کنید.
pictures
مجموعه نام .
شما نیازی به ایجاد سند ندارید. وقتی تصاویر جدید در Cloud Storage ذخیره می شوند و توسط Vision API تجزیه و تحلیل می شوند، آنها را به صورت برنامه نویسی اضافه خواهید کرد.
روی Save
کلیک کنید.
Firestore اولین سند پیش فرض را در مجموعه جدید ایجاد می کند، می توانید با خیال راحت آن سند را حذف کنید زیرا حاوی اطلاعات مفیدی نیست:
اسنادی که به صورت برنامه نویسی در مجموعه ما ایجاد می شوند دارای 4 فیلد خواهند بود:
- نام (رشته): نام فایل تصویر آپلود شده که کلید سند نیز می باشد
- برچسب ها (آرایه رشته ها): برچسب های موارد شناسایی شده توسط Vision API
- رنگ (رشته): کد رنگ هگزادسیمال رنگ غالب (یعنی #ab12ef)
- ایجاد (تاریخ): مُهر زمانی ذخیره شدن فراداده این تصویر
- تصویر بندانگشتی (بولی): یک فیلد اختیاری که در صورت ایجاد یک تصویر کوچک برای این تصویر وجود دارد و درست است.
از آنجایی که در Firestore برای یافتن تصاویری که دارای ریز عکسها هستند جستجو میکنیم و بر اساس تاریخ ایجاد مرتب میکنیم، باید یک فهرست جستجو ایجاد کنیم.
می توانید با دستور زیر در Cloud Shell ایندکس را ایجاد کنید:
gcloud firestore indexes composite create \
--collection-group=pictures \
--field-config field-path=thumbnail,order=descending \
--field-config field-path=created,order=descending
یا میتوانید این کار را از کنسول Cloud انجام دهید، با کلیک بر روی Indexes
، در ستون پیمایش در سمت چپ، و سپس ایجاد یک نمایه ترکیبی مانند شکل زیر:
روی Create
کلیک کنید. ایجاد فهرست ممکن است چند دقیقه طول بکشد.
8. کد را شبیه سازی کنید
اگر قبلاً در آزمایشگاه کد قبلی نبوده اید، کد را شبیه سازی کنید:
git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop
سپس می توانید برای شروع ساخت آزمایشگاه به دایرکتوری حاوی سرویس بروید:
cd serverless-photosharing-workshop/services/image-analysis/java
شما طرح بندی فایل زیر را برای سرویس خواهید داشت:
9. کد سرویس را کاوش کنید
شما با نگاهی به نحوه فعال شدن کتابخانه های کلاینت جاوا در pom.xml
با استفاده از یک BOM شروع می کنید:
ابتدا فایل pom.xml
را ویرایش کنید که وابستگی های تابع جاوا را فهرست می کند. برای افزودن وابستگی به Cloud Vision API Maven، کد را بهروزرسانی کنید:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cloudfunctions</groupId>
<artifactId>gcs-function</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>libraries-bom</artifactId>
<version>26.1.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.cloud.functions</groupId>
<artifactId>functions-framework-api</artifactId>
<version>1.0.4</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-firestore</artifactId>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-vision</artifactId>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-storage</artifactId>
</dependency>
</dependencies>
این عملکرد در کلاس EventController
پیاده سازی شده است. هر بار که یک تصویر جدید در سطل آپلود می شود، سرویس اعلانی برای پردازش دریافت می کند:
@RestController
public class EventController {
private static final Logger logger = Logger.getLogger(EventController.class.getName());
private static final List<String> requiredFields = Arrays.asList("ce-id", "ce-source", "ce-type", "ce-specversion");
@RequestMapping(value = "/", method = RequestMethod.POST)
public ResponseEntity<String> receiveMessage(
@RequestBody Map<String, Object> body, @RequestHeader Map<String, String> headers) throws IOException, InterruptedException, ExecutionException {
...
}
کد به اعتبار سنجی سرصفحه های Cloud Events
ادامه می دهد:
System.out.println("Header elements");
for (String field : requiredFields) {
if (headers.get(field) == null) {
String msg = String.format("Missing expected header: %s.", field);
System.out.println(msg);
return new ResponseEntity<String>(msg, HttpStatus.BAD_REQUEST);
} else {
System.out.println(field + " : " + headers.get(field));
}
}
System.out.println("Body elements");
for (String bodyField : body.keySet()) {
System.out.println(bodyField + " : " + body.get(bodyField));
}
if (headers.get("ce-subject") == null) {
String msg = "Missing expected header: ce-subject.";
System.out.println(msg);
return new ResponseEntity<String>(msg, HttpStatus.BAD_REQUEST);
}
اکنون می توان یک درخواست ایجاد کرد و کد یکی از این درخواست ها را برای ارسال به Vision API
آماده می کند:
try (ImageAnnotatorClient vision = ImageAnnotatorClient.create()) {
List<AnnotateImageRequest> requests = new ArrayList<>();
ImageSource imageSource = ImageSource.newBuilder()
.setGcsImageUri("gs://" + bucketName + "/" + fileName)
.build();
Image image = Image.newBuilder()
.setSource(imageSource)
.build();
Feature featureLabel = Feature.newBuilder()
.setType(Type.LABEL_DETECTION)
.build();
Feature featureImageProps = Feature.newBuilder()
.setType(Type.IMAGE_PROPERTIES)
.build();
Feature featureSafeSearch = Feature.newBuilder()
.setType(Type.SAFE_SEARCH_DETECTION)
.build();
AnnotateImageRequest request = AnnotateImageRequest.newBuilder()
.addFeatures(featureLabel)
.addFeatures(featureImageProps)
.addFeatures(featureSafeSearch)
.setImage(image)
.build();
requests.add(request);
ما 3 قابلیت کلیدی Vision API را درخواست می کنیم:
- تشخیص برچسب : برای درک آنچه در آن تصاویر وجود دارد
- ویژگی های تصویر : برای دادن ویژگی های جالب به تصویر (ما به رنگ غالب تصویر علاقه مند هستیم)
- جستجوی ایمن : برای اطلاع از اینکه آیا تصویر برای نمایش بی خطر است (این تصویر نباید حاوی محتوای بزرگسالان / پزشکی / نژادی / خشونت آمیز باشد)
در این مرحله، میتوانیم با Vision API تماس بگیریم:
...
logger.info("Calling the Vision API...");
BatchAnnotateImagesResponse result = vision.batchAnnotateImages(requests);
List<AnnotateImageResponse> responses = result.getResponsesList();
...
برای مرجع، در اینجا پاسخ از Vision API به نظر می رسد:
{
"faceAnnotations": [],
"landmarkAnnotations": [],
"logoAnnotations": [],
"labelAnnotations": [
{
"locations": [],
"properties": [],
"mid": "/m/01yrx",
"locale": "",
"description": "Cat",
"score": 0.9959855675697327,
"confidence": 0,
"topicality": 0.9959855675697327,
"boundingPoly": null
},
✄ - - - ✄
],
"textAnnotations": [],
"localizedObjectAnnotations": [],
"safeSearchAnnotation": {
"adult": "VERY_UNLIKELY",
"spoof": "UNLIKELY",
"medical": "VERY_UNLIKELY",
"violence": "VERY_UNLIKELY",
"racy": "VERY_UNLIKELY",
"adultConfidence": 0,
"spoofConfidence": 0,
"medicalConfidence": 0,
"violenceConfidence": 0,
"racyConfidence": 0,
"nsfwConfidence": 0
},
"imagePropertiesAnnotation": {
"dominantColors": {
"colors": [
{
"color": {
"red": 203,
"green": 201,
"blue": 201,
"alpha": null
},
"score": 0.4175916016101837,
"pixelFraction": 0.44456374645233154
},
✄ - - - ✄
]
}
},
"error": null,
"cropHintsAnnotation": {
"cropHints": [
{
"boundingPoly": {
"vertices": [
{ "x": 0, "y": 118 },
{ "x": 1177, "y": 118 },
{ "x": 1177, "y": 783 },
{ "x": 0, "y": 783 }
],
"normalizedVertices": []
},
"confidence": 0.41695669293403625,
"importanceFraction": 1
}
]
},
"fullTextAnnotation": null,
"webDetection": null,
"productSearchResults": null,
"context": null
}
اگر خطایی برگردانده نشد، میتوانیم ادامه دهیم، به همین دلیل این بلوک را داریم:
if (responses.size() == 0) {
logger.info("No response received from Vision API.");
return new ResponseEntity<String>(msg, HttpStatus.BAD_REQUEST);
}
AnnotateImageResponse response = responses.get(0);
if (response.hasError()) {
logger.info("Error: " + response.getError().getMessage());
return new ResponseEntity<String>(msg, HttpStatus.BAD_REQUEST);
}
ما میخواهیم برچسبهای چیزها، دستهها یا مضامین شناسایی شده در تصویر را دریافت کنیم:
List<String> labels = response.getLabelAnnotationsList().stream()
.map(annotation -> annotation.getDescription())
.collect(Collectors.toList());
logger.info("Annotations found:");
for (String label: labels) {
logger.info("- " + label);
}
ما علاقه مندیم که رنگ غالب تصویر را بدانیم:
String mainColor = "#FFFFFF";
ImageProperties imgProps = response.getImagePropertiesAnnotation();
if (imgProps.hasDominantColors()) {
DominantColorsAnnotation colorsAnn = imgProps.getDominantColors();
ColorInfo colorInfo = colorsAnn.getColors(0);
mainColor = rgbHex(
colorInfo.getColor().getRed(),
colorInfo.getColor().getGreen(),
colorInfo.getColor().getBlue());
logger.info("Color: " + mainColor);
}
بیایید بررسی کنیم که آیا تصویر برای نمایش امن است یا خیر:
boolean isSafe = false;
if (response.hasSafeSearchAnnotation()) {
SafeSearchAnnotation safeSearch = response.getSafeSearchAnnotation();
isSafe = Stream.of(
safeSearch.getAdult(), safeSearch.getMedical(), safeSearch.getRacy(),
safeSearch.getSpoof(), safeSearch.getViolence())
.allMatch( likelihood ->
likelihood != Likelihood.LIKELY && likelihood != Likelihood.VERY_LIKELY
);
logger.info("Safe? " + isSafe);
}
ما در حال بررسی ویژگی های بزرگسالان / جعل / پزشکی / خشونت / نژادپرستانه هستیم تا ببینیم که آیا محتمل یا بسیار محتمل هستند .
اگر نتیجه جستجوی ایمن درست باشد، میتوانیم متادیتا را در Firestore ذخیره کنیم:
// Saving result to Firestore
if (isSafe) {
FirestoreOptions firestoreOptions = FirestoreOptions.getDefaultInstance();
Firestore pictureStore = firestoreOptions.getService();
DocumentReference doc = pictureStore.collection("pictures").document(fileName);
Map<String, Object> data = new HashMap<>();
data.put("labels", labels);
data.put("color", mainColor);
data.put("created", new Date());
ApiFuture<WriteResult> writeResult = doc.set(data, SetOptions.merge());
logger.info("Picture metadata saved in Firestore at " + writeResult.get().getUpdateTime());
}
10. ساخت تصاویر برنامه با GraalVM (اختیاری)
در این مرحله اختیاری، با استفاده از GraalVM، یک JIT(JVM) based app image
و سپس یک AOT(Native) Java app image
خواهید ساخت.
برای اجرای بیلد، باید مطمئن شوید که یک JDK مناسب و سازنده تصویر native نصب و پیکربندی شده است. چندین گزینه در دسترس است.
To start
، GraalVM 22.2.x Community Edition را دانلود کنید و دستورالعمل های صفحه نصب GraalVM را دنبال کنید.
این فرآیند را می توان تا حد زیادی با کمک SDKMAN ساده کرد!
برای نصب توزیع JDK مناسب با SDKman
، با استفاده از دستور install شروع کنید:
sdk install java 22.2.r17-grl
به SDKman دستور دهید از این نسخه برای ساخت JIT و AOT استفاده کند:
sdk use java 22.2.0.r17-grl
native-image utility
برای GraalVM نصب کنید:
gu install native-image
در Cloudshell
، برای راحتی شما، می توانید GraalVM و ابزار native-image را با این دستورات ساده نصب کنید:
# install GraalVM in your home directory cd ~ # download GraalVM wget https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.2.0/graalvm-ce-java17-linux-amd64-22.2.0.tar.gz ls tar -xzvf graalvm-ce-java17-linux-amd64-22.2.0.tar.gz # configure Java 17 and GraalVM 22.2 echo Existing JVM: $JAVA_HOME cd graalvm-ce-java17-22.2.0 export JAVA_HOME=$PWD cd bin export PATH=$PWD:$PATH echo JAVA HOME: $JAVA_HOME echo PATH: $PATH # install the native image utility java -version gu install native-image cd ../..
ابتدا متغیرهای محیط پروژه GCP را تنظیم کنید:
export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
سپس می توانید برای شروع ساخت آزمایشگاه به دایرکتوری حاوی سرویس بروید:
cd serverless-photosharing-workshop/services/image-analysis/java
تصویر برنامه JIT (JVM) را بسازید:
./mvnw package -Pjvm
گزارش ساخت را در ترمینال مشاهده کنید:
... [INFO] --- spring-boot-maven-plugin:2.7.3:repackage (repackage) @ image-analysis --- [INFO] Replacing main artifact with repackaged archive [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 24.009 s [INFO] Finished at: 2022-09-26T22:17:32-04:00 [INFO] ------------------------------------------------------------------------
تصویر AOT (Native) را بسازید:.
./mvnw package -Pnative -DskipTests
گزارش ساخت را در ترمینال مشاهده کنید، از جمله گزارشهای ساخت تصویر بومی:
توجه داشته باشید که ساخت، بسته به دستگاهی که روی آن آزمایش می کنید، کمی بیشتر طول می کشد.
... [2/7] Performing analysis... [**********] (95.4s @ 3.57GB) 23,346 (94.42%) of 24,725 classes reachable 44,625 (68.71%) of 64,945 fields reachable 163,759 (70.79%) of 231,322 methods reachable 989 classes, 1,402 fields, and 11,032 methods registered for reflection 63 classes, 69 fields, and 55 methods registered for JNI access 5 native libraries: -framework CoreServices, -framework Foundation, dl, pthread, z [3/7] Building universe... (10.0s @ 5.35GB) [4/7] Parsing methods... [***] (9.7s @ 3.13GB) [5/7] Inlining methods... [***] (4.5s @ 3.29GB) [6/7] Compiling methods... [[6/7] Compiling methods... [********] (67.6s @ 5.72GB) [7/7] Creating image... (8.7s @ 4.59GB) 62.21MB (54.80%) for code area: 100,371 compilation units 50.98MB (44.91%) for image heap: 465,035 objects and 365 resources 337.09KB ( 0.29%) for other data 113.52MB in total ------------------------------------------------------------------------------------------------------------------------ Top 10 packages in code area: Top 10 object types in image heap: 2.36MB com.google.protobuf 12.70MB byte[] for code metadata 1.90MB i.g.xds.shaded.io.envoyproxy.envoy.config.core.v3 6.66MB java.lang.Class 1.73MB i.g.x.shaded.io.envoyproxy.envoy.config.route.v3 6.47MB byte[] for embedded resources 1.67MB sun.security.ssl 4.61MB byte[] for java.lang.String 1.54MB com.google.cloud.vision.v1 4.37MB java.lang.String 1.46MB com.google.firestore.v1 3.38MB byte[] for general heap data 1.37MB io.grpc.xds.shaded.io.envoyproxy.envoy.api.v2.core 1.96MB com.oracle.svm.core.hub.DynamicHubCompanion 1.32MB i.g.xds.shaded.io.envoyproxy.envoy.api.v2.route 1.80MB byte[] for reflection metadata 1.09MB java.util 911.80KB java.lang.String[] 1.08MB com.google.re2j 826.48KB c.o.svm.core.hub.DynamicHub$ReflectionMetadata 45.91MB for 772 more packages 6.45MB for 3913 more object types ------------------------------------------------------------------------------------------------------------------------ 15.1s (6.8% of total time) in 56 GCs | Peak RSS: 7.72GB | CPU load: 4.37 ------------------------------------------------------------------------------------------------------------------------ Produced artifacts: /Users/ddobrin/work/dan/serverless-photosharing-workshop/services/image-analysis/java/target/image-analysis (executable) /Users/ddobrin/work/dan/serverless-photosharing-workshop/services/image-analysis/java/target/image-analysis.build_artifacts.txt (txt) ======================================================================================================================== Finished generating 'image-analysis' in 3m 41s. [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 03:56 min [INFO] Finished at: 2022-09-26T22:22:29-04:00 [INFO] ------------------------------------------------------------------------
11. ساخت و انتشار تصاویر کانتینر
بیایید یک تصویر ظرف در دو نسخه مختلف بسازیم: یکی به عنوان یک JIT(JVM) image
و دیگری به عنوان یک AOT(Native) Java image
.
ابتدا متغیرهای محیط پروژه GCP را تنظیم کنید:
export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
تصویر JIT (JVM) را بسازید:.
./mvnw package -Pjvm-image
گزارش ساخت را در ترمینال مشاهده کنید:
[INFO] [creator] Adding layer 'process-types' [INFO] [creator] Adding label 'io.buildpacks.lifecycle.metadata' [INFO] [creator] Adding label 'io.buildpacks.build.metadata' [INFO] [creator] Adding label 'io.buildpacks.project.metadata' [INFO] [creator] Adding label 'org.opencontainers.image.title' [INFO] [creator] Adding label 'org.opencontainers.image.version' [INFO] [creator] Adding label 'org.springframework.boot.version' [INFO] [creator] Setting default process type 'web' [INFO] [creator] Saving docker.io/library/image-analysis-jvm:r17... [INFO] [creator] *** Images (03a44112456e): [INFO] [creator] docker.io/library/image-analysis-jvm:r17 [INFO] [creator] Adding cache layer 'paketo-buildpacks/syft:syft' [INFO] [creator] Adding cache layer 'cache.sbom' [INFO] [INFO] Successfully built image 'docker.io/library/image-analysis-jvm:r17' [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 02:11 min [INFO] Finished at: 2022-09-26T13:09:34-04:00 [INFO] ------------------------------------------------------------------------
تصویر AOT (Native) را بسازید:.
./mvnw package -Pnative-image
گزارش ساخت را در ترمینال مشاهده کنید، از جمله گزارشهای ساخت تصویر بومی و فشردهسازی تصویر با استفاده از UPX.
توجه داشته باشید که ساخت، بسته به دستگاهی که روی آن آزمایش می کنید، کمی بیشتر طول می کشد
... [INFO] [creator] [2/7] Performing analysis... [***********] (147.6s @ 3.10GB) [INFO] [creator] 23,362 (94.34%) of 24,763 classes reachable [INFO] [creator] 44,657 (68.67%) of 65,029 fields reachable [INFO] [creator] 163,926 (70.76%) of 231,656 methods reachable [INFO] [creator] 981 classes, 1,402 fields, and 11,026 methods registered for reflection [INFO] [creator] 63 classes, 68 fields, and 55 methods registered for JNI access [INFO] [creator] 4 native libraries: dl, pthread, rt, z [INFO] [creator] [3/7] Building universe... (21.1s @ 2.66GB) [INFO] [creator] [4/7] Parsing methods... [****] (13.7s @ 4.16GB) [INFO] [creator] [5/7] Inlining methods... [***] (9.6s @ 4.20GB) [INFO] [creator] [6/7] Compiling methods... [**********] (107.6s @ 3.36GB) [INFO] [creator] [7/7] Creating image... (14.7s @ 4.87GB) [INFO] [creator] 62.24MB (51.35%) for code area: 100,499 compilation units [INFO] [creator] 51.99MB (42.89%) for image heap: 473,948 objects and 473 resources [INFO] [creator] 6.98MB ( 5.76%) for other data [INFO] [creator] 121.21MB in total [INFO] [creator] -------------------------------------------------------------------------------- [INFO] [creator] Top 10 packages in code area: Top 10 object types in image heap: [INFO] [creator] 2.36MB com.google.protobuf 12.71MB byte[] for code metadata [INFO] [creator] 1.90MB i.g.x.s.i.e.e.config.core.v3 7.59MB byte[] for embedded resources [INFO] [creator] 1.73MB i.g.x.s.i.e.e.config.route.v3 6.66MB java.lang.Class [INFO] [creator] 1.67MB sun.security.ssl 4.62MB byte[] for java.lang.String [INFO] [creator] 1.54MB com.google.cloud.vision.v1 4.39MB java.lang.String [INFO] [creator] 1.46MB com.google.firestore.v1 3.66MB byte[] for general heap data [INFO] [creator] 1.37MB i.g.x.s.i.e.envoy.api.v2.core 1.96MB c.o.s.c.h.DynamicHubCompanion [INFO] [creator] 1.32MB i.g.x.s.i.e.e.api.v2.route 1.80MB byte[] for reflection metadata [INFO] [creator] 1.09MB java.util 910.41KB java.lang.String[] [INFO] [creator] 1.08MB com.google.re2j 826.95KB c.o.s.c.h.DynamicHu~onMetadata [INFO] [creator] 45.94MB for 776 more packages 6.69MB for 3916 more object types [INFO] [creator] -------------------------------------------------------------------------------- [INFO] [creator] 20.4s (5.6% of total time) in 81 GCs | Peak RSS: 6.75GB | CPU load: 4.53 [INFO] [creator] -------------------------------------------------------------------------------- [INFO] [creator] Produced artifacts: [INFO] [creator] /layers/paketo-buildpacks_native-image/native-image/services.ImageAnalysisApplication (executable) [INFO] [creator] /layers/paketo-buildpacks_native-image/native-image/services.ImageAnalysisApplication.build_artifacts.txt (txt) [INFO] [creator] ================================================================================ [INFO] [creator] Finished generating '/layers/paketo-buildpacks_native-image/native-image/services.ImageAnalysisApplication' in 5m 59s. [INFO] [creator] Executing upx to compress native image [INFO] [creator] Ultimate Packer for eXecutables [INFO] [creator] Copyright (C) 1996 - 2020 [INFO] [creator] UPX 3.96 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020 [INFO] [creator] [INFO] [creator] File size Ratio Format Name [INFO] [creator] -------------------- ------ ----------- ----------- 127099880 -> 32416676 25.50% linux/amd64 services.ImageAnalysisApplication ... [INFO] [creator] ===> EXPORTING ... [INFO] [creator] Adding cache layer 'paketo-buildpacks/native-image:native-image' [INFO] [creator] Adding cache layer 'cache.sbom' [INFO] [INFO] Successfully built image 'docker.io/library/image-analysis-native:r17' ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 05:28 min [INFO] Finished at: 2022-09-26T13:19:53-04:00 [INFO] ------------------------------------------------------------------------
تأیید کنید که تصاویر ساخته شده اند:
docker images | grep image-analysis
دو تصویر را تگ کنید و به GCR فشار دهید:
# JIT(JVM) image docker tag image-analysis-jvm:r17 gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-jvm:r17 docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-jvm:r17 # AOT(Native) image docker tag image-analysis-native:r17 gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-native:r17 docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-native:r17
12. در Cloud Run مستقر شوید
زمان استقرار سرویس است.
شما دو بار سرویس را مستقر خواهید کرد، یک بار با استفاده از تصویر JIT(JVM) و بار دوم با استفاده از تصویر AOT(Native). هر دو استقرار سرویس، برای مقاصد مقایسه، تصویر یکسانی را از سطل به صورت موازی پردازش خواهند کرد.
ابتدا متغیرهای محیط پروژه GCP را تنظیم کنید:
export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project) gcloud config set project ${GOOGLE_CLOUD_PROJECT} gcloud config set run/region gcloud config set run/platform managed gcloud config set eventarc/location europe-west1
تصویر JIT (JVM) را اجرا کنید و گزارش استقرار را در کنسول مشاهده کنید:
gcloud run deploy image-analysis-jvm \ --image gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-jvm:r17 \ --region europe-west1 \ --memory 2Gi --allow-unauthenticated ... Deploying container to Cloud Run service [image-analysis-jvm] in project [...] region [europe-west1] ✓ Deploying... Done. ✓ Creating Revision... ✓ Routing traffic... ✓ Setting IAM Policy... Done. Service [image-analysis-jvm] revision [image-analysis-jvm-00009-huc] has been deployed and is serving 100 percent of traffic. Service URL: https://image-analysis-jvm-...-ew.a.run.app
تصویر AOT (Native) را اجرا کنید و گزارش استقرار را در کنسول مشاهده کنید:
gcloud run deploy image-analysis-native \ --image gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-native:r17 \ --region europe-west1 \ --memory 2Gi --allow-unauthenticated ... Deploying container to Cloud Run service [image-analysis-native] in project [...] region [europe-west1] ✓ Deploying... Done. ✓ Creating Revision... ✓ Routing traffic... ✓ Setting IAM Policy... Done. Service [image-analysis-native] revision [image-analysis-native-00005-ben] has been deployed and is serving 100 percent of traffic. Service URL: https://image-analysis-native-...-ew.a.run.app
13. Eventarc Triggers را راه اندازی کنید
Eventarc یک راه حل استاندارد برای مدیریت جریان تغییرات حالت، به نام رویدادها، بین میکروسرویس های جدا شده ارائه می دهد. هنگامی که فعال میشود، Eventarc این رویدادها را از طریق اشتراکهای Pub/Sub به مقصدهای مختلف هدایت میکند (در این سند، به مقصد رویداد مراجعه کنید) در حالی که تحویل، امنیت، مجوز، قابلیت مشاهده و مدیریت خطا را برای شما مدیریت میکند.
میتوانید یک راهانداز Eventarc ایجاد کنید تا سرویس Cloud Run شما اعلانهای یک رویداد یا مجموعهای از رویدادها را دریافت کند. با تعیین فیلترها برای تریگر، میتوانید مسیریابی رویداد، از جمله منبع رویداد و سرویس Cloud Run را پیکربندی کنید.
ابتدا متغیرهای محیط پروژه GCP را تنظیم کنید:
export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project) gcloud config set project ${GOOGLE_CLOUD_PROJECT} gcloud config set run/region gcloud config set run/platform managed gcloud config set eventarc/location europe-west1
اعطای pubsub.publisher
به حساب سرویس Cloud Storage:
SERVICE_ACCOUNT="$(gsutil kms serviceaccount -p ${GOOGLE_CLOUD_PROJECT})" gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \ --member="serviceAccount:${SERVICE_ACCOUNT}" \ --role='roles/pubsub.publisher'
راهاندازهای Eventarc را برای تصاویر سرویس JVM(JIT) و AOT(Native) برای پردازش تصویر تنظیم کنید:
gcloud eventarc triggers list --location=eu gcloud eventarc triggers create image-analysis-jvm-trigger \ --destination-run-service=image-analysis-jvm \ --destination-run-region=europe-west1 \ --location=eu \ --event-filters="type=google.cloud.storage.object.v1.finalized" \ --event-filters="bucket=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}" \ --service-account=${PROJECT_NUMBER}-compute@developer.gserviceaccount.com gcloud eventarc triggers create image-analysis-native-trigger \ --destination-run-service=image-analysis-native \ --destination-run-region=europe-west1 \ --location=eu \ --event-filters="type=google.cloud.storage.object.v1.finalized" \ --event-filters="bucket=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}" \ --service-account=${PROJECT_NUMBER}-compute@developer.gserviceaccount.com
توجه داشته باشید که دو محرک ایجاد شده اند:
gcloud eventarc triggers list --location=eu
14. نسخه های سرویس تست
پس از اجرای موفقیت آمیز سرویس، تصویری را در Cloud Storage پست میکنید، ببینید آیا خدمات ما فراخوانی شدهاند، Vision API چه چیزی را برمیگرداند، و آیا ابرداده در Firestore ذخیره میشود.
به Cloud Storage
برگردید و روی سطلی که در ابتدای آزمایشگاه ایجاد کردیم کلیک کنید:
پس از ورود به صفحه جزئیات سطل، روی دکمه Upload files
کلیک کنید تا یک عکس آپلود شود.
به عنوان مثال، یک تصویر GeekHour.jpeg
به همراه پایگاه کد شما در زیر /services/image-analysis/java
ارائه می شود. یک تصویر را انتخاب کنید و Open button
فشار دهید:
اکنون میتوانید اجرای سرویس را بررسی کنید، با image-analysis-jvm
شروع و سپس image-analysis-native
.
از منوی "همبرگر" (☰)، به سرویس Cloud Run > image-analysis-jvm
بروید.
روی Logs کلیک کنید و خروجی را مشاهده کنید:
و در واقع، در لیست گزارشها، میتوانم ببینم که سرویس JIT(JVM) image-analysis-jvm
فراخوانی شده است.
گزارش ها شروع و پایان اجرای سرویس را نشان می دهد. و در این بین، ما میتوانیم گزارشهایی را که در تابع خود قرار میدهیم با دستورات log در سطح INFO ببینیم. می بینیم:
- جزئیات رویدادی که عملکرد ما را تحریک می کند،
- نتایج خام از فراخوانی Vision API،
- برچسب هایی که در تصویری که آپلود کردیم یافت شد،
- اطلاعات رنگ های غالب،
- اینکه آیا تصویر برای نشان دادن بی خطر است،
- و در نهایت آن ابرداده های مربوط به تصویر در Firestore ذخیره شده است.
شما این فرآیند را برای سرویس image-analysis-native
تکرار خواهید کرد.
از منوی "همبرگر" (☰)، به Cloud Run > image-analysis-native
سرویس بروید.
روی Logs کلیک کنید و خروجی را مشاهده کنید:
اکنون می خواهید مشاهده کنید که آیا فراداده تصویر در Fiorestore ذخیره شده است یا خیر.
دوباره از منوی "همبرگر" (☰)، به بخش Firestore
بروید. در زیر بخش Data
(به طور پیش فرض نشان داده شده است)، باید مجموعه pictures
را با یک سند جدید اضافه کنید، مطابق با تصویری که اخیراً آپلود کرده اید:
15. تمیز کردن (اختیاری)
اگر قصد ندارید با دیگر آزمایشگاههای این سری ادامه دهید، میتوانید منابع را پاکسازی کنید تا در هزینهها صرفهجویی کنید و در کل شهروند ابری خوبی باشید. می توانید منابع را به صورت جداگانه به صورت زیر پاک کنید.
سطل را حذف کنید:
gsutil rb gs://${BUCKET_PICTURES}
حذف تابع:
gcloud functions delete picture-uploaded --region europe-west1 -q
با انتخاب حذف مجموعه از مجموعه، مجموعه Firestore را حذف کنید:
یا می توانید کل پروژه را حذف کنید:
gcloud projects delete ${GOOGLE_CLOUD_PROJECT}
16. تبریک می گویم!
تبریک می گویم! شما اولین سرویس کلیدی پروژه را با موفقیت اجرا کردید!
آنچه را پوشش داده ایم
- فضای ذخیره سازی ابری
- Cloud Run
- Cloud Vision API
- Cloud Firestore
- تصاویر بومی جاوا