Event Hubs ve IoT Hub için özel eklentilerle Azure Yük Testi

Çözüm fikirleri

Bu makalede bir çözüm fikri açıklanmaktadır. Bulut mimarınız bu mimarinin tipik bir uygulaması için ana bileşenleri görselleştirmeye yardımcı olmak için bu kılavuzu kullanabilir. İş yükünüzün özel gereksinimlerine uygun iyi tasarlanmış bir çözüm tasarlamak için bu makaleyi başlangıç noktası olarak kullanın.

Bu çözüm, kullanıcı ve cihaz davranışlarının benzetimini yapmak için Apache JMeter betikleri ve özel eklentiler çalıştırmanıza olanak tanıyan bir hizmet olan Azure Yük Testi'i kullanma konusunda rehberlik sağlar. Bu çözüm ayrıca Azure İşlevleri ve Azure Event Hubs ile örnek bir uygulamada temel performans göstergelerini (KPI) tasarlamayı ve yük testinin sonuçlarını izlemek ve analiz etmek için bir pano geliştirmeyi açıklar. Bu örnekte Event Hubs kullanılır, ancak Event Hubs istemcisini IoT Hub istemcisi olarak değiştirerek aynı yaklaşımı Azure IoT Hub'a uygulayabilirsiniz. Bu makalede JMeter, eklentileri ve özel eklentileri ile İşlevler ve Event Hubs hakkında bilgi sahibi olduğunuz varsayılır.

IoT Hub, bölümler de dahil olmak üzere Event Hubs'dan daha fazla temel bileşen içerir. Bu nedenle, bu makalede açıklanan yük testi yaklaşımı, en az değişiklikle IoT Hub için de geçerlidir.

Mimari

Yük testi gerçekleştirmek için, JMeter'e test sırasında ne yapacağını bildiren bir dizi yönerge olan bir test planına ihtiyacınız vardır. Test planı birden çok test senaryosu içerebilir ve her senaryo farklı ayarlara ve yapılandırmalara sahip olabilir. Örneğin, bir web uygulamasına erişen tek bir kullanıcının simülasyonunu oluşturan bir senaryonuz ve aynı uygulamaya aynı anda birden çok kullanıcının sanal olarak erişmesini sağlayan başka bir senaryonuz olabilir.

Yük testi için örnek mimari diyagramı.

Bu mimarinin bir Visio dosyasını indirin.

Veri akışı

Aşağıdaki veri akışı önceki diyagrama karşılık gelir:

  1. Simülasyon cihazı, yük testi aracısı aracılığıyla bir olay hub'ına veri gönderir. JMeter özel eklentileri kullanılarak cihazın herhangi bir davranışı simülasyonu yapılabilir. Yük Testi aracısı, herhangi bir sanal cihaz türü için özel eklentiyi çalıştırdıktan sonra olay hub'ına veri gönderir.

  2. Olay hub'ı, verileri işleyen ve Azure SQL Veritabanı ve Azure Digital Twins gibi diğer aşağı akış hizmetlerine gönderen bir Azure işlev uygulamasını tetikler.

  3. Azure İzleyici, işlev uygulamasını ve Event Hubs'ı izler.

  4. Yük Testi, Verileri Azure İzleyici'den toplar ve bir panoda görüntüler.

Bileşenler

