gcp-cloud-run

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GCP Cloud Run

GCP Cloud Run

Patterns

模式

Cloud Run Service Pattern

Cloud Run服务模式

Containerized web service on Cloud Run
When to use: ['Web applications and APIs', 'Need any runtime or library', 'Complex services with multiple endpoints', 'Stateless containerized workloads']
javascript
```dockerfile
Cloud Run上的容器化Web服务
适用场景:['Web应用与API', '需要任意运行时或库', '包含多个端点的复杂服务', '无状态容器化工作负载']
dockerfile
undefined

Dockerfile - Multi-stage build for smaller image

Dockerfile - Multi-stage build for smaller image

FROM node:20-slim AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --only=production
FROM node:20-slim WORKDIR /app
FROM node:20-slim AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --only=production
FROM node:20-slim WORKDIR /app

Copy only production dependencies

Copy only production dependencies

COPY --from=builder /app/node_modules ./node_modules COPY src ./src COPY package.json ./
COPY --from=builder /app/node_modules ./node_modules COPY src ./src COPY package.json ./

Cloud Run uses PORT env variable

Cloud Run uses PORT env variable

ENV PORT=8080 EXPOSE 8080
ENV PORT=8080 EXPOSE 8080

Run as non-root user

Run as non-root user

USER node
CMD ["node", "src/index.js"]

```javascript
// src/index.js
const express = require('express');
const app = express();

app.use(express.json());

// Health check endpoint
app.get('/health', (req, res) => {
  res.status(200).send('OK');
});

