Sunucusuz mimari, modern web uygulamaları için standart haline geldi, ancak geliştiriciler düzenli olarak bir sorunla karşılaşıyor: Lambda işlevlerinden veya Edge Functions'tan gelen tüm istekler, bulut sağlayıcılarının veri merkezlerinden gelen IP adresleriyle geliyor. Bu, dış API'lere erişimde, veri ayrıştırmada veya görev otomasyonunda engellere yol açıyor. Bu kılavuzda, kısıtlamaları, oran limitlerini ve coğrafi engelleri aşmak için sunucusuz işlevlere proxy entegrasyonunu inceleyeceğiz.
Neden sunucusuz işlevlere proxy gerekir
Sunucusuz platformlar (AWS Lambda, Google Cloud Functions, Vercel, Cloudflare Workers) kodu bulut altyapısında çalıştırır ve veri merkezi IP adreslerini kullanır. Bu, geliştiriciler için birkaç kritik sorun yaratır:
Sorun 1: Veri merkezi IP'lerine göre engellemeler. Birçok hizmet, AWS, Google Cloud veya Azure'dan gelen bilinen IP adreslerinden gelen istekleri otomatik olarak engeller. Örneğin, e-ticaret sitelerinin (Amazon, eBay, Wildberries) veya sosyal ağların (Instagram API, TikTok API) ayrıştırılması sırasında, Lambda işlevleriniz ilk istekte HTTP 403 veya captcha alabilir. Bot koruma sistemleri (Cloudflare, Akamai, DataDome) bulut veri merkezlerinden gelen trafiği anında tanır.
Sorun 2: IP düzeyinde oran sınırlaması. Eğer binlerce eşzamanlı çağrıyla bir sunucusuz uygulama dağıtıyorsanız, tüm istekler bir veya birkaç AWS IP adresinden gelebilir. Dış API'ler hızla limitlere ulaşır (örneğin, GitHub API — bir IP'den saatte 60 istek, Google Maps API — saniyede 100 istek). Genişletilmiş API planınız olsa bile, IP sınırlaması yine de devreye girecektir.
Sorun 3: Coğrafi engellemeler. us-east-1 bölgesindeki sunucusuz işlevler, yalnızca Rusya, Avrupa veya Asya'dan erişilebilen içeriğe erişemez. Bu, bölgesel pazar yerlerinin (Ozon, Yandex.Market) ayrıştırılması, farklı ülkelerden reklamların kontrolü veya web sitelerinin yerelleştirilmesinin test edilmesi sırasında kritik öneme sahiptir.
Sorun 4: Diğer kullanıcılarla paylaşılan IP. Sunucusuz ortamda işlevleriniz, bulut sağlayıcısının diğer müşterileri tarafından daha önce kullanılmış bir IP adresi alabilir. Eğer biri daha önce bu IP'yi kötüye kullandıysa (spam, DDoS, ayrıştırma), bu IP kara listelere alınabilir. Suçsuz bir şekilde engellenebilirsiniz.
Tüm bu sorunların çözümü, proxy sunucularının entegrasyonudur. Proxy'ler, sunucusuz işlevlerinizin normal kullanıcılar gibi görünen yerleşik veya mobil IP adresleri üzerinden istek göndermesini sağlar. Bu, engelleri kaldırır, oran limitlerini aşar ve coğrafi olarak engellenmiş içeriğe erişim sağlar.
Sunucusuz için hangi proxy türleri uygundur
Proxy türünün seçimi, sunucusuz uygulamanızın görevine bağlıdır. Üç ana seçeneği ve bunların kullanım senaryolarını inceleyelim:
| Proxy Türü | Hız | Anonimlik | Kullanım Senaryoları |
|---|---|---|---|
| Veri Merkezi Proxy'leri | Çok yüksek (10-50 ms) | Düşük | Sert kısıtlamalar olmadan API'ye erişim, hizmetlerin kullanılabilirliğini kontrol etme, uptime izleme |
| Yerleşik Proxy'ler | Orta (100-500 ms) | Yüksek | E-ticaret ayrıştırması, sosyal medya ile çalışma, Cloudflare'ı aşma, coğrafi olarak engellenmiş içeriğe erişim |
| Mobil Proxy'ler | Orta (150-600 ms) | Çok yüksek | Mobil API'lerle çalışma (Instagram, TikTok), mobil uygulamaların test edilmesi, en katı korumaların aşılması |
Çoğu sunucusuz uygulama için yerleşik proxy kullanılması önerilir. Bunlar, hız ve anonimlik arasında optimal bir denge sağlar. Yerleşik IP'ler, normal ev kullanıcıları gibi görünür, bu da bot koruma sistemlerini ve oran limitlerini aşmayı sağlar, gecikmeyi önemli ölçüde artırmadan.
Veri merkezi proxy'leri yalnızca basit görevler için uygundur (HTTP durumlarının kontrolü, kamuya açık API'lerle çalışma). Mobil proxy'ler, mobil API'lerle çalıştığınızda veya maksimum anonimlik sağlamak kritik olduğunda gereklidir.
AWS Lambda'da proxy ayarlama
AWS Lambda, en popüler sunucusuz platformdur ve burada proxy entegrasyonu, HTTP istemcisinin doğru bir şekilde ayarlanmasını gerektirir. Lambda işlevleri, çeşitli programlama dilleri (Node.js, Python, Go) kullanabilir, en yaygın olanlar için örnekleri inceleyelim.
Node.js (axios)
Axios, Node.js'te HTTP istekleri için en popüler kütüphanedir. Proxy ayarlamak için yapılandırmada proxy parametresini kullanın:
const axios = require('axios');
exports.handler = async (event) => {
const proxyConfig = {
host: 'proxy.example.com',
port: 8080,
auth: {
username: 'your_username',
password: 'your_password'
},
protocol: 'http'
};
try {
const response = await axios.get('https://api.example.com/data', {
proxy: proxyConfig,
timeout: 10000 // 10 saniye
});
return {
statusCode: 200,
body: JSON.stringify(response.data)
};
} catch (error) {
console.error('Proxy hatası:', error.message);
return {
statusCode: 500,
body: JSON.stringify({ error: error.message })
};
}
};
Önemli bir nokta: Proxy kimlik bilgilerini AWS Systems Manager Parameter Store veya AWS Secrets Manager'da saklayın, kodda değil. Bu, güvenliği sağlar ve proxy'yi yeniden derleme olmadan kolayca değiştirmeyi mümkün kılar.
Python (requests)
Python'da proxy ile çalışmak için proxies parametresi ile requests kütüphanesini kullanın:
import requests
import json
def lambda_handler(event, context):
proxies = {
'http': 'http://username:password@proxy.example.com:8080',
'https': 'http://username:password@proxy.example.com:8080'
}
try:
response = requests.get(
'https://api.example.com/data',
proxies=proxies,
timeout=10
)
return {
'statusCode': 200,
'body': json.dumps(response.json())
}
except requests.exceptions.RequestException as e:
print(f'Proxy hatası: {str(e)}')
return {
'statusCode': 500,
'body': json.dumps({'error': str(e)})
}
SOCKS5 proxy'leri (daha güvenli bir protokol) için Python'da ek bir kütüphane requests[socks] yüklemeniz ve URL formatını değiştirmeniz gerekir:
proxies = {
'http': 'socks5://username:password@proxy.example.com:1080',
'https': 'socks5://username:password@proxy.example.com:1080'
}
Soğuk başlangıçlar için optimizasyon
Lambda işlevleri, soğuk başlangıçlar sorununa sahiptir — boşta kaldıktan sonraki ilk istek 1-3 saniye sürer. Proxy kullanırken bu süre artar. Gecikmeleri en aza indirmek için, HTTP istemcisini handler işlevinin dışında oluşturun:
const axios = require('axios');
// Konteynerin başlatılması sırasında bir kez istemci oluşturun
const httpClient = axios.create({
proxy: {
host: 'proxy.example.com',
port: 8080,
auth: {
username: process.env.PROXY_USER,
password: process.env.PROXY_PASS
}
},
timeout: 10000
});
exports.handler = async (event) => {
// Her çağrıda istemciyi yeniden kullanın
const response = await httpClient.get('https://api.example.com/data');
return {
statusCode: 200,
body: JSON.stringify(response.data)
};
};
Bu yaklaşım, soğuk başlangıç süresini 200-500 ms kadar azaltır, çünkü proxy yapılandırması yalnızca Lambda konteyneri oluşturulurken bir kez gerçekleştirilir.
Vercel Edge Functions'a proxy entegrasyonu
Vercel, iki tür sunucusuz işlev sunar: Node.js Functions (Lambda'ya benzer) ve Edge Functions (CDN üzerinde çalışır). Edge Functions, Cloudflare Workers'a yakın bir runtime'da çalışır ve Node.js API'lerinin kullanımında kısıtlamalar vardır. Her iki seçeneği de inceleyelim.
Vercel Node.js Functions
Normal Vercel Functions için AWS Lambda'daki gibi aynı yaklaşımı kullanın. api/fetch-data.js adlı bir dosya oluşturun:
import axios from 'axios';
export default async function handler(req, res) {
const proxyConfig = {
host: process.env.PROXY_HOST,
port: parseInt(process.env.PROXY_PORT),
auth: {
username: process.env.PROXY_USER,
password: process.env.PROXY_PASS
}
};
try {
const response = await axios.get(req.query.url, {
proxy: proxyConfig,
timeout: 8000
});
res.status(200).json(response.data);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
Vercel Dashboard'da (Ayarlar → Çevresel Değişkenler) PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS çevresel değişkenlerini ekleyin.
Vercel Edge Functions
Edge Functions, Node.js kütüphaneleri yerine Web Fetch API'sini kullanır. Proxy, özel başlıklar veya middleware aracılığıyla ayarlanır:
export const config = {
runtime: 'edge',
};
export default async function handler(req) {
const proxyUrl = `http://${process.env.PROXY_USER}:${process.env.PROXY_PASS}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
// Edge Runtime için proxy üzerinden agent ile fetch gerekir (polyfill gerektirir)
// Alternatif: proxy API'sini doğrudan kullanmak
const targetUrl = new URL(req.url).searchParams.get('target');
const response = await fetch(targetUrl, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
return new Response(await response.text(), {
status: response.status,
headers: response.headers
});
}
Önemli bir kısıtlama: Edge Runtime, standart Node.js proxy ajanlarını desteklemez. Proxy ile tam uyum için Node.js Functions kullanmanız veya Edge Functions'tan gelen istekleri alacak ayrı bir proxy sunucusu oluşturmanız önerilir.
Cloudflare Workers'ta proxy
Cloudflare Workers, V8 isolates üzerinde çalışır ve Vercel Edge Functions'tan daha sıkı kısıtlamalara sahiptir. Proxy'yi Node.js kütüphaneleri aracılığıyla bağlama standardı burada çalışmaz. İki işleyen yaklaşım vardır:
Yöntem 1: HTTP CONNECT tünelleme
HTTP CONNECT yöntemini destekleyen bir proxy kullanın. Proxy sunucusu üzerinden bir tünel oluşturun:
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const proxyUrl = 'http://proxy.example.com:8080';
const targetUrl = 'https://api.example.com/data';
const proxyAuth = btoa(`${PROXY_USER}:${PROXY_PASS}`);
const response = await fetch(proxyUrl, {
method: 'CONNECT',
headers: {
'Host': new URL(targetUrl).host,
'Proxy-Authorization': `Basic ${proxyAuth}`
}
});
if (response.status === 200) {
// Tünel kuruldu, ana isteği gerçekleştiriyoruz
const finalResponse = await fetch(targetUrl, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
}
});
return finalResponse;
}
return new Response('Proxy bağlantısı başarısız', { status: 502 });
}
Bu yöntem, CONNECT'i destekleyen HTTP proxy'leri ile çalışır. Çoğu yerleşik proxy sağlayıcısı bu imkanı sunar.
Yöntem 2: Proxy geçidi (önerilir)
Daha güvenilir bir yöntem, ayrı bir sunucuda (örneğin, VPS veya AWS EC2 üzerinde) bir ara proxy geçidi dağıtmaktır. Cloudflare Worker, istekleri geçidinize gönderir ve o da bunları proxy üzerinden iletir:
// Cloudflare Worker
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const targetUrl = new URL(request.url).searchParams.get('url');
const gatewayUrl = 'https://your-proxy-gateway.com/fetch';
const response = await fetch(gatewayUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY // Geçidinizi koruma
},
body: JSON.stringify({
url: targetUrl,
method: 'GET'
})
});
return response;
}
Proxy geçidi tarafında (Node.js sunucusu):
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
const proxyConfig = {
host: 'proxy.example.com',
port: 8080,
auth: {
username: process.env.PROXY_USER,
password: process.env.PROXY_PASS
}
};
app.post('/fetch', async (req, res) => {
if (req.headers['x-api-key'] !== process.env.API_KEY) {
return res.status(401).json({ error: 'Yetkisiz' });
}
try {
const response = await axios({
url: req.body.url,
method: req.body.method || 'GET',
proxy: proxyConfig,
timeout: 10000
});
res.json(response.data);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000);
Bu yaklaşım, ek bir hop ekler (50-100 ms gecikme artışı), ancak proxy bağlantısı üzerinde tam uyumluluk ve kontrol sağlar.
Sunucusuz ortamda IP adreslerinin döngüsü
Proxy kullanımının başlıca nedenlerinden biri, oran limitlerini aşmak için istekleri çok sayıda IP adresi arasında dağıtmaktır. Sunucusuz mimaride döngü için iki yaklaşım vardır:
Proxy sağlayıcısında otomatik döngü
Çoğu yerleşik proxy sağlayıcısı, dönen proxy'ler sunar — bir uç noktaya bağlanırsınız ve IP her istekte veya belirli bir aralıkta (örneğin, her 5 dakikada bir) otomatik olarak değişir. Bu, sunucusuz için en basit seçenektir:
// Tek bir uç nokta, IP otomatik olarak değişiyor
const proxyConfig = {
host: 'rotating.proxy.example.com',
port: 8080,
auth: {
username: 'user-session-' + Date.now(), // Benzersiz oturum
password: 'password'
}
};
Bazı sağlayıcılar, döngüyü kullanıcı adındaki parametreler aracılığıyla yönetmenize izin verir: user-session-random (her istekte yeni IP), user-session-sticky-300 (300 saniye boyunca bir IP).
Proxy havuzundan manuel döngü
Eğer statik proxy'lerin bir listesini (örneğin, özel proxy satın aldıysanız) varsa, uygulama düzeyinde döngü gerçekleştirebilirsiniz. Sunucusuz ortamda, durumu saklamak için DynamoDB (AWS) veya KV Storage (Cloudflare) kullanın:
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB.DocumentClient();
const PROXY_POOL = [
{ host: 'proxy1.example.com', port: 8080 },
{ host: 'proxy2.example.com', port: 8080 },
{ host: 'proxy3.example.com', port: 8080 }
];
async function getNextProxy() {
// Mevcut indeksi DynamoDB'den al
const result = await dynamodb.get({
TableName: 'ProxyRotation',
Key: { id: 'current_index' }
}).promise();
const currentIndex = result.Item?.index || 0;
const nextIndex = (currentIndex + 1) % PROXY_POOL.length;
// İndeksi güncelle
await dynamodb.put({
TableName: 'ProxyRotation',
Item: { id: 'current_index', index: nextIndex }
}).promise();
return PROXY_POOL[currentIndex];
}
exports.handler = async (event) => {
const proxy = await getNextProxy();
const response = await axios.get('https://api.example.com/data', {
proxy: {
...proxy,
auth: {
username: process.env.PROXY_USER,
password: process.env.PROXY_PASS
}
}
});
return { statusCode: 200, body: JSON.stringify(response.data) };
};
Bu yöntem, döngü üzerinde tam kontrol sağlar, ancak DynamoDB'ye ek istekler gerektirir (10-30 ms gecikme ekler). Yüksek trafikli uygulamalar için, indeksi Lambda konteynerinin belleğinde önbelleğe almayı ve her 100-1000 istekte bir güncellemeyi öneririz.
Hata ve zaman aşımı yönetimi
Proxy'ler, sunucusuz uygulamanıza ek bir hata noktası ekler. Kullanıcı isteklerini kaybetmemek için hataları doğru bir şekilde yönetmek kritik öneme sahiptir.
Proxy ile çalışırken yaygın hatalar
| Hata | Sebep | Çözüm |
|---|---|---|
| ETIMEDOUT | Proxy yanıt vermiyor veya yavaş çalışıyor | Zaman aşımını 5-8 saniyeye düşürün, başka bir proxy ile tekrar deneyin |
| ECONNREFUSED | Proxy sunucusu erişilemez | Proxy'nin erişilebilirliğini kontrol edin, başka bir proxy ile yedekleme kullanın |
| 407 Proxy Kimlik Doğrulaması Gerekiyor | Geçersiz kimlik bilgileri | Kullanıcı adı/parolayı kontrol edin, Lambda IP'sinin proxy'de beyaz listeye alındığından emin olun |
| 502 Bad Gateway | Proxy, hedef siteye bağlanamıyor | Site proxy'yi engelliyor olabilir, başka bir IP veya proxy türü deneyin |
Yedekleme ile tekrar deneme mantığı uygulaması
Hatalarda yedek proxy'ye geçiş ile otomatik tekrar denemeleri ekleyin:
const axios = require('axios');
const PRIMARY_PROXY = {
host: 'primary.proxy.com',
port: 8080,
auth: { username: 'user', password: 'pass' }
};
const FALLBACK_PROXY = {
host: 'fallback.proxy.com',
port: 8080,
auth: { username: 'user', password: 'pass' }
};
async function fetchWithRetry(url, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const proxy = attempt === 0 ? PRIMARY_PROXY : FALLBACK_PROXY;
try {
const response = await axios.get(url, {
proxy,
timeout: 8000
});
return response.data;
} catch (error) {
console.log(`Deneme ${attempt + 1} başarısız:`, error.message);
// Müşteri hatalarında (4xx) tekrar deneme yok
if (error.response && error.response.status < 500) {
throw error;
}
// Son deneme — hatayı fırlat
if (attempt === maxRetries - 1) {
throw error;
}
// Tekrar deneme öncesinde üstel gecikme
await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt)));
}
}
}
exports.handler = async (event) => {
try {
const data = await fetchWithRetry('https://api.example.com/data');
return { statusCode: 200, body: JSON.stringify(data) };
} catch (error) {
return { statusCode: 500, body: JSON.stringify({ error: error.message }) };
}
};
Bu uygulama, üç deneme yapar: ilki ana proxy üzerinden, diğerleri yedek üzerinden. Denemeler arasında üstel gecikme (1 saniye, 2 saniye, 4 saniye) eklenmiştir, böylece aşırı yük oluşturulmaz.
İzleme ve uyarılar
Proxy hatalarını CloudWatch (AWS), Vercel Analytics veya Sentry üzerinden izleyin. Aşağıdaki metrikleri takip edin:
- Proxy üzerinden başarılı isteklerin yüzdesi (>%95 olmalıdır)
- İsteklerin ortalama gecikmesi (artış, proxy ile ilgili sorunları gösterebilir)
- Zaman aşımı hatalarının sayısı (eğer >%5 ise — proxy aşırı yüklenmiş veya yavaş)
- Hata kodlarına göre hata dağılımı (407, 502, ETIMEDOUT vb.)
Eşiklerin aşılması durumunda uyarılar ayarlayın — bu, yedek proxy sağlayıcısına hızlı bir şekilde geçiş yapmanızı veya yapılandırmayı değiştirmenizi sağlar.
Sonuç
Proxy entegrasyonu, sunucusuz uygulamalarda kritik sorunları çözer: veri merkezi IP'lerine göre engellemeler, oran sınırlamaları ve coğrafi engellemeler. AWS Lambda'da (Node.js ve Python), Vercel Functions ve Cloudflare Workers'ta proxy ayarlama, IP adreslerinin döngüsü ve hata yönetimini inceledik.
Anahtar öneriler: yüksek anonimlik gerektiren görevler için yerleşik proxy kullanın (ayrıştırma, sosyal medya API'leri ile çalışma), kimlik bilgilerini güvenli depolarda saklayın (AWS Secrets Manager, Vercel Çevresel Değişkenleri), yedek proxy'lere geçiş ile tekrar deneme mantığını uygulayın ve hata izleme ayarlayın.
Yüksek stabilite gerektiren sunucusuz uygulamalar için, yerleşik proxy'leri otomatik döngü ile kullanmanızı öneririz — bunlar, dış API'ler ve hizmetlerle çalışırken engellemeleri en aza indirirken hız, anonimlik ve güvenilirlik arasında optimal bir denge sağlar.