Bu örnekte aşağıdaki bileşenler kullanılır:

  • Yük Testi: Kullanıcı ve cihaz davranışlarının simülasyonunu yapmak için Apache JMeter betiklerini ve özel eklentileri çalıştırmak için Yük Testi'ni kullanın. Yük Testi, yük testlerini yönetmek ve çalıştırmak için web tabanlı bir arabirim ve işlemi otomatikleştirmek için bir dizi API sağlar. Yük Testi tam olarak yönetilen bir hizmettir ve bu da sunucuları veya altyapıyı yönetmenize gerek olmadığı anlamına gelir. Bu mimaride, Yük Testi JMeter betiklerini ve özel eklentileri yükler ve bu betiklerin çalıştırıldığı hesaplama ortamıdır.

  • Event Hubs: Event Hubs, çeşitli kaynaklardan gelen olayları ve akış verilerini gerçek zamanlı olarak toplamak, işlemek ve analiz etmek için kullanabileceğiniz bulut tabanlı bir olay işleme hizmetidir. Event Hubs, Gelişmiş Message Queuing Protokolü (AMQP), HTTPS, Kafka protokolü, Message Queuing Telemetri Aktarımı (MQTT) ve WebSocket üzerinden AMQP gibi birden çok protokolü destekler. Bu mimari etkinlik tabanlı olup, Yük Testi iş yükünü yük testi amacıyla etkinliklerle oluşturur.

  • IoT Hub: IoT Hub, bir IoT uygulaması ile ekli cihazları arasındaki iletişim için merkezi bir ileti hub'ı olarak hizmet veren, bulutta barındırılan bir yönetilen hizmettir. Milyonlarca cihazı ve arka uç çözümlerini güvenilir ve güvenli bir şekilde bağlayabilirsiniz. Neredeyse tüm cihazlar bir IoT hub'ına bağlanabilir. Event Hubs istemcisini IoT Hub istemcisi olarak değiştirerek bu mimariyi IoT Hub'ı kullanacak şekilde uyarlayabilirsiniz.

  • Azure İşlevleri: İşlevler, sunucuları veya altyapıyı yönetmeye gerek kalmadan kodu çalıştırmak için kullanabileceğiniz sunucusuz bir işlem hizmetidir. C#, F#, Java, JavaScript, PowerShell, Python ve TypeScript gibi birden çok programlama dilini destekler. Bu mimaride birincil işlem katmanı olarak İşlevler kullanılır. Event Hubs'daki olay verileri işlev uygulamalarını tetikler ve ölçeklendirir.

  • JMeter GUI: JMeter GUI, öncelikli olarak web uygulamalarının performansını test etmek için kullanılan bir açık kaynak yük testi aracıdır. Bununla birlikte, SOAP ve REST web hizmetleri, FTP sunucuları ve veritabanları gibi diğer uygulama türlerini test etmek için de kullanabilirsiniz.

  • Azure İzleyici: Azure İzleyici, Azure kaynakları için izleme ve uyarı özellikleri sağlar. Uygulamalarınızın ve temel alınan altyapının performansını ve durumunu izlemek için bunu kullanın. Bu mimaride Azure İzleyici, yük testi sırasında Azure altyapı bileşenlerinin durumunu izler.

Senaryo ayrıntıları

Mevcut bir Apache JMeter betiğini uygulamak ve herhangi bir Azure kaynağında bulut ölçeğinde yük testi çalıştırmak için Yük Testi'ni kullanabilirsiniz.

JMeter, test edicilerin yük testleri, stres testleri ve işlevsel testler oluşturmasına ve çalıştırmasına olanak tanır. Test edicilerin ağır yükler altında ortaya çıkabilecek olası performans sorunlarını veya diğer sorunları belirleyebilmesi için aynı anda bir web uygulamasına erişen birden çok kullanıcının simülasyonunu oluşturur. Yanıt süresi, aktarım hızı ve hata oranı gibi çeşitli performans ölçümlerini ölçmek için JMeter kullanabilirsiniz.

JMeter, kullanıcıların farklı ayarlara ve yapılandırmalara sahip birden çok test senaryosu içerebilen test planları oluşturmasına olanak sağlamak için GUI tabanlı bir arabirim kullanır. Test ediciler ayrıca eklentileri kullanarak veya özel kod yazarak JMeter'i özelleştirebilir. Eklentiler, kullanıcıların AMQP ve WebSocket gibi HTTP dışı protokoller kullanan hizmetlerle çalışmasına yardımcı olabilir.

JMeter, yük testi için çok çeşitli özellikler ve işlevler sağlar, ancak yerleşik işlevsellik belirli kullanım örneklerini veya gereksinimleri kapsamayabilir. Test ediciler özel eklentiler geliştirerek yeni işlevler ekleyebilir veya mevcut özellikleri ihtiyaçlarına daha uygun olacak şekilde özelleştirebilir.

