9 Ekim 2022 Pazar

Docker ve NGINX

Giriş
Elle hazırlanan conf dosyası /etc/nginx/conf.d/ dizinine kopyalanır. Yeni ismi default.conf veya başka bir conf ismi olabilir

Örnek
Şöyle yaparız
FROM nginx
LABEL "Project"="Vproject"
LABEL "Author"="Onumaku chibuike"

RUN rm -rf /etc/nginx/conf.d/default.conf
COPY nginvproapp.conf /etc/nginx/conf.d/vproapp.conf
nginvproapp.conf dosyası şöyledir
upstream vproapp {
 server vproapp:8080;
}
server {
  listen 80;
  location / {
    proxy_pass http://vproapp;
  }
}
Örnek
Şöyle yaparız
FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf



7 Ekim 2022 Cuma

Real Time Messaging Protocol - RTMP - Kullanmayın

Giriş
RTMP de bir streaming protokolü. Sadece TCP kullanır. 

Tarihçesi
RTMP Macromedia tarafından yaratılan ve daha sonra Adobe tarafından sahiplenilen bir protokol. Flash Player'da kullanılıyordu. Artık Adobe da bu protokolden desteğini çekti. Açıklaması şöyle
In 2017, Adobe announced that it would no longer support RTMP after the end of 2020. 
Kamera çıkışları genellikle şöyle
MP4
h.265
mpeg
Bu çıktıyı RTPM ile sarmalamak gerekir. Ancak bazı kameralar direkt RTMP çıkışı verebilir. 

Neden RTMP Kullanılmamalı
Çünkü desteklenmiyor dolayısıyla artık kullanmamak lazım. Bu protokol yerine HTML5 tarafından desteklenen HLS tercih edilebilir.





Jenkins Ortam Değişlenleri

Giriş
Açıklaması şöyle
$JOB_NAME — The name that you give your job when it is first set up.
$NODE_NAME — This is the name of the node on which the current build is running.
$JENKINS_URL — This is set to the URL of the Jenkins master that is responsible for running the build.
$BUILD_URL — Indicates the URL where the results of the builds can be found.
$WORKSPACE — Refers to the path of the workspace

Jenkins Pluginler

Giriş
Jenkins'e bir sürü plugin kurulabiliyor. Çoğu plugin harici bir komutun çıktısını göstermek üzere tasarlanmış.

Pluginler şurada
Manage Jenkins > Manage Plugins
JDK Tool Plugin
Bunun kurulum Manage Plugins altında değil. Manage Jenkins > Global Tool Configuration altında. Şeklen şöyle. Listede hazır gelen bir JDK sürümü veya bir zip kurması sağlanabilir.



Git Plugin
Açıklaması şöyle
1. Once you are at Jenkins Dashboard click on the “Manage Jenkins” button.
2. Click on Manage Plugins
3. On the Plugin page, select the GIT Plugin.
4. Install the Git plugin and restart your Jenkins.
4. Once you install the plugins, go to Manage Jenkins on your Jenkins dashboard. You will see your plugins listed among the rest.
Docker Plugin
Örnek ver

Docker Pipeline Plugin
Örnek ver

NodeJS Plugin
Örnek ver

SLOCCount Plugin
1. SLOCCount plugin kurulur

2. Execute shell alanına sayma işlemini yapan komut yazılır. Linux'ta kod saymak için iki araç var. Bunlar cloc ve sloc. sloc şöyle kullanılır.
sloccount --wide --details . > sloccount.sc
Aslında bash scriptleri için varsayılan çalışma alanı workspace dizinidir. Ancak emin olamadığım için böyle yazdım.
cloc ${WORKSPACE} --by-file --xml -out=${WORKSPACE}/cloc.xml
3. Publish SLOCLCount Analysis result alanına slockcount.sc veya clock.xml adını ekle.

Eğer cloc komutunu terminalde çalıştırmak isteseydik şöyle yapardık. 1234567 getirmek istediğimiz revizyon numarası olsun.
svn checkout -r 1234567 http:/... mysrc
cloc "mysrc/"


Jenkins Jobs

