SDK kullanarak dış uygulamayı Lakebase'e bağlama

Bu kılavuzda, OAuth belirteci döndürmeli standart Postgres sürücülerini (psycopg, pgx, JDBC) kullanarak dış uygulamaların Lakebase Otomatik Ölçeklendirme'ye nasıl bağlanıldığı gösterilmektedir. Azure Databricks SDK'sını bir hizmet sorumlusu ve her yeni bağlantıyı açarken çağıran generate_database_credential() bir bağlantı havuzuyla kullanırsınız, böylece her bağlandığınızda yeni bir belirteç (60 dakikalık yaşam süresi) elde edersiniz. Python, Java ve Go için örnekler sağlanır. Otomatik kimlik bilgileri yönetimiyle daha kolay kurulum için bunun yerine Azure Databricks Uygulamaları'nı göz önünde bulundurun.

Oluşturacakların: Harici bir uygulamadan Lakebase Otomatik Ölçeklendirme'ye bağlanmak için OAuth belirteci döngüsünü kullanan bir bağlantı deseni ve ardından bağlantının çalıştığını doğrulamak.

Databricks SDK'sı (Python v0.89.0+, Java v0.73.0+ veya Go v0.109.0+) gerekir. Aşağıdaki adımları sırayla tamamlayın:

:::tip Diğer Diller Databricks SDK desteği olmayan diller için (Node.js, Ruby, PHP, Elixir, Rust vb.), bkz. API kullanarak dış uygulamayı Lakebase'e bağlama. :::

Nasıl çalışır?

Databricks SDK'sı, çalışma alanı belirteci yönetimini otomatik olarak işleyerek OAuth kimlik doğrulamasını basitleştirir:

SDK OAuth akışı

Uygulamanız uç nokta parametresiyle çağırır generate_database_credential() . SDK, çalışma alanı OAuth belirtecini dahili olarak alır (kod gerekmez), Lakebase API'sinden veritabanı kimlik bilgilerini ister ve uygulamanıza döndürür. Ardından Postgres'e bağlanırken parola olarak bu kimlik bilgilerini kullanırsınız.

Çalışma alanı OAuth belirtecinin ve veritabanı kimlik bilgilerinin süresi 60 dakika sonra dolar. Bağlantı havuzları, yeni bağlantılar oluştururken generate_database_credential() çağrısı yaparak otomatik yenilemeyi işler.

1. OAuth gizli anahtarıyla hizmet sorumlusu oluşturma

Azure Databricks hizmet sorumlusunu bir OAuth gizli anahtarı ile oluşturun. Tüm ayrıntılar Hizmet sorumlusu erişimini yetkilendirme bölümündedir. Dış uygulama oluşturmak için şunları aklınızda bulundurun:

  • Sır süresini tercih ettiğiniz şekilde 730 güne kadar ayarlayın. Bu, veritabanı kimlik bilgilerini döngüsel yenileme yoluyla oluşturmak için kullanılan gizli bilgiyi ne sıklıkta yenilemeniz gerektiğini tanımlar.
  • Hizmet sorumlusu için "Çalışma alanı erişimini" etkinleştirin (Ayarlar → Kimlik ve erişim → Hizmet sorumluları → {name} → Yapılandırmalar sekmesine erişin). Yeni veritabanı kimlik bilgileri oluşturmak için gereklidir.
  • İstemci kimliğini (UUID) not edin. Uygulama kurulumunuzda ve PGUSER ile uygun Postgres rolünü oluştururken bunu kullanırsınız.

2. Hizmet sorumlusu için Postgres rolü oluşturma

Hizmet sorumlusu için bir OAuth rolü oluşturun. Bunu Lakebase kullanıcı arabiriminde ( Rol ekle iletişim kutusunun OAuth sekmesini kullanarak) veya 1. adımdaki istemci kimliğini kullanarak Lakebase SQL Düzenleyicisi'nde (görünen ad değil; rol adı büyük/küçük harfe duyarlıdır) yapabilirsiniz:

-- Enable the auth extension (if not already enabled)
CREATE EXTENSION IF NOT EXISTS databricks_auth;

-- Create OAuth role using the service principal client ID
SELECT databricks_create_role('{client-id}', 'SERVICE_PRINCIPAL');