Örneğin, belirli bir kullanıcı davranışı türünün benzetimini yapmak veya daha gerçekçi test verileri oluşturmak için özel bir eklenti geliştirebilirsiniz. JMeter'i günlüğe kaydetme ve raporlama araçları veya sürekli tümleştirme ve sürekli dağıtım (CI/CD) işlem hatları gibi diğer araçlar veya sistemlerle tümleştirmek için özel eklentiler de geliştirebilirsiniz. Özel eklentiler, test sürecini kolaylaştırmaya yardımcı olabilir ve yük testini genel yazılım geliştirme iş akışına dahil etmeyi kolaylaştırabilir. Test edicilerin JMeter'i kendi ihtiyaçlarına göre uyarlamasına ve yük testi çalışmalarının doğruluğunu ve verimliliğini artırmasına olanak sağlar.

Bu örnekte bir cihaz belirli bir süre içindeki sıcaklığı ve nemi bildirir. Örnek, özel bir JMeter eklentisi kullanarak bu davranışın simülasyonunu oluşturur. Özel eklentinin geçerli uygulaması, sağlanan bir şablon kullanarak rastgele veriler oluşturur. Ancak eklenti, herhangi bir cihaz için olası karmaşık davranışları içerebilir. Bu örnekte cihaz, verileri Azure'daki bir olay hub'ına gönderir. Olay hub'ı, verileri işleyen ve SQL Veritabanı gibi diğer aşağı akış hizmetlerine gönderen bir Azure işlev uygulamasını tetikler. Azure İşlevleri, mimarinin test yaptığı hizmettir. Test planı, cihazın davranışını simüle etmek ve olay hub'ına veri göndermek için tasarlanmıştır.

Olası kullanım örnekleri

Yük Testi'nin özel eklentilerle kullanılması aşağıdakiler gibi çeşitli senaryolarda yararlı olabilir:

  • AMQP ve WebSocket gibi HTTP dışı protokoller kullanan bir uygulamanın performansını test etme.
  • Özel protokol kullanan bir uygulamanın performansını test etme.
  • Microsoft dışı SDK kullanan bir uygulamanın performansını test etme.
  • Belirli bir kullanıcı veya cihaz davranışı türünün benzetimini yapın.
  • Daha gerçekçi test verileri oluşturma.

Özel eklentiler

JMeter'de özel eklentiler, varsayılan işlevselliğini genişletmek için ekleyebileceğiniz yazılım bileşenleridir. Özel eklentiler JMeter'a yeni özellikler, işlevler veya tümleştirmeler ekler. Java programlama dilini ve JMeter eklentisi geliştirme setini (PDK) kullanarak özel eklentiler geliştirebilirsiniz. PDK, GUI öğeleri, dinleyiciler ve örnekleyiciler de dahil olmak üzere yeni eklentiler oluşturmanıza yardımcı olan bir dizi araç ve API sağlar.

JMeter'da Event Hubs için özel bir örnekleyici uygulamak için JMeter eklentilerini yükleme yönergelerini izleyin. Özel örnekleyicinizi uyguladıktan sonra, bunu diğer tüm örnekleyiciler gibi Yük Testi'ndeki JMeter test planınızda kullanabilirsiniz.

Belirli bir senaryoyu çalıştırmak için sanal kullanıcılar ve cihazlar gibi iş parçacıklarının sayısını denetleyan bir iş parçacığı grubu kullanarak bir test planı uygulayabilirsiniz. Her iş parçacığı grubu, iş parçacığı sayısı, rampa süresi, döngü sayısı ve süre için farklı ayarlara sahip olabilir. İş parçacığı grupları, test planı yapılandırmasına ve uygulama gereksinimlerine bağlı olarak sıralı veya paralel olarak çalışabilir. Örnekleyiciyi bir iş parçacığı grubuna ekleyebilir, parametrelerini ayarlayabilir ve gerektiğinde yapılandırabilirsiniz. Özel örnekleyiciler, JMeter'da yerleşik örnekleyicilerin desteklemediğini karmaşık senaryoların ve isteklerin benzetimini yapmanızı sağlayan güçlü araçlar olabilir.

Özel eklenti ile Apache JMeter betiği oluşturma

Bu bölümde, Event Hubs ile bir uygulamayı yüklemek için örnek bir JMeter test betiği oluşturacaksınız.