Giriş
Açıklaması şöyle
Freestyle

Freestyle build jobs are general-purpose build jobs, which provide maximum flexibility. It can be used for any type of project.

Multi-configuration

The multi-configuration project allows users to run the same build job on different environments. It is used for testing an application in different environments.

Folder

This project allows users to create folders to organize and categorize similar jobs in one folder or subfolder.

Multi-branch Pipeline

This project type lets you implement different Jenkinsfiles for different branches of the same project.

Pipeline

This project runs the entire software development workflow as code. Rather than creating several jobs for each stage of software development, you can now run the entire workflow as one code.

GitHub Organisation
This project scans your entire GitHub organization and creates Pipeline jobs for each repository containing a Jenkinsfile.
1. Freestyle
Örnek
Şöyle yaparız


Örnek
Şöyle yaparız
Click New item, give it a name (I called mine “continuous-integration”), and then select Freestyle Project. You will be presented with a bunch of option, the following settings should be set:

- Under Source Code Management, select git, then enter the URL of your GitHub repo as well as the branch you would like Jenkins to listen to.
- Under Build Triggers, select GitHub hook trigger for GITScm polling
- Under Build Environment, select Provide Node & npm bin/ folder to PATH. Select your node installation under NodeJS Installation
- Under Build, add the build step Execute Shell and in the prompt enter:
  npm install
  npm test
Şeklen şöyle


4. Multi-branch pipeline
Açıklaması şöyle
How do you create a multi-branch Jenkins pipeline?
In a Multi-branch Pipeline project, Jenkins automatically discovers, manages, and executes Pipelines for branches that contain a Jenkinsfile in source control.

To create a Multi-branch Jenkins Pipeline

1. Open Jenkins Dashboard and create a new item by clicking “New Item”
2. Enter the project name, and from the options select “Multi-branch pipeline”
3. Once you confirm, select the repository location, and branch source and add the branch source credentials.
4. After saving the project, Jenkins automatically creates new Multibranch Pipelines for repositories
5. Then to connect to the GitHub repo, we need the HookURL
6. To get this URL from the repository settings, add this HookURL to the Webhooks section
7. Once the jobs are created, Jenkins will automatically trigger the build.
Bir video burada. Açıklaması şöyle. Yani aynı pipeline farklı branch'ler için otomatik olarak yaratılıyor ve çalıştırılıyor.
A multi-branch pipeline is a concept of automatically creating Jenkins pipelines based on Git branches. It can automatically discover new branches in the source control (Github) and automatically create a pipeline for that branch. When the pipeline build starts, Jenkins uses the Jenkinsfile in that branch for build stages.

SCM (Source Control) can be Github, Bitbucket, or a Gitlab repo.
Benzer bir açıklama şöyle
Jenkins Pipeline Vs. Multibranch Pipeline
A normal pipeline job is meant for building a single branch from the SCM and deploy to a single environment. 

A multibranch pipeline is meant for building multiple branches from a repository and deploy to multiple environments if required.
5. Pipeline
Docker image deployment için kullanılır
Örnek
Açıklaması şöyle
Now go back to the dashboard and create a new item and select Pipeline.

Under Build Triggers, select Build after other projects are built, enter the name of your previous CI item, and select Trigger only if build is stable. That way we will only deploy the application if the previous tests succeeded.
Şeklen şöyle

Açıklaması şöyle
Next under Pipeline, select Pipeline script and enter the following script. Make sure to change the environment variables at the top of the script. Change registry (repository) and gitUrl/gitBranch to your repositories, and change the registryCredential variable to the id of your Docker Hub credentials that you created earlier.
Şöyle yaparız
pipeline {
    environment {
        registry = 'christophergustafson/node-application'
        registryCredential = 'dockerhub'
        dockerImage = ''
        gitBranch = 'main'
        gitUrl = 'https://github.com/ChristopherGustafson/tutorial-app.git'
    }

    agent any
    stages {
            stage('Cloning our Git') {
                steps {
                    git branch:gitBranch, url:gitUrl
                }
            }

            stage('Building Docker Image') {
                steps {
                    script {
                        dockerImage = docker.build registry + ":$BUILD_NUMBER"
                    }
                }
            }

            stage('Deploying Docker Image to Dockerhub') {
                steps {
                    script {
                        docker.withRegistry('', registryCredential) {
                        dockerImage.push()
                        }
                    }
                }
            }

            stage('Cleaning Up') {
                steps{
                  sh "docker rmi --force $registry:$BUILD_NUMBER"
                }
            }
        }
    }