-- Grant database permissions
GRANT CONNECT ON DATABASE databricks_postgres TO "{client-id}";
GRANT USAGE ON SCHEMA public TO "{client-id}";
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO "{client-id}";
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "{client-id}";

{client-id} değerini hizmet sorumlusu istemci kimliğinizle değiştirin. Bkz. OAuth rolleri oluşturma.

3. Bağlantı ayrıntılarını alma

Lakebase Konsolu'ndaki projenizden Bağlan'a tıklayın, dal ve uç nokta seçin ve konak, veritabanı (genellikle databricks_postgres) ve uç nokta adı (biçim: projects/<project-id>/branches/<branch-id>/endpoints/<endpoint-id>) değerlerini not edin.

Veya CLI'yi kullanın:

databricks postgres list-endpoints projects/<project-id>/branches/<branch-id>

Ayrıntılar için bkz . Bağlantı dizeleri .

4. Ortam değişkenlerini ayarlama

Uygulamanızı çalıştırmadan önce şu ortam değişkenlerini ayarlayın:

# Databricks workspace authentication
export DATABRICKS_HOST="https://your-workspace.databricks.com"
export DATABRICKS_CLIENT_ID="<service-principal-client-id>"
export DATABRICKS_CLIENT_SECRET="<your-oauth-secret>"

# Lakebase connection details (from step 3)
export ENDPOINT_NAME="projects/<project-id>/branches/<branch-id>/endpoints/<endpoint-id>"
export PGHOST="<endpoint-id>.database.<region>.cloud.databricks.com"
export PGDATABASE="databricks_postgres"
export PGUSER="<service-principal-client-id>"   # Same UUID as step 1
export PGPORT="5432"
export PGSSLMODE="require"   # Python only

5. Bağlantı kodu ekleme

Piton

Bu örnek, havuz her yeni bağlantıyı oluşturduğunda yeni bir belirteç oluşturan özel bir bağlantı sınıfıyla psycopg3 kullanır.

import os
from databricks.sdk import WorkspaceClient
import psycopg
from psycopg_pool import ConnectionPool

# Initialize Databricks SDK
workspace_client = None

def _get_workspace_client():
    """Get or create the workspace client for OAuth."""
    global workspace_client
    if workspace_client is None:
        workspace_client = WorkspaceClient(
            host=os.environ["DATABRICKS_HOST"],
            client_id=os.environ["DATABRICKS_CLIENT_ID"],
            client_secret=os.environ["DATABRICKS_CLIENT_SECRET"],
        )
    return workspace_client

def _get_endpoint_name():
    """Get endpoint name from environment."""
    name = os.environ.get("ENDPOINT_NAME")
    if not name:
        raise ValueError(
            "ENDPOINT_NAME must be set (format: projects/<id>/branches/<id>/endpoints/<id>)"
        )
    return name

class OAuthConnection(psycopg.Connection):
    """Custom connection class that generates a fresh OAuth token per connection."""

    @classmethod
    def connect(cls, conninfo="", **kwargs):
        endpoint_name = _get_endpoint_name()
        client = _get_workspace_client()
        # Generate database credential (tokens are workspace-scoped)
        credential = client.postgres.generate_database_credential(
            endpoint=endpoint_name
        )
        kwargs["password"] = credential.token
        return super().connect(conninfo, **kwargs)

# Create connection pool with OAuth token rotation
def get_connection_pool():
    """Get or create the connection pool."""
    database = os.environ["PGDATABASE"]
    user = os.environ["PGUSER"]
    host = os.environ["PGHOST"]
    port = os.environ.get("PGPORT", "5432")
    sslmode = os.environ.get("PGSSLMODE", "require")

    conninfo = f"dbname={database} user={user} host={host} port={port} sslmode={sslmode}"

    return ConnectionPool(
        conninfo=conninfo,
        connection_class=OAuthConnection,
        min_size=1,
        max_size=10,
        open=True,
    )

# Use the pool in your application
pool = get_connection_pool()
with pool.connection() as conn:
    with conn.cursor() as cur:
        cur.execute("SELECT current_user, current_database()")
        print(cur.fetchone())

Bağımlılıklar:databricks-sdk>=0.89.0, psycopg[binary,pool]>=3.1.0

Başlayın