Örnek JMeter test betiği oluşturmak için:

  1. Metin düzenleyicisinde bir LoadTest.jmx dosyası oluşturun ve aşağıdaki kod parçacığını dosyaya yapıştırın. Bu betik, olay hub'ına aynı anda olay gönderen 36 sanal makinenin yük testini simüle eder. Tamamlanması 10 dakika sürer.

    <?xml version="1.0" encoding="UTF-8"?>
    <jmeterTestPlan version="1.2" properties="5.0" jmeter="5.5">
        <hashTree>
        <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
            <stringProp name="TestPlan.comments"></stringProp>
            <boolProp name="TestPlan.functional_mode">false</boolProp>
            <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
            <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
            <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
                <collectionProp name="Arguments.arguments"/>
            </elementProp>
            <stringProp name="TestPlan.user_define_classpath"></stringProp>
        </TestPlan>
        <hashTree>
            <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
                <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
                <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
                    <boolProp name="LoopController.continue_forever">false</boolProp>
                    <intProp name="LoopController.loops">-1</intProp>
                </elementProp>
                <stringProp name="ThreadGroup.num_threads">36</stringProp>
                <stringProp name="ThreadGroup.ramp_time">20</stringProp>
                <boolProp name="ThreadGroup.scheduler">true</boolProp>
                <stringProp name="ThreadGroup.duration">600</stringProp>
                <stringProp name="ThreadGroup.delay"></stringProp>
                <boolProp name="ThreadGroup.same_user_on_next_iteration">false</boolProp>
            </ThreadGroup>
            <hashTree>
                 <com.microsoft.eventhubplugin.EventHubPlugin guiclass="com.microsoft.eventhubplugin.EventHubPluginGui" testclass="com.microsoft.eventhubplugin.EventHubPlugin" testname="Azure Event Hubs Sampler" enabled="true">
                    <!-- Azure Event Hub connection configuration using Managed Identity (see repository for instructions) -->
                    <boolProp name="useManagedIdentity">true</boolProp>
                    <stringProp name="eventHubNamespace">telemetry-ehn.servicebus.windows.net</stringProp>
                    <stringProp name="eventHubName">telemetry-data-changed-eh</stringProp>
                    <stringProp name="liquidTemplateFileName">StreamingDataTemplate.liquid</stringProp>
                </com.microsoft.eventhubplugin.EventHubPlugin>
            </hashTree>
        </hashTree>
        </hashTree>
    </jmeterTestPlan>
    

    ve com.microsoft.eventhubplugin.EventHubPluginGui uygulamasını com.microsoft.eventhubplugin.EventHubPluginAzure örnekleri bölümünde bulabilirsiniz.

  2. Dosyasında, test çalıştırıcılarının atanmış yönetilen kimliğini kullanarak Event Hubs bağlantı değerlerini ayarlayın. Bu kimliğin Event Hubs örneğine yazma erişimi olması gerekir.

  3. Dosyada, eventHubName düğümünün değerini olay hub'ı adı gibi telemetry-data-changed-eh olarak ayarlayın.

  4. Düğümün liquidTemplateFileName değerini etkinlik hub'ına gönderilen iletiyi içeren dosyaya ayarlayın. Örneğin, adlı StreamingDataTemplate.liquid bir dosya oluşturun:

    {
        {% assign numberOfMachines = 36 %}
        {% assign machineId = dataGenerator.randomNaturalNumber | modulo: numberOfMachines %}
        "MachineId": "{{machineId | prepend: '0000000000000000000000000000000000000000' | slice: -27, 27 }}",
        "Temperature": {{dataGenerator.randomInt | modulo: 100 }},
        "Humidity": {{dataGenerator.randomInt | modulo: 100 }}
    }
    

    Bu örnekte, olay hub'ı iletisinin yükü, MachineId, Temperature ve Humidity olmak üzere üç özelliğe sahip bir JSON nesnesidir. MachineId 27 karakter uzunluğunda ve TemperatureHumidity 100'den küçük rastgele tamsayılar olan rastgele oluşturulmuş bir kimliktir. Bu dosya bir Liquid şablon sözdizimidir. Liquid şablonu, çeşitli web geliştirme çerçevelerinde kullanılan popüler bir şablon oluşturma dilidir. Liquid şablonları, geliştiricilerin kolayca güncelleştirilebilen ve değiştirilebilen dinamik içerik oluşturmasına olanak tanır. Olay hub'ı iletilerinize değişkenler, koşullar, döngüler ve diğer dinamik öğeler eklemenize olanak sağlar. Söz dizimi basittir ve başlamanıza yardımcı olacak çok sayıda çevrimiçi kaynak vardır. Liquid şablonları dinamik, özelleştirilebilir iletiler oluşturmak için güçlü ve esnek bir yol sağlar.

  5. Dosyayı kaydedip kapatın

    Önemli

    JMeter betiğinde örnekleyici adına hiçbir kişisel veri eklemeyin. Örnekleyici adları Yük Testi test sonuçları panosunda görünür. JMeter betik dosyasıyla birlikte bir sıvı şablonu örneği Azure örnekleri'nden indirilebilir.