Jenkins jenkins.exe

Giriş
Kullanım şöyle
# Start Jenkins
jenkins.exe start

# Stop Jenkins
jenkins.exe stop

# Restart Jenkins
jenkins.exe restart
stop seçeneği
Servisi durdurmak için şöyle yaparız.
jenkins.exe stop

4 Ekim 2022 Salı

Amazon Kinesis (AWS) - Kafka Gibidir

Giriş
Kinesis, aslında Kafka'ya bakarak geliştirilmiş. Açıklaması şöyle. Kafka'daki partition, Kinesis'te shard olarak isimlendiriliyor.
Kinesis is a promising technology modeled after Kafka, a partition in the latter is a shard in Kinesis
Shard'ın üst sınırı var. Açıklaması şöyle
Each shard can support up to 5 transactions per second for reads, up to a maximum total data read rate of 2 MB per second and up to 1,000 records per second for writes, up to a maximum total data write rate of 1 MB per second (including partition keys)
Kinesis'in bazı özellikleri şöyle
It provides ordering of records, as well as the ability to read and/or replay records in the same order.
- Allows record size up to 1 MB
- Works at shard level not message level
- No auto scaling, developer needs to track shard usage and re-shard the Kinesis stream when necessary
- Limited read throughput (5 transactions per second per shard)
- Number of shards in a stream determines the maximum throughput
- Multiple consumers can be attached to a single stream, and each consumer can process every record individually (thanks to shard-iterators)
Kinesis kullanmak için KCL Client gerekiyor. Açıklaması şöyle
Streaming data such as video processing/uploading are a good fit for Kinesis. But, not all data/records/events should go into Kinesis. It is not a general purpose enterprise event bus or queue.

A little context:

We once joined on a project midway, and have to support an ETL pipeline that included Kinesis in the deployment. The application collected small json records, and stuffed them into Kinesis with the python boto3 api . On the other side, worker process running inside EC2/ECS were pulling these records with boto3 and processing them. We then discovered that retrieving records out of Kinesis Streams when you have multiple worker is non-trivial.

Imagine if you are running 4 workers, and they are all listening to the same Kinesis stream for events. How do we prevent them from working on the same events? In traditional queueing systems, you use locks and owner columns to ensure each task is handled by only one worker. Amazon SQS will mark a message as busy when one of the worker is working on the message, so that other workers do not do duplicate work.

To implement the same pattern with Kinesis Stream, you must implement KCL, which is written in Java (nothing wrong with Java). The KCL agent will be spun up as a second daemon process in the background, and send events to your application when it itself receives events.

This means: all of your python/ruby/node docker images that handles records from Kinesis must install Java dependencies and run the KCL java process in the background.
Message Queue Olarak Kinesis
Kinesis yerine SNS veya SQS tercih edilebilir. Açıklaması şöyle
It is both cumbersome and difficult to apply Kinesis stream correctly, especially when you are looking for an enterprise queue. You would do better by using SNS/SQS combination, or using a queuing framework that sits on top of Redis or traditional databases.
Data Ingestion veya Strema Olarak Kinesis
Bu kullanım Kinesis için daha uygun. Ancak SQS + Kinesis yerine, direkt Kafka ve Apache Flink kullanılabilir. Migration from Amazon SQS and Kinesis to Apache Kafka and Flink yazındaki bir örnek

Unit Test
LocalStackContainer kullanılır. Şu satırı dahil ederiz
<dependency>
  <groupId>org.testcontainers</groupId>
  <artifactId>localstack</artifactId>
  <version>1.17.3</version>
  <scope>test</scope>
</dependency>
Örnek
Şöyle yaparız
import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.containers.localstack.LocalStackContainer.Service;

