Dokumen proses integrasi Android SDK menjelaskan proses lengkap impor dan konfigurasi Android SDK, penguraian alamat IP, penerapan SDK ke library jaringan, serta verifikasi integrasi. Topik ini menjelaskan prosedur spesifik untuk menggunakan HTTPDNS bersama gRPC.
1. Latar Belakang
gRPC adalah framework Remote Procedure Call (RPC) open-source berkinerja tinggi dari Google yang berbasis protokol HTTP/2 dan banyak digunakan dalam arsitektur mikroservis. Secara default, gRPC menggunakan DNS sistem untuk resolusi nama domain. Namun, gRPC juga menyediakan mekanisme ekstensi NameResolver yang memungkinkan developer menyesuaikan logika resolusi.
Di Android, jika aplikasi Anda menggunakan gRPC, Anda dapat mengimplementasikan NameResolver kustom untuk mengintegrasikan HTTPDNS ke dalam gRPC, sehingga menggantikan DNS sistem dalam proses resolusi nama domain.
Catatan: Solusi ini berlaku untuk client gRPC yang menggunakan grpc-okhttp sebagai lapisan transport, yang merupakan metode yang direkomendasikan untuk Android.
2. Cara Kerja
Alur resolusi nama domain gRPC adalah sebagai berikut:
ManagedChannel
↓
NameResolver (custom endpoint)
↓
LoadBalancer
↓
Transport (grpc-okhttp)
↓
TCP connectionDengan membuat NameResolver kustom, Anda dapat mengintegrasikan HTTPDNS pada tahap resolusi nama domain. NameResolver kustom tersebut mengembalikan daftar alamat IP yang telah diselesaikan kepada gRPC, lalu LoadBalancer gRPC menangani load balancing dan failover.
3. Langkah Integrasi
3.1 Tambahkan dependensi
Tambahkan dependensi gRPC ke file build.gradle Anda:
dependencies {
// EMAS HTTPDNS
implementation 'com.aliyun.ams:alicloud-android-httpdns:x.x.x'
// gRPC Android
implementation 'io.grpc:grpc-okhttp:x.x.x'
implementation 'io.grpc:grpc-stub:x.x.x'
implementation 'io.grpc:grpc-protobuf-lite:x.x.x'
}
3.2 Inisialisasi HTTPDNS
Inisialisasi layanan HTTPDNS di kelas Application Anda:
public class MyApplication extends Application {
@Overridepublic void onCreate() {
super.onCreate();
// Initialize HTTPDNS
InitConfig config = new InitConfig.Builder()
.setContext(this)
.setSecretKey("your_secret_key") // Optional
.setEnableCacheIp(true, 24 * 60 * 60 * 1000) // Enable cache
.setEnableExpiredIp(true) // Allow use of expired IPs
.setTimeoutMillis(2000)
.build();
HttpDns.init("your_account_id", config);
}
}
3.3 Implementasikan NameResolver kustom
Buat kelas EmasHttpDnsNameResolver:
import io.grpc.EquivalentAddressGroup;
import io.grpc.NameResolver;
import io.grpc.Status;
import com.alibaba.sdk.android.httpdns.HttpDns;
import com.alibaba.sdk.android.httpdns.HttpDnsService;
import com.alibaba.sdk.android.httpdns.HTTPDNSResult;
import com.alibaba.sdk.android.httpdns.RequestIpType;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
public class EmasHttpDnsNameResolver extends NameResolver {
private final String host;
private final int port;
private Listener2 listener;
public EmasHttpDnsNameResolver(String host, int port) {
this.host = host;
this.port = port;
}
@Overridepublic String getServiceAuthority() {
return host;
}
@Overridepublic void start(Listener2 listener) {
this.listener = listener;
resolve();
}
@Overridepublic void refresh() {
resolve();
}
private void resolve() {
List<EquivalentAddressGroup> addressGroups = new ArrayList<>();
try {
// Call HTTPDNS to resolve the domain name
HttpDnsService httpDnsService = HttpDns.getService("your_account_id");
HTTPDNSResult result = httpDnsService.getHttpDnsResultForHostSyncNonBlocking(
host,
RequestIpType.auto
);
// If HTTPDNS returns null, fall back to the system DNS
if (result == null ||
(result.getIps() == null || result.getIps().length == 0) &&
(result.getIpv6s() == null || result.getIpv6s().length == 0)) {
InetAddress[] systemAddrs = InetAddress.getAllByName(host);
for (InetAddress addr : systemAddrs) {
addressGroups.add(new EquivalentAddressGroup(
new InetSocketAddress(addr, port)
));
}
} else {
// Add IPv4 addresses
if (result.getIps() != null) {
for (String ip : result.getIps()) {
addressGroups.add(new EquivalentAddressGroup(
new InetSocketAddress(ip, port)
));
}
}
// Add IPv6 addresses
if (result.getIpv6s() != null) {
for (String ip : result.getIpv6s()) {
addressGroups.add(new EquivalentAddressGroup(
new InetSocketAddress(ip, port)
));
}
}
}
// Return the resolution result
ResolutionResult resolutionResult = ResolutionResult.newBuilder()
.setAddresses(addressGroups)
.build();
listener.onResult(resolutionResult);
} catch (Exception e) {
listener.onError(Status.UNAVAILABLE.withDescription(
"HTTPDNS resolve failed: " + e.getMessage()
));
}
}
@Overridepublic void shutdown() {
// Clean up resources
}
}
3.4 Implementasikan NameResolverProvider
Buat kelas EmasHttpDnsResolverProvider:
import io.grpc.NameResolver;
import io.grpc.NameResolverProvider;
import java.net.URI;
public class EmasHttpDnsResolverProvider extends NameResolverProvider {
private static final String SCHEME = "emashttpdns";
@Overrideprotected boolean isAvailable() {
return true;
}
@Overrideprotected int priority() {
return 5;
}
@Overridepublic NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
if (!SCHEME.equals(targetUri.getScheme())) {
return null;
}
String host = targetUri.getHost();
int port = targetUri.getPort() == -1 ? 443 : targetUri.getPort();
return new EmasHttpDnsNameResolver(host, port);
}
@Overridepublic String getDefaultScheme() {
return SCHEME;
}
}
3.5 Daftarkan NameResolver
Daftarkan NameResolver kustom di kelas Application Anda:
public class MyApplication extends Application {
@Overridepublic void onCreate() {
super.onCreate();
// Initialize HTTPDNS (see step 3.2)
// ...
// Register the custom NameResolver
NameResolverRegistry.getDefaultRegistry()
.register(new EmasHttpDnsResolverProvider());
}
}
3.6 Gunakan client gRPC
Saat membuat channel gRPC, gunakan skema kustom:
// Create the channel
ManagedChannel channel = OkHttpChannelBuilder
.forTarget("emashttpdns://your-grpc-server.com:443")
.overrideAuthority("your-grpc-server.com") // Important: This ensures correct TLS SNI
.useTransportSecurity() // Enable TLS
.build();
// Create the stub and make the call
YourServiceGrpc.YourServiceBlockingStub stub =
YourServiceGrpc.newBlockingStub(channel);
YourResponse response = stub.yourMethod(request);
4. Verifikasi Integrasi
Setelah integrasi selesai, Anda dapat memverifikasi keberhasilannya menggunakan metode seperti hijacking impersonation atau pengujian fault injection. Untuk informasi lebih lanjut, lihat dokumen Verifikasi Integrasi Library Jaringan yang Berhasil.
5. Ringkasan
Dengan mengimplementasikan antarmuka NameResolver gRPC, Anda dapat mengintegrasikan HTTPDNS ke dalam client gRPC Anda. Pendekatan ini memberikan keuntungan berikut:
Implementasi sederhana: Anda hanya perlu mengimplementasikan antarmuka NameResolver untuk mengintegrasikan layanan HTTPDNS.
Versatilitas tinggi: Metode ini berlaku untuk berbagai skenario gRPC dan kompatibel dengan mekanisme keamanan seperti validasi sertifikat dan Server Name Indication (SNI).
Ketersediaan tinggi: Mendukung load balancing otomatis dan failover di antara beberapa alamat IP. Jika resolusi HTTPDNS gagal, sistem secara otomatis kembali menggunakan DNS sistem.
Optimalisasi kinerja: Membantu mencegah DNS hijacking serta meningkatkan kecepatan dan tingkat keberhasilan resolusi.