Event Hubs'tan IoT Hub'a özel eklentiyi güncelleştirme

Özel eklenti birincil hedef kaynak olarak Event Hubs kullanır. Event Hubs için SDK istemci kurulumu aşağıdaki yapılandırmadır:

EventHubProducerClient producer = null;
EventHubClientBuilder producerBuilder = new EventHubClientBuilder();

producerBuilder.credential(getEventHubNamespace(), getEventHubName(), new DefaultAzureCredentialBuilder().build());
producer = producerBuilder.buildProducerClient();

EventDataBatch batch = producer.createBatch(new CreateBatchOptions());
batch.tryAdd(new EventData(msg));
producer.send(batch);

Aşağıdaki örnekte aynı çözümü nasıl yeniden kullanabileceğiniz, IoT bağımlılıklarını nasıl ekleyebileceğiniz ve SDK istemcisini IoT Hub kullanacak şekilde nasıl değiştirebileceğiniz gösterilmektedir:

IotHubServiceClientProtocol protocol = IotHubServiceClientProtocol.AMQPS;
ServiceClient client = new ServiceClient(getIoTHostName(), new DefaultAzureCredentialBuilder().build(), protocol);
client.open();

Message message = new Message(msg);
client.send(getDeviceName(), message);

client.close();

Yeni eklentiyi kullanarak yük testini çalıştırma

Yük Testi yük testinizi başlattığında ilk olarak JMeter betiğini ve diğer tüm dosyaları test altyapısı örneklerine dağıtır. Testi çalıştırmadan önce gerekli parametreleri tanımlamak ve ayarlamak için parametre sekmesine gidin. Daha fazla bilgi için bkz. Apache JMeter eklentileriyle yük testlerini özelleştirme ve Yük Testi.

Ortam için performans testi ayarlama

Performans testi için, test ortamınızın üretim ortamına benzer olması önemlidir. Bu örnek, sistemin kapasitesini ve performansını daha iyi anlamak için performans testi için aşağıdaki ortamı kullanır.

Hizmet Yapılandırma
Event Hubs Tek işlem birime sahip Premium
Azure İşlevleri Premium Plan (EP1) ile Linux - 210 ACU, 3,5 GB Bellek ve 1 vCPU eşdeğeri Standard_D1_v2
Bölge Doğu ABD

Event Hubs ve Azure İşlevleri dahil olmak üzere tüm Azure hizmetleri için doğru hizmet katmanını seçmek karmaşık bir işlemdir ve birçok faktöre bağlıdır. Daha fazla bilgi için bkz . Event Hubs fiyatlandırması ve İşlevler fiyatlandırması.

Performans testi için KPI tasarlama

Performans testi için KPI tasarlamadan önce iş gereksinimlerini ve sistem mimarisini tanımlamanız gerekir. İş gereksinimleri yanıt süresi, aktarım hızı veya hata oranı gibi hangi KPI'leri ölçmek istediğinizi bildirir. Sistem mimarisi, web sunucuları, veritabanları veya API'ler gibi her bileşenin performansını nasıl test ettiğinizi bildirir. Ayrıca yük testi, stres testi veya dayanıklılık testi gibi en iyi performans testi stratejisini seçmenize de yardımcı olur.