LocalStackContainer localStack = new LocalStackContainer(parse("localstack/localstack")
  .withTag("0.12.3"))
  .withEnv("KINESIS_LATENCY","1000")
  .withServices(Service.KINESIS);
localStack.start();
Daha sonra şöyle yaparız
import com.amazonaws.services.kinesis.AmazonKinesisAsync;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.kinesis.AmazonKinesisAsync;
import com.amazonaws.services.kinesis.AmazonKinesisAsyncClientBuilder;


String endpoint = "http://" + localStack.getHost() + ":" + 
  localStack.getMappedPort(4566));
String region = localStack.getRegion();
String accessKey = localStack.getAccessKey();
String secretKey = localStack.getSecretKey();

AmazonKinesisAsyncClientBuilder builder = AmazonKinesisAsyncClientBuilder.standard();
builder.withEndpointConfiguration(
  new AwsClientBuilder.EndpointConfiguration(endpoint, region));

builder.withCredentials(
  accessKey == null ? new DefaultAWSCredentialsProviderChain() :
  new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey))
);

builder.withClientConfiguration(new ClientConfiguration());
builder.withExecutorFactory(() -> executorServiceSupplier.get());

AmazonKinesisAsync kinesis =  builder.build();
Test bitince şöyle yaparız
kinesis.shutdown();
localStack.stop();

Kinesis API
Şu satırı dahil ederiz
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-java-sdk-kinesis</artifactId>
  <version>1.12.276</version>
</dependency>

AmazonKinesisAsync Sınıfı
Şu satırı dahil ederiz
import com.amazonaws.SDKGlobalConfiguration;
import com.amazonaws.services.kinesis.AmazonKinesisAsync;
import com.amazonaws.services.kinesis.model.PutRecordsResult;
import com.amazonaws.services.kinesis.model.Shard;

import static com.amazonaws.services.kinesis.model.ShardIteratorType
.AFTER_SEQUENCE_NUMBER;

import static com.amazonaws.services.kinesis.model.ShardIteratorType.AT_SEQUENCE_NUMBER;
import static com.amazonaws.services.kinesis.model.ShardIteratorType.AT_TIMESTAMP;
import static com.amazonaws.services.kinesis.model.ShardIteratorType.LATEST;
import static com.amazonaws.services.kinesis.model.ShardIteratorType.TRIM_HORIZON;
createStream metodu
Örnek
Şöyle yaparız
import com.amazonaws.services.kinesis.model.CreateStreamRequest;

CreateStreamRequest request = new CreateStreamRequest();
int shardCount = 3
request.setShardCount(shardCount);

String stream = "TestStream";
request.setStreamName(stream);

CreateStreamResult result = kinesis.createStream(request);
describeStreamSummary metodu
Örnek
Şöyle yaparız. StreamStatus CREATING, DELETING, ACTIVE, UPDATING olabilir.
import com.amazonaws.services.kinesis.model.DescribeStreamSummaryRequest;
import com.amazonaws.services.kinesis.model.StreamDescriptionSummary;
import com.amazonaws.services.kinesis.model.StreamStatus;

DescribeStreamSummaryRequest request = new DescribeStreamSummaryRequest();
request.setStreamName(stream);

StreamDescriptionSummary description = kinesis.describeStreamSummary(request)
  .getStreamDescriptionSummary();
String statusString = description.getStreamStatus();

StreamStatus status =  StreamStatus.valueOf(statusString);
listShards metodu
Örnek
Şöyle yaparız
import com.amazonaws.services.kinesis.model.ListShardsRequest;
import com.amazonaws.services.kinesis.model.ListShardsResult;

import com.amazonaws.services.kinesis.model.Shard;
import com.amazonaws.services.kinesis.model.ShardFilterType;

List<Shard> shards = new ArrayList<>();
String nextToken = null;
do {
  ShardFilterType filterType = ShardFilterType.AT_LATEST; //only the currently open shards
  ListShardsRequest request = ...;
  ListShardsResult response = kinesis.listShards(request);
  shards.addAll(response.getShards());
  nextToken = response.getNextToken();
} while (nextToken != null);