Bu örnekte, her yeni bağlantı için yeni bir belirteç oluşturan bir BeforeConnect geri çağırması ile pgxpool kullanılır.

package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/databricks/databricks-sdk-go"
	"github.com/databricks/databricks-sdk-go/service/postgres"
	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/pgxpool"
)

func createConnectionPool(ctx context.Context) (*pgxpool.Pool, error) {
	// Initialize Databricks workspace client
	w, err := databricks.NewWorkspaceClient(&databricks.Config{
		Host:         os.Getenv("DATABRICKS_HOST"),
		ClientID:     os.Getenv("DATABRICKS_CLIENT_ID"),
		ClientSecret: os.Getenv("DATABRICKS_CLIENT_SECRET"),
	})
	if err != nil {
		return nil, err
	}

	// Build connection string
	connStr := fmt.Sprintf("host=%s port=%s dbname=%s user=%s sslmode=require",
		os.Getenv("PGHOST"),
		os.Getenv("PGPORT"),
		os.Getenv("PGDATABASE"),
		os.Getenv("PGUSER"))

	config, err := pgxpool.ParseConfig(connStr)
	if err != nil {
		return nil, err
	}

	// Configure pool
	config.MaxConns = 10
	config.MinConns = 1
	config.MaxConnLifetime = 45 * time.Minute
	config.MaxConnIdleTime = 15 * time.Minute

	// Generate fresh token for each new connection
	config.BeforeConnect = func(ctx context.Context, connConfig *pgx.ConnConfig) error {
		credential, err := w.Postgres.GenerateDatabaseCredential(ctx,
			postgres.GenerateDatabaseCredentialRequest{
				Endpoint: os.Getenv("ENDPOINT_NAME"),
			})
		if err != nil {
			return err
		}
		connConfig.Password = credential.Token
		return nil
	}

	return pgxpool.NewWithConfig(ctx, config)
}

func main() {
	ctx := context.Background()
	pool, err := createConnectionPool(ctx)
	if err != nil {
		log.Fatal(err)
	}
	defer pool.Close()

	var user, database string
	err = pool.QueryRow(ctx, "SELECT current_user, current_database()").Scan(&user, &database)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Connected as: %s to database: %s\n", user, database)
}

Bağımlılık: Go v0.109.0+ için Databricks SDK'sı (github.com/databricks/databricks-sdk-go), pgx sürücüsü (github.com/jackc/pgx/v5)

Not:BeforeConnect Geri çağırım, her yeni bağlantı için yeni OAuth belirteçleri sağlar ve uzun süre çalışan uygulamalar için belirteçlerin otomatik olarak döndürülmesini işler.

Java

Bu örnekte HikariCP ile JDBC ve havuz her yeni bağlantıyı oluşturduğunda yeni bir belirteç oluşturan özel bir DataSource kullanılır.

import java.sql.*;
import javax.sql.DataSource;
import com.databricks.sdk.WorkspaceClient;
import com.databricks.sdk.core.DatabricksConfig;
import com.databricks.sdk.service.postgres.*;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

public class LakebaseConnection {

    private static WorkspaceClient workspaceClient() {
        String host = System.getenv("DATABRICKS_HOST");
        String clientId = System.getenv("DATABRICKS_CLIENT_ID");
        String clientSecret = System.getenv("DATABRICKS_CLIENT_SECRET");

        return new WorkspaceClient(new DatabricksConfig()
            .setHost(host)
            .setClientId(clientId)
            .setClientSecret(clientSecret));
    }

    private static DataSource createDataSource() {
        WorkspaceClient w = workspaceClient();
        String endpointName = System.getenv("ENDPOINT_NAME");
        String host = System.getenv("PGHOST");
        String database = System.getenv("PGDATABASE");
        String user = System.getenv("PGUSER");
        String port = System.getenv().getOrDefault("PGPORT", "5432");

        String jdbcUrl = "jdbc:postgresql://" + host + ":" + port +
                         "/" + database + "?sslmode=require";

        // DataSource that returns a new connection with a fresh token (tokens are workspace-scoped)
        DataSource tokenDataSource = new DataSource() {
            @Override
            public Connection getConnection() throws SQLException {
                DatabaseCredential cred = w.postgres().generateDatabaseCredential(
                    new GenerateDatabaseCredentialRequest().setEndpoint(endpointName)
                );
                return DriverManager.getConnection(jdbcUrl, user, cred.getToken());
            }

            @Override
            public Connection getConnection(String u, String p) {
                throw new UnsupportedOperationException();
            }
            // ... other DataSource methods (getLogWriter, etc.)
        };

        // Wrap in HikariCP for connection pooling
        HikariConfig config = new HikariConfig();
        config.setDataSource(tokenDataSource);
        config.setMaximumPoolSize(10);
        config.setMinimumIdle(1);
        // Recycle connections before 60-min token expiry
        config.setMaxLifetime(45 * 60 * 1000L);

        return new HikariDataSource(config);
    }