Bu örnekte aşağıdaki iş gereksinimleri vardır:

  • Sistem saniyede 1.000 isteği işleyebilir.
  • Sistem güvenilirliği 0,99'dan yüksektir.
  • Sistem telemetri verilerini bildiren 1.000 eşzamanlı cihazı işleyebilir.
  • Sistemin destekleyebilecek cihaz sayısı açısından maksimum kapasiteyi belirtebilirsiniz. Örneğin sistem, geçerli kapasitenin üç katı olan 1.000 eşzamanlı cihazı destekleyebilir.

Sistemin bu gereksinimleri karşılayıp karşılamadığını ölçmek için performans testi için aşağıdaki KPI'leri kullanabilirsiniz:

KPI Açıklama
RPS Olay hub'ı için saniye başına istek sayısı
YÜK Performans testi sırasında olay hub'ına gönderilen yük veya istek sayısı
Kızılötesi İşlev çağrılarının sayısı veya veri alım oranı
RT Azure İşlevleri için ortalama çalışma süresi
AMÜ Azure İşlevleri için ortalama bellek kullanımı
SR Tüm işlev uygulaması çağrılarının başarı oranı
ARS SQL server veya mikro hizmet gibi hizmetler için ortalama aşağı akış hizmeti yanıt süresi
DF İç işlev uygulaması hataları da dahil olmak üzere bağımlılık hatası sayısı
MRPS Art arda işlemede gecikme olmaksızın olay merkezi için maksimum RPS (sistem kapasitesi)

KPI'leri ölçme

KPI'leri ölçmek için bir performans testi stratejiniz olması gerekir. Strateji, her bileşen için performans testi yaklaşımını tanımlar. Bu örnek aşağıdaki performans testi stratejisini kullanır.

  • Event Hubs: Olay hub'ına yönelik performans testi yaklaşımı, olay hub'ına çok sayıda ileti göndermek ve ardından RPS ve LOAD'yi ölçmektir. RPS, olay hub'ına saniyede gönderilen ileti sayısıdır. LOAD, performans testi sırasında olay hub'ına gönderilen toplam ileti sayısıdır. Yük Testi RPS ve LOAD'yi ölçebilir.

  • Azure İşlevleri: İşlevler için performans testi yaklaşımı aşağıdaki ölçümleri ölçmektir.

    • Kızılötesi
    • RT
    • AMÜ
    • SR
    • ARS
    • DF

Azure İzleyici AMU, ARS ve DF'yi ölçebilir ancak IR, RT veya SR'yi ölçemez. Azure İzleyici'yi kullanarak KPI'leri ölçmek için Azure İşlevleri için Application Insights'ı etkinleştirin. Daha fazla bilgi için bkz. Application Insights tümleştirmesini etkinleştir.

Azure İzleyici'yi etkinleştirdikten sonra KPI'leri ölçmek için aşağıdaki sorguları kullanabilirsiniz:

  • IR: FunctionAppLogs | where Category startswith "name-space-of-your-function" and Message startswith "Executed" | summarize count() by FunctionName, Level, bin(TimeGenerated, 1h) | order by FunctionName desc

  • RT: FunctionAppLogs| where Category startswith "name-space-of-your-function" and Message startswith "Executed "| parse Message with "Executed " Name " (" Result ", Id=" Id ", Duration=" Duration:long "ms)"| project TimeGenerated, Message, FunctionName, Result, FunctionInvocationId, Duration

  • SR: FunctionAppLogs| where Category startswith "name-space-of-your-function" and Message startswith "Executed" | summarize Success=countif(Level == "Information" ), Total=count() by FunctionName| extend Result=Success*100.0/Total| project FunctionName, Result| order by FunctionName desc

Azure İzleyici panosu örneği

Aşağıdaki görüntüde Azure İzleyici panosunun bir örneği gösterilmektedir. Önceki sorgulara göre Azure İşlevleri için KPI'leri gösterir.

Azure İzleyici panosu örneklerini gösteren ekran görüntüsü.

Katkıda Bulunanlar

Microsoft bu makaleyi korur. Bu makaleyi aşağıdaki katkıda bulunanlar yazdı.

Asıl yazarlar:

Nonpublic LinkedIn profillerini görmek için LinkedIn'de oturum açın.

Sonraki adımlar