// API routes
app.get('/api/items/:id', async (req, res) => {
  try {
    const item = await getItem(req.params.id);
    res.json(item);
  } catch (error) {
    console.error('Error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// Graceful shutdown
process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down gracefully');
  server.close(() => {
    console.log('Server closed');
    process.exit(0);
  });
});

const PORT = process.env.PORT || 8080;
const server = app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`);
});
yaml
undefined
USER node
CMD ["node", "src/index.js"]

```javascript
// src/index.js
const express = require('express');
const app = express();

app.use(express.json());

// Health check endpoint
app.get('/health', (req, res) => {
  res.status(200).send('OK');
});

// API routes
app.get('/api/items/:id', async (req, res) => {
  try {
    const item = await getItem(req.params.id);
    res.json(item);
  } catch (error) {
    console.error('Error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// Graceful shutdown
process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down gracefully');
  server.close(() => {
    console.log('Server closed');
    process.exit(0);
  });
});

const PORT = process.env.PORT || 8080;
const server = app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`);
});
yaml
undefined

cloudbuild.yaml

cloudbuild.yaml

steps:

Build the container image

  • name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', 'gcr.io/$PROJECT_ID/my-service:$COMMIT_SHA', '.']

Push the container image

  • name: 'gcr.io/cloud-builders/docker' args: ['push', 'gcr.io/$PROJECT_ID/my-service:$COMMIT_SHA']

Deploy to Cloud Run

  • name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' entrypoint: gcloud args:
    • 'run'
    • 'deploy'
    • 'my-service'
    • '--image=gcr.io/$PROJECT_ID/my-service:$COMMIT_SHA'
    • '--region=us-central1'
    • '--platform=managed'
    • '--allow-unauthenticated'
    • '--memory=512Mi'
    • '--cpu=1'
    • '--min-instances=1'
    • '--max-instances=100'
undefined
steps:

Build the container image

  • name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', 'gcr.io/$PROJECT_ID/my-service:$COMMIT_SHA', '.']

Push the container image

  • name: 'gcr.io/cloud-builders/docker' args: ['push', 'gcr.io/$PROJECT_ID/my-service:$COMMIT_SHA']

Deploy to Cloud Run

  • name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' entrypoint: gcloud args:
    • 'run'
    • 'deploy'
    • 'my-service'
    • '--image=gcr.io/$PROJECT_ID/my-service:$COMMIT_SHA'
    • '--region=us-central1'
    • '--platform=managed'
    • '--allow-unauthenticated'
    • '--memory=512Mi'
    • '--cpu=1'
    • '--min-instances=1'
    • '--max-instances=100'
undefined

Cloud Run Functions Pattern

Cloud Run Functions模式

Event-driven functions (formerly Cloud Functions)
When to use: ['Simple event handlers', 'Pub/Sub message processing', 'Cloud Storage triggers', 'HTTP webhooks']
javascript
```javascript
// HTTP Function
// index.js
const functions = require('@google-cloud/functions-framework');

functions.http('helloHttp', (req, res) => {
  const name = req.query.name || req.body.name || 'World';
  res.send(`Hello, ${name}!`);
});
javascript
// Pub/Sub Function
const functions = require('@google-cloud/functions-framework');

functions.cloudEvent('processPubSub', (cloudEvent) => {
  // Decode Pub/Sub message
  const message = cloudEvent.data.message;
  const data = message.data
    ? JSON.parse(Buffer.from(message.data, 'base64').toString())
    : {};

  console.log('Received message:', data);

  // Process message
  processMessage(data);
});
javascript
// Cloud Storage Function
const functions = require('@google-cloud/functions-framework');

functions.cloudEvent('processStorageEvent', async (cloudEvent) => {
  const file = cloudEvent.data;

  console.log(`Event: ${cloudEvent.type}`);
  console.log(`Bucket: ${file.bucket}`);
  console.log(`File: ${file.name}`);

  if (cloudEvent.type === 'google.cloud.storage.object.v1.finalized') {
    await processUploadedFile(file.bucket, file.name);
  }
});
bash
undefined
事件驱动函数(原Cloud Functions)
适用场景:['简单事件处理器', 'Pub/Sub消息处理', 'Cloud Storage触发器', 'HTTP Webhook']
javascript
// HTTP Function
// index.js
const functions = require('@google-cloud/functions-framework');

functions.http('helloHttp', (req, res) => {
  const name = req.query.name || req.body.name || 'World';
  res.send(`Hello, ${name}!`);
});
javascript
// Pub/Sub Function
const functions = require('@google-cloud/functions-framework');

functions.cloudEvent('processPubSub', (cloudEvent) => {
  // Decode Pub/Sub message
  const message = cloudEvent.data.message;
  const data = message.data
    ? JSON.parse(Buffer.from(message.data, 'base64').toString())
    : {};

  console.log('Received message:', data);

  // Process message
  processMessage(data);
});
javascript
// Cloud Storage Function
const functions = require('@google-cloud/functions-framework');

functions.cloudEvent('processStorageEvent', async (cloudEvent) => {
  const file = cloudEvent.data;

  console.log(`Event: ${cloudEvent.type}`);
  console.log(`Bucket: ${file.bucket}`);
  console.log(`File: ${file.name}`);

  if (cloudEvent.type === 'google.cloud.storage.object.v1.finalized') {
    await processUploadedFile(file.bucket, file.name);
  }
});
bash
undefined

Deploy HTTP function

Deploy HTTP function

gcloud functions deploy hello-http
--gen2
--runtime nodejs20
--trigger-http
--allow-unauthenticated
--region us-central1
gcloud functions deploy hello-http
--gen2
--runtime nodejs20
--trigger-http
--allow-unauthenticated
--region us-central1

Deploy Pub/Sub function

Deploy Pub/Sub function

gcloud functions deploy process-messages
--gen2
--runtime nodejs20
--trigger-topic my-topic
--region us-central1
gcloud functions deploy process-messages
--gen2
--runtime nodejs20
--trigger-topic my-topic
--region us-central1

Deploy Cloud Storage function

Deploy Cloud Storage function

gcloud functions deploy process-uploads
--gen2
--runtime nodejs20
--trigger-event-filters="type=google.cloud.storage.object.v1.finalized"
--trigger-event-filters="bucket=my-bucket"
--region us-central1
undefined
gcloud functions deploy process-uploads
--gen2
--runtime nodejs20
--trigger-event-filters="type=google.cloud.storage.object.v1.finalized"
--trigger-event-filters="bucket=my-bucket"
--region us-central1
undefined

Cold Start Optimization Pattern

冷启动优化模式

Minimize cold start latency for Cloud Run
When to use: ['Latency-sensitive applications', 'User-facing APIs', 'High-traffic services']
javascript
undefined
最小化Cloud Run的冷启动延迟
适用场景:['对延迟敏感的应用', '面向用户的API', '高流量服务']

1. Enable Startup CPU Boost

1. 启用启动CPU加速

bash
gcloud run deploy my-service \
  --cpu-boost \
  --region us-central1
bash
gcloud run deploy my-service \
  --cpu-boost \
  --region us-central1

2. Set Minimum Instances

2. 设置最小实例数

bash
gcloud run deploy my-service \
  --min-instances 1 \
  --region us-central1
bash
gcloud run deploy my-service \
  --min-instances 1 \
  --region us-central1

3. Optimize Container Image

3. 优化容器镜像

dockerfile
undefined
dockerfile
undefined

Use distroless for minimal image

Use distroless for minimal image

FROM node:20-slim AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --only=production
FROM gcr.io/distroless/nodejs20-debian12 WORKDIR /app COPY --from=builder /app/node_modules ./node_modules COPY src ./src CMD ["src/index.js"]
undefined
FROM node:20-slim AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --only=production
FROM gcr.io/distroless/nodejs20-debian12 WORKDIR /app COPY --from=builder /app/node_modules ./node_modules COPY src ./src CMD ["src/index.js"]
undefined

4. Lazy Initialize Heavy Dependencies

4. 延迟初始化重型依赖

javascript
// Lazy load heavy libraries
let bigQueryClient = null;

function getBigQueryClient() {
  if (!bigQueryClient) {
    const { BigQuery } = require('@google-cloud/bigquery');
    bigQueryClient = new BigQuery();
  }
  return bigQueryClient;
}

// Only initialize when needed
app.get('/api/analytics', async (req, res) => {
  const client = getBigQueryClient();
  const results = await client.query({...});
  res.json(results);
});
javascript
// Lazy load heavy libraries
let bigQueryClient = null;

function getBigQueryClient() {
  if (!bigQueryClient) {
    const { BigQuery } = require('@google-cloud/bigquery');
    bigQueryClient = new BigQuery();
  }
  return bigQueryClient;
}

// Only initialize when needed
app.get('/api/analytics', async (req, res) => {
  const client = getBigQueryClient();
  const results = await client.query({...});
  res.json(results);
});

5. Increase Memory (More CPU)

5. 增加内存(获得更多CPU)

bash
undefined
bash
undefined

Higher memory = more CPU during startup

Higher memory = more CPU during startup

gcloud run deploy my-service
--memory 1Gi
--cpu 2
--region us-central1
undefined
gcloud run deploy my-service
--memory 1Gi
--cpu 2
--region us-central1
undefined

Anti-Patterns

反模式

❌ CPU-Intensive Work Without Concurrency=1

❌ 未设置Concurrency=1的CPU密集型工作负载

Why bad: CPU is shared across concurrent requests. CPU-bound work will starve other requests, causing timeouts.
问题原因:CPU会在并发请求之间共享。CPU密集型工作负载会导致其他请求资源不足,从而引发超时。

❌ Writing Large Files to /tmp

❌ 向/tmp写入大文件

Why bad: /tmp is an in-memory filesystem. Large files consume your memory allocation and can cause OOM errors.
问题原因:/tmp是内存文件系统。大文件会消耗内存配额,可能导致OOM(内存不足)错误。

❌ Long-Running Background Tasks

❌ 长时间运行的后台任务

Why bad: Cloud Run throttles CPU to near-zero when not handling requests. Background tasks will be extremely slow or stall.
问题原因:当Cloud Run未处理请求时,CPU会被限制到接近零。后台任务会变得极慢或停滞。

⚠️ Sharp Edges

⚠️ 注意事项

IssueSeveritySolution
Issuehigh## Calculate memory including /tmp usage
Issuehigh## Set appropriate concurrency
Issuehigh## Enable CPU always allocated
Issuemedium## Configure connection pool with keep-alive
Issuehigh## Enable startup CPU boost
Issuemedium## Explicitly set execution environment
Issuemedium## Set consistent timeouts
问题严重程度解决方案
问题## 计算包含/tmp使用量的内存
问题## 设置合适的并发数
问题## 启用始终分配CPU
问题## 配置带保持连接的连接池
问题## 启用启动CPU加速
问题## 显式设置执行环境
问题## 设置一致的超时时间