    public static void main(String[] args) throws SQLException {
        DataSource pool = createDataSource();

        try (Connection conn = pool.getConnection();
             Statement st = conn.createStatement();
             ResultSet rs = st.executeQuery("SELECT current_user, current_database()")) {
            if (rs.next()) {
                System.out.println("User: " + rs.getString(1));
                System.out.println("Database: " + rs.getString(2));
            }
        }
    }
}

Bağımlılık: Java v0.73.0+ için Databricks SDK'sı (com.databricks:databricks-sdk-java), PostgreSQL JDBC sürücüsü (org.postgresql:postgresql), HikariCP (com.zaxxer:HikariCP)

6. Bağlantıyı çalıştırın ve doğrulayın

Piton

Bağımlılıkları yükleme:

pip install databricks-sdk psycopg[binary,pool]

Çalıştır:

# Save all the code from step 5 (above) as db.py, then run:
from db import get_connection_pool

pool = get_connection_pool()
with pool.connection() as conn:
    with conn.cursor() as cur:
        cur.execute("SELECT current_user, current_database()")
        print(cur.fetchone())

Beklenen çıkış:

('c00f575e-d706-4f6b-b62c-e7a14850571b', 'databricks_postgres')

current_user 1. adımdaki hizmet sorumlusu istemci kimliğiniz ile eşleşiyorsa, OAuth belirteci döndürme işlevi çalışıyor.

Java

Not: Bu, yukarıdaki Java örneğinden bağımlılıkları içeren bir Maven projeniz pom.xmlolduğunu varsayar.

Bağımlılıkları yükleme:

mvn install

Çalıştır:

mvn exec:java -Dexec.mainClass="com.example.LakebaseConnection"

Beklenen çıkış:

User: c00f575e-d706-4f6b-b62c-e7a14850571b
Database: databricks_postgres

Kullanıcı, 1. adımdaki hizmet sorumlusu istemci kimliğiniz ile eşleşiyorsa, OAuth belirteci döndürme işlevi çalışıyor.

Başlayın

Bağımlılıkları yükleme:

go mod init myapp
go get github.com/databricks/databricks-sdk-go
go get github.com/jackc/pgx/v5

Çalıştır:

go run main.go

Beklenen çıkış:

Connected as: c00f575e-d706-4f6b-b62c-e7a14850571b to database: databricks_postgres

Kullanıcı, 1. adımdaki hizmet sorumlusu istemci kimliğiniz ile eşleşiyorsa, OAuth belirteci döndürme işlevi çalışıyor.

Not: Lakebase Otomatik Ölçeklendirme işlemi sıfırdan başlattığından, boşta kalmadan sonraki ilk bağlantı daha uzun sürebilir.

Sorun giderme

Hata Düzelt
"API, çalışma alanı erişimi yetkilendirmesi olmayan kullanıcılar için devre dışı bırakıldı" Hizmet sorumlusu için "Çalışma alanı erişimini" etkinleştirin (1. adım).
"Rol mevcut değil" veya kimlik doğrulama başarısız oluyor Kullanıcı arabirimini değil SQL (2. adım) aracılığıyla OAuth rolünü oluşturun.
"Bağlantı reddedildi" veya "Uç nokta bulunamadı" ENDPOINT_NAME formatını projects/<id>/branches/<id>/endpoints/<id> kullanın; uç nokta kimliği host'tadır.
"Geçersiz kullanıcı" veya "Kullanıcı bulunamadı" PGUSER değerini görüntüleme adına değil, hizmet sorumlusu istemci kimliğine (UUID) ayarlayın.