[Linux, Docker] Oracle Container Runtime for Docker on Oracle Linux for ARM64

原文はこちら。
https://blogs.oracle.com/linux/oracle-container-runtime-for-docker-on-oracle-linux-for-arm64

ARM64アーキテクチャ用のOracle Container Runtime for Dockerの提供を発表できうれしく思っています。インストールするには、以下のコマンドを実行してください。
yum install docker-engine
Docker Hubの公式Oracle Linuxイメージもアップデートされ、x86_64およびARM64アーキテクチャをサポートします。最新のOracle Linux 7ベースイメージをDocker HubからPullするには、以下のコマンドでOKです。
docker pull oraclelinux:7-slim
Dockerは自動的にアーキテクチャに対応した正しいイメージを取得します。Oracle Linux 7最小限のベースイメージを提供し、GitHubのDocker Imagesリポジトリに公開されているすべてのOracle製品イメージで使用されている7-slimタグを利用されることを推奨しますが、お好みであれば、latest、7、7.4タグも提供しています。
Official source for Docker configurations, images, and examples of Dockerfiles for Oracle products and projects
https://github.com/oracle/docker-images
REPOSITORY        TAG      IMAGE ID       CREATED     SIZE 
oraclelinux       7        b5e0e6470f16   2 hours ago 279MB 
oraclelinux       7.4      b5e0e6470f16   2 hours ago 279MB 
oraclelinux       latest   b5e0e6470f16   2 hours ago 279MB 
oraclelinux       7-slim   fdaeac435bbd   2 hours ago 146MB
ARM64で利用可能なOracle製品のイメージはまだないことにご注意ください。

Support

Oracle Linux for ARM64は開発者プレビューとして提供しており、Oracle Linux Supportの範囲外です。何か問題があれば、Oracle Technology Network (OTN) のOracle Linux for ARM64スペースで、コミュニティによるサポートを求めてください。
Oracle Linux for ARM64
https://community.oracle.com/community/server_&_storage_systems/linux/oracle-linux-for-arm64
Oracle Developer Community
https://community.oracle.com/welcome

[Cloud] Deploying Highly Available DC/OS on Oracle Cloud Infrastructure with Terraform

原文はこちら。
https://blogs.oracle.com/cloud-infrastructure/deploying-highly-available-dcos-on-oracle-cloud-infrastructure-with-terraform

Introduction

この記事では、Oracle Cloud InfrastructureにDC/OSを自動的にデプロイするためのTerraformテンプレートを紹介します。
Oracle Cloud Infrastructure
https://cloud.oracle.com/cloud-infrastructure
DC/OSは、Apache Mesos分散システムカーネルをベースにしたオープンソースの分散データセンターオペレーティングシステムです。単一のインタフェースから複数のシステムを管理し、これらのシステムにコンテナ、分散サービス、アプリケーションを展開することができます。

DC/OSは、クラスターを形成するマスター・ノードとエージェント・ノードのグループで構成されています。

Terraformテンプレートは、Oracle Cloud InfrastructureにこのDC/OSクラスタを自動的にデプロイします。テンプレートは、Terraformモジュールのセットと、Oracle Cloud Infrastructureで高可用性および構成可能なDC/OSクラスタを実行するために必要なリソースのプロビジョニングおよび構成に使用される基本構成の例で構成されています。

Oracle Cloud Infrastructure Environment

DC/OSクラスタをOracle Cloud Infrastructure内の任意のリージョンにデプロイできます。高可用性が必要な場合は、DC/OSマスタとエージェントノードをOracle Cloud Infrastructureのリージョンにある複数のアベイラビリティ・ドメインにデプロイすることを推奨します。

下図は、マスタ、パブリック・エージェント、GPUエージェント、通常のプライベートエージェントの各ノードを持つDC/OSクラスタのデプロイ例を示したものです。

Terraformテンプレートは、以下のComputeインスタンスをプロビジョニングします。
  • ブートストラップノード
  • マスターノード
  • パブリックエージェントノード
  • エージェントノード
  • GPUエージェントノード
テンプレートは、インスタンスシェイプ(GPUを含む)、これらのインスタンスの数、およびこれらのインスタンスの複数のアベイラビリティ・ドメインへの配置方法などを選択するための複数の入力変数を受け入れます。要件が基本構成を超えて拡張する場合、 関連モジュールをカスタマイズしてご自身の構成を形成することができます。

Deploy DC/OS Cluster

Prerequisites

Quick Start

  • 構成のカスタマイズ
    • プロジェクトルートにある、構成を指定するための "env-vars" ファイルを開く
    • テナント、ユーザー、コンパートメントに関連する、Oracle Cloud Infrastructureの必須入力変数を設定
      • Tenancy OCID
      • User OCID
      • API fingerprint
      • API private key
      • Compartment OCID
      • DC/OSインスタンスへSSHアクセスするための公開鍵・秘密鍵のペア
    • デフォルトの入力変数を確認し、必要に応じてアップデート
      • dcos_installer_url:   DC/OSコード入手のためのURL。デフォルト値は早期アクセスリリースに設定されているので、安定リリース(stable)に変更する場合は以下のURLを使う。https://downloads.dcos.io/dcos/stable/dcos_generate_config.sh
      • dcos_master_ad1_count、dcos_master_ad2_count、dcos_master_ad3_count:  各アベイラビリティ・ドメインにおけるマスタノードの個数
      • dcos_agent_ad1_count、dcos_agent_ad2_count、dcos_agent_ad3_count:  各アベイラビリティ・ドメインにおけるエージェント・ノードの個数
      • dcos_public_agent_ad1_count、dcos_public_agent_ad2_count、dcos_public_agent_ad3_count:  各アベイラビリティ・ドメインにおけるパブリック・エージェント・ノードの個数
      • dcos_gpu_agent_ad1_count、dcos_gpu_agent_ad2_count、dcos_gpu_agent_ad3_count:  各アベイラビリティ・ドメインにおけるGPUエージェントの個数
  • 環境変数を設定
    . env-vars 
  • Terraformの初期化
    terraform init
  • 実際の実行前にTerraformの実行計画を確認
    terraform plan
  • DC/OSリソースをプロビジョニングし、DC/OSクラスタをOracle Cloud Infrastructureにセットアップ
    terraform apply
リソースのプロビジョニングが完了すると、Terraformテンプレートは以下のような出力を表示します。
Outputs:

master_private_ips = [
  xx.xx.xx.xx,
  xx.xx.xx.xx,
  xx.xx.xx.xx
]

master_public_ips = [
  xx.xx.xx.xx,
  xx.xx.xx.xx,
  xx.xx.xx.xx,
]

Notes:

エージェント、パブリックエージェント、およびGPUエージェントの各ノードのデプロイは、ブートストラップノードのデプロイによって変わりますが、Terraformモジュールを使えば、Terraform "resources" の依存関係で通常実施しているように、依存関係を明示的に設定する仕組みはありません。depends_onというキーワードは、Terraformモジュールでは機能しません。この問題を回避するために、変数を使用して暗黙の依存関係を使用します。
例えば、モジュール "dcos_agent_ad1"において、モジュール "dcos_bootstrap"の "dcos_bootstrap"インスタンスIDの生成に依存する変数 "dcos_bootstrap_instance_id"を定義します。
module  "dcos_agent_ad1" {
    source              = "./instances/agent"
    count               = "${var.dcos_agent_ad1_count}"
    availability_domain = "${lookup(data.oci_identity_availability_domains.ADs.availability_domains[0],"name")}"
    compartment_ocid    = "${var.compartment_ocid}"
    tenancy_ocid        = "${var.compartment_ocid}"
    dcos_cluster_name   = "${var.dcos_cluster_name}"
    image               = "${var.InstanceImageOCID[var.region]}"
    shape               = "${var.AgentInstanceShape}"
    subnet_id           = "${module.vcn.subnet_ad1_id}"
    ssh_public_key      = "${var.ssh_public_key}"
    ssh_private_key     = "${var.ssh_private_key}"
    display_name_prefix = "ad1"
    dcos_bootstrap_instance_id = "${module.dcos_bootstrap.instance_id}"
}

Access DC/OS Cluster

Once the DC/OSのデプロイが完了したら、DC/OSダッシュボードにhttp://<master_public_ip>/からアクセスできます。

Next Steps

入力変数を使用して、エージェント、パブリックエージェント、GPUエージェントの各ノードの数を拡大または縮小できます。たとえば、次のようにエージェントノードの数を増やすことができます。
terraform apply -var "dcos_agent_id1_count=xx"

Conclusion

Oracle Cloud Infrastructureは、DC/OSとそのサービスを実行するための高性能で柔軟な環境を提供します。このTerraform DC/OSインストーラを使用すると、OCI上へのDC/OSクラスタのデプロイを自動化できます。

[Cloud] Announcing Terraform support for Oracle Cloud Platform Services

原文はこちら。
https://blogs.oracle.com/developers/announcing-terraform-support-for-oracle-cloud-platform-services

OracleとHashiCorpは、Oracle Cloud Platform Terraformプロバイダがご利用いただけるようになったことを発表します。
Oracle Cloud Platform Terraform Provider
https://www.terraform.io/docs/providers/oraclepaas
The initial release of the Oracle Cloud Platform Terraform providerの初期リリースでは、Oracle Database Cloud ServiceとOracle Java Cloud Serviceインスタンスの作成ならびにライフサイクル管理をサポートします。
Oracle Database Cloud Service
https://cloud.oracle.com/ja_JP/database/enterprise/features
Oracle Java Cloud Service
https://cloud.oracle.com/ja_JP/java
Oracle Cloud Platformのサポートにより、Terraformのinfrastructure-as-code構成をスタンドアロンOracle PaaSの展開のために定義したり、完全なインフラストラクチャおよびアプリケーションのデプロイのために、OPCプロバイダやOCIプロバイダがサポートするOracle Cloud InfrastructureおよびInfrastructure Classicと組み合わせることができます。

Supported PaaS Services

初期段階では、Oracle Cloud Platform (PaaS) Terraformプロバイダは以下のOracle Cloud Platformサービスをサポートしています。今後サービスやリソースを追加拡充していく予定です。
  • Oracle Database Cloud Service Instances
  • Oracle Database Cloud Service Access Rules
  • Oracle Java Cloud Service Instances
  • Oracle Java Service Access Rules

Using the Oracle Cloud Platform Terraform provider

Terraformを使用してOracle Cloud Platformサービスをプロビジョニングする例として、1個のJava Cloud Serviceインスタンスと依存関係にあるDatabase Cloud Serviceのインスタンスを展開する例をご紹介します。
まず、プロバイダの定義を宣言し、アカウント資格情報と適切なサービスREST APIエンドポイントを設定します。アイデンティティ・ドメイン名、アイデンティティ・サービスIDおよびRESTエンドポイントURLは、マイ・サービス・ダッシュボードの「サービスの詳細」セクションにあります。
My Services Dashboard
https://myservices.us.oraclecloud.com/mycloud/cloudportal/dashboard
IDCS Cloudアカウントの場合、identity_domainには、アイデンティティ・サービスIDを使います。
provider "oraclepaas" {
  user              = "example@user.com"
  password          = "Pa55_Word"
  identity_domain   = "idcs-5bb188b5460045f3943c57b783db7ffa"  
  database_endpoint = "https://dbaas.oraclecloud.com"
  java_endpoint     = "https://jaas.oraclecloud.com"
}
Traditionalアカウントの場合、identity_domainにはアイデンティティドメイン名を使います。
provider "oraclepaas" {
  user              = "example@user.com"
  password          = "Pa55_Word"
  identity_domain   = "mydomain"
  database_endpoint = "https://dbaas.oraclecloud.com"
  java_endpoint     = "https://jaas.oraclecloud.com"
}

Database Service Instance configuration

oraclepaas_database_service_instanceリソースを使って、Oracle Database Cloud Serviceインスタンスを定義します。単一のテラフォーム・データベース・サービス・リソース定義で、単一インスタンスのOracle Database Standard Editionデプロイメントから、高可用性と災害復旧のためのRACおよびData Guardを備えた完全なマルチノードのOracle Database Enterprise Editionまでの構成を表現できます。
別のDatabase Serviceインスタンスのバックアップまたはスナップショットからインスタンスを作成することもできます(訳注:原文では Instances can also be created for backups or snapshots... と記載されていますが、このforはおそらくfromの間違いと思われます。そのためfromに読み替えています)。この例では、後で構成するJava Cloud Serviceで使用するための新しいシングルインスタンスのデータベースを作成します。
resource "oraclepaas_database_service_instance" "database" {
  name        = "my-terraformed-database"
  description = "Created by Terraform"

  edition           = "EE"
  version           = "12.2.0.1"    
  subscription_type = "HOURLY"
  shape             = "oc1m"

  ssh_public_key = "${file("~/.ssh/id_rsa.pub")}"

  database_configuration {
    admin_password     = "Pa55_Word"
    backup_destination = "BOTH"
    sid                = "ORCL"
    usable_storage     = 25
  }

  backups {
    cloud_storage_container = "Storage-${var.domain}/my-terraformed-database-backup"
    cloud_storage_username  = "${var.user}"
    cloud_storage_password  = "${var.password}"
    create_if_missing       = true
  }
}
構成設定を少々詳しくみていきましょう。この例では、これがoc1m(1 OCPU/15GB RAM)シェイプのOracle Database 12cリリース2(12.2.0.1)Enterprise Editionインスタンスで、時間単位課金であることを宣言しています。
edition           = "EE"
version           = "12.2.0.1"    
subscription_type = "HOURLY"
shape             = "oc1m"
ssh_public_keyは、SSHアクセスを許可するためにインスタンスにプロビジョニングされる公開鍵です。

database_configurationブロックは、データベースSID、初期パスワード、およびデータベースの初期使用可能ブロックボリューム記憶域を含む、Database Cloud Serviceで作成される実際のデータベースインスタンスの初期設定を設定します。
database_configuration {
  admin_password     = "Pa55_Word"
  backup_destination = "BOTH"
  sid                = "ORCL"
  usable_storage     = 25
}
backup_destinationは、バックアップ先(Object Storage Servive(OSS)、オブジェクトストレージとローカルストレージの両方(BOTH)、または無効(NONE))を設定します。Java Cloud Serviceインスタンスと組み合わせて使用するデータベースインスタンスには、OSSまたはBOTHのバックアップ先が必要です。
Object Storage Serviceの場所とアクセス資格情報は、backupsブロックで設定します。
backups {
  cloud_storage_container = "Storage-${var.domain}/my-terraformed-database-backup"
  cloud_storage_username  = "${var.user}"
  cloud_storage_password  = "${var.password}"
  create_if_missing       = true
}

Java Cloud Service Instance

oraclepaas_java_service_instanceリソースを使って、Oracle Java Cloud Serviceインスタンスを定義します。1つのTerraformリソース定義で、Oracle WebLogic Serverの単一インスタンスのデプロイメントから、Oracle CoherenceデータグリッドクラスタおよびOracle Traffic Directorロードバランサを使用する完全なマルチノードOracle WebLogicクラスタまでの構成を表現できます。
別のJava Cloud Serviceインスタンスのスナップショットからインスタンスを作成することもできます。この例では、新たに2ノードのWebLogic Serverクラスタ(ロードバランサ付き)を作成し、先ほど作成したDatabase Cloud Serviceインスタンスに関連付けます。
resource "oraclepaas_java_service_instance" "jcs" {
  name        = "my-terraformed-java-service"
  description = "Created by Terraform"

  edition              = "EE"
  service_version      = "12cRelease212"
  metering_frequency   = "HOURLY"
  enable_admin_console = true

  ssh_public_key = "${file("~/.ssh/id_rsa.pub")}"

  weblogic_server {
    shape = "oc1m"

    managed_servers {
      server_count = 2
    }    

    admin {
      username = "weblogic"
      password = "Weblogic_1"
    }

    database {
      name     = "${oraclepaas_database_service_instance.database.name}"
      username = "sys"
      password = "${oraclepaas_database_service_instance.database.database_configuration.0.admin_password}"
    }
  }

  oracle_traffic_director {
    shape = "oc1m"
    listener {
      port         = 8080
      secured_port = 8081
    }
  }

  backups {
    cloud_storage_container = "Storage-${var.domain}/my-terraformed-java-service-backup"
    auto_generate           = true
  }
}
細かくみていきましょう。ここでは、これが12c Release 2 (12.2.1.2) Enterprise Edition Java Cloud Serviceのインスタンスで、時間単位の課金ルールを利用すると宣言しています。
edition              = "EE"
  service_version      = "12cRelease212"
  metering_frequency   = "HOURLY"
ssh_public_keyは、ここでもSSHアクセスを許可するためにインスタンスにプロビジョニングされる公開鍵です。
weblogic_serverブロックでは、このJava Cloud ServiceインスタンスにデプロイされたWebLogic Serverインスタンスの構成の詳細を提供します。 weblogic_server定義は、インスタンス・シェイプを設定します。この場合、oc1m(1 OCPU/15GB RAM)です。
adminブロックでは、WebLogic Serverの管理者ユーザーと初期パスワードを設定します。
admin {
    username = "weblogic"
    password = "Weblogic_1"
  }
databaseブロックでは、すでに上で定義したDatabase ServiceインスタンスにWebLogic Serverを接続します。この例では、Database Cloud ServiceインスタンスとJava Cloud Serviceインスタンスが同じ構成で宣言されていると仮定しているので、データベース構成値を取得できます。
database {
    name     = "${oraclepaas_database_service_instance.database.name}"
    username = "sys"
    password = "${oraclepaas_database_service_instance.database.database_configuration.0.admin_password}"
  }
The oracle_traffic_director ブロックでは、ロードバランサを構成してトラフィックをWebLogic Serverの管理対象サーバインスタンスに流すようにします。
oracle_traffic_director {
    shape = "oc1m"
    listener {
      port         = 8080
      secured_port = 8081
    }
  }
デフォルトでは、ロードバランサはweblogic_serverブロックで定義された同じ管理者資格情報で設定されますが、必要に応じて異なる資格情報を設定することもできます。安全でないポートが設定されていない場合、secured_portだけが有効になります。

最後に、Database Cloud Serviceインスタンスの設定と同様に、backupsブロックで、Java Cloud ServiceインスタンスのバックアップのObject Storage Serviceの場所を設定します。
backups {
    cloud_storage_container = "Storage-${var.domain}/-backup"
    auto_generate           = true
  }

Provisioning

プロバイダとterraformプロジェクトで構成されたリソース定義(例えば、全てがmain.tfファイルに入っている)を使うと、上記構成の展開は簡単ですにプロバイダとリソース定義が設定されているので、上記の設定を展開するのは簡単です。
$ terraform init
$ terraform apply
terraform initコマンドは、oraclepaasプロバイダの最新バージョンを自動的に取得します。terraform applyコマンドでプロビジョニングを開始します。Database CloudおよびJava Cloudインスタンスの完全なプロビジョニングは長時間にわたることがあります。プロビジョニングインスタンスを削除するには、terraform destroyを使います。


Related Content

Terraform Provider for Oracle Cloud Platform
https://www.terraform.io/docs/providers/oraclepaas
Terraform Provider for Oracle Cloud Infrastructure
https://github.com/oracle/terraform-provider-oci
Terraform Provider for Oracle Cloud Infrastructure Classic
https://www.terraform.io/docs/providers/opc/

[Linux] Tracing Linux Networking with DTrace on Oracle Linux

原文はこちら
https://blogs.oracle.com/linuxkernel/tracing-linux-networking-with-dtrace-on-oracle-linux

Alan Maguireのこの記事では、DTraceを使用した一般的なネットワーク関連のシステムコールを調査方法を紹介します。DTraceは、ユーザーおよびカーネルプロセスを理解するための強力なトレースツールです。

私たちは、DTraceのOracle Linuxのネットワーキングに対するサポートは着実に追加されています。これらのプローブを使ってネットワークの動作をよりよく理解する方法を見ていきましょう。ネットワークスタックの動的トレースでどのようなサポートが利用できるかを簡単に見てみましょう。
しかし、詳細を知る前に、なぜDTraceを使うのがいいのでしょうか。ネットワークの領域で十分なツールがあるのではないでしょうか。私がDTraceを使用する理由は次のとおりです。
  • DTraceは実稼動環境で安全でありつつ、制約がありません。つまり、何かを見つけたいのであれば、通常はそれを行う方法があります。最も重要なのは、システムがパニックを起こさずに実行できることです。当然のことながら、その困難な部分が、これらの質問からDTraceが理解する問い合わせになっています。私は、次回以後のエントリでそうする方法についていくつかの有用なヒントを提供できると思っています。
  • DTraceを使用すると、複数のサブシステムにアクセスできます。例えば、以下のような情報を取得できます。
    • パケットを受信するときに割り込みをどれぐらい効率的に合体させているのか
    • どのロックがネットワーク受信パスでホットな状態なのか
    特にクラウド環境では、ネットワークの振る舞いから他のサブシステムや抽象に結びつけて全体像を作り上げることが不可欠です。人々は "ネットワーク"を責めたがりますが、DTraceを使用すると、コストが本当にどこで発生しているかを確認できます。

Socket layer: syscall provider - available since UEK2

他のオペレーティングシステムと同様に、syscallプロバイダも利用でき、ネットワーク関連のシステムコール(sendto、sendmsg、sendmmsg、recvfrom、recvmsg、recvmmsg)をトレースできます。
以下は、実行可能な単位で送信されるバイトトレースの簡単な例です。情報を収集したら、Ctrl+Cキーを押します。
# dtrace -n 'syscall::sendto:entry { @c[execname] = sum(arg2); }'
dtrace: description 'syscall::sendto:entry ' matched 1 probe
^C
  
  DNS Resolver #6                                                  65
  ping                                                            192
  Socket Thread                                                  2006
  vpnagentd                                                      3872
これがDTraceのone-linerです。一つずつ見ていきましょう。
  • -nオプションは、DTraceスクリプトを使用するのではなく、プローブを直接指定していることを示しています(DTraceスクリプトを使用するには、 "dtrace -s <scriptname>"を使用します)。
  • プローブは4要素を記述し、各要素は ":"で区切ります。最初の要素は、私たちが使用しているDTraceサブシステムのプロバイダです。今回の場合、syscall(システムコール)です。もう1つはモジュールです。これは他のDTraceプロバイダには関係しますが、ここでは使用できません(Linuxでは常に "vmlinux"ですので空白にしておきます)。 3番目は関数です - システムコールプロバイダの場合はシステムコール名です。最後にプローブ名です。システムコールごとに、システムコールの要求/完了に対応するエントリとリターンの2つのプローブがあります。
  • 次は、中括弧に含まれるアクションです。DTraceコードは、"probe/predicate/{action}"の形式をとります。この場合、述語はありませんが、もし述語がある場合、ボディが実行されたか否かを判断します。続いてアクションを説明します。
  • ここでは、集計変数 "c"を使用しています。集計は "@"記号で表されています。アグリゲーションでは、角括弧の間に複数のキーを指定でき、sum()、count()、avg()などのいずれかの集計関数を使用して、さまざまなキーセットに関連付けられた値を計算します。アグリゲーションは効率的にカーネル内で収集されます。この例では、sendto()の3個目の引数であるarg2のSummationを取得しています。マニュアルを見ればarg2のサイズがわかります。
まとめると、one-linerでは「システムコールsendto()経由で送信されたバイト数の合計を表示し、各プログラム名での合計を収集」しています(execnameは組み込み済みの変数で、現在のプロセス実行可能ファイル名を表す)。
もちろん、これらはリクエストであり、失敗するものもあります。 再度使用したプローブはsyscall::sendto:entryでした。対応するsyscall::sendto:returnもあります。DTraceの一般的なパターンは、:entryから:returnまでの時間を測定します。

Layer 4 (Transport layer): TCP, UDP providers - available since UEK4QU5

Linuxの場合(Solarisでも同様です)、TCPやUDPのトランスポートレベル・プロバイダがあります。これらは送受信イベントをトレースし、TCPについてはTCPステートマシン遷移と接続確立マイルストンもトレースします。
# dtrace -l -P udp
   ID   PROVIDER            MODULE                          FUNCTION NAME
 1836        udp           vmlinux                      udp_send_skb send
 1838        udp           vmlinux                       udp_recvmsg receive
 1840        udp           vmlinux                 udp_queue_rcv_skb receive
 1868        udp           vmlinux                   udp_v6_send_skb send
 1869        udp           vmlinux                     udpv6_recvmsg receive
 1871        udp           vmlinux               udpv6_queue_rcv_skb receive
  
# dtrace -l -P tcp
   ID   PROVIDER            MODULE                          FUNCTION NAME
 1818        tcp           vmlinux                     tcp_set_state state-change
 1819        tcp           vmlinux                  tcp_conn_request state-change
 1820        tcp           vmlinux                tcp_finish_connect connect-established
 1821        tcp           vmlinux             tcp_rcv_state_process accept-established
 1822        tcp           vmlinux             tcp_rcv_state_process connect-refused
 1823        tcp           vmlinux                  tcp_transmit_skb send
 1824        tcp           vmlinux                  tcp_transmit_skb connect-request
 1825        tcp           vmlinux                       tcp_connect state-change
 1826        tcp           vmlinux                   tcp_v4_send_ack send
 1827        tcp           vmlinux                 tcp_v4_send_reset send
 1828        tcp           vmlinux                 tcp_v4_send_reset accept-refused
 1829        tcp           vmlinux                tcp_v4_send_synack send
 1830        tcp           vmlinux                        tcp_v4_rcv receive
 1831        tcp           vmlinux                     tcp_time_wait state-change
 1882        tcp           vmlinux              tcp_v6_send_response send
 1883        tcp           vmlinux              tcp_v6_send_response accept-refused
 1884        tcp           vmlinux                tcp_v6_send_synack send
 1885        tcp           vmlinux                        tcp_v6_rcv receive
以下は、どのシステム(リモートIP)への接続を拒否しているのか、どのポートに接続しようとしているのか、という例です。
# dtrace -n 'tcp:::accept-refused { @c[args[2]->ip_daddr, args[4]->tcp_sport] = count(); }'
dtrace: description 'tcp:::accept-refused ' matched 2 probes
^C
  
  127.0.0.1                                              7                1
この例を生成するために、別のウィンドウでポート7に対しローカルにtelnetで接続しました。ポート7は閉じられているため、1つの接続が拒否されています。TCP、UDP、およびIPプロバイダーはすべて静的定義トレース(SDT)プロバイダーです。これらの考え方は、絶えず変化する機能のエントリやリターンに位置するプローブを作成して変化するデータ構造から情報を収集しようとするのではなく、関心のあるイベントや、これらのイベントが発生するコードの各ポイントを定義して、静的プローブを配置します。たとえば、tcp:::sendプローブがtcp_v4_send_reset、tcp_v4_send_ackなどにあることがわかります。重要なのは、これらのプローブは、OS固有の構造をとり、DTraceコンシューマが信頼できる安定した引数に変換する安定したトランスレータを定義します。 Oracle Linuxの関連する定義を参照するには、/usr/lib64/dtrace/4.1/tcp.d、udp.d、ip.dを参照してください。

ほとんどの場合、Solarisとの互換性は維持されています、本当に必要なのが見つからない場合はお知らせください。様々な引数がどのように見えるかご紹介しましょう。arg0ではなくargs[0]を使って、安定した、変換済み引数へアクセスしようとしていることをDTraceに知らせています。素の引数はarg0、arg1などを使って引き続き利用できます。
args[0] - pktinfo_t * [packet information]
args[1] - csinfo_t * [ connection information]
args[2] - ipinfo_t * [IP protocol information]
args[3] - tcpsinfo_t * for TCP, udpsinfo_t * for UDP [TCP/UDP state information]
args[4] - tcpinfo_t * for TCP, udpinfo_t * for UDP [TCP/UDP header information]

Layer 3 (IP provider) - available since UEK4QU4


IPプロバイダは送信、受信、インバウンド/アウトバウンドのパケットドロップをトレースします。
 # dtrace -l -P ip
   ID   PROVIDER            MODULE                          FUNCTION NAME
 1839         ip           vmlinux                     ip_rcv_finish drop-in
 1840         ip           vmlinux                  ip_local_deliver receive
 1841         ip           vmlinux                            ip_rcv drop-in
 1842         ip           vmlinux                  __ip_append_data drop-out
 1843         ip           vmlinux                 __ip_local_out_sk send
 1844         ip           vmlinux                    ip_append_page drop-out
 1845         ip           vmlinux                       ip_send_skb drop-out
 1861         ip           vmlinux                       raw_sendmsg send
 1878         ip           vmlinux        __ip6_flush_pending_frames drop-out
 1879         ip           vmlinux                          ip6_xmit send
 1880         ip           vmlinux                          ip6_xmit drop-out
 1881         ip           vmlinux                ip6_finish_output2 drop-out
 1882         ip           vmlinux                 __ip6_append_data drop-out
 1883         ip           vmlinux                       ip6_forward drop-out
 1884         ip           vmlinux                        ip6_output drop-out
 1885         ip           vmlinux                      ip6_send_skb drop-out
 1886         ip           vmlinux                  ip6_input_finish drop-in
 1887         ip           vmlinux                          ipv6_rcv drop-in
 1888         ip           vmlinux                         ip6_input receive
 1895         ip           vmlinux                    ndisc_send_skb send
 1900         ip           vmlinux                     rawv6_sendmsg send
 1903         ip           vmlinux                      mld_sendpack send
 1904         ip           vmlinux                      mld_sendpack drop-out
 1905         ip           vmlinux                        igmp6_send send
 1906         ip           vmlinux                        igmp6_send drop-out
 1923         ip           vmlinux                __ip6_local_out_sk send
IPプロバイダにおける引数は以下のようです。
args[0] - pktinfo_t * [packet information]
args[1] - csinfo_t * [connection information]
args[2] - ipinfo_t * [IP protocol information]
args[3] - ifinfo_t * [IP interface info]
args[4] - ipv4info_t * [IPv6 header info if IPv6 packet]
args[5] - ipv6info_t * [IPv6 header info if IPv6 packet]

Other

Oracle LinuxのDTraceには、perfイベントをトレースするperfプロバイダが含まれています。もちろん、関数境界トレース(fbt)も利用できます。以下は、関数境界トレースを使用してソケットバッファ(struct sk_buff)の割り当てサイズを取得する例です。sk_buffはネットワークデータのキー構造です。ここでは、2のべき乗のバケット(0-1、1-2、2-4など)に入る個数を調べています。これはquantize()という集約アクションです。例えば、大多数が2048〜4096の範囲にあったことがわかります。
# dtrace -n 'fbt::__alloc_skb:entry { @size = quantize(arg0); }'
dtrace: description 'fbt::__alloc_skb:entry ' matched 1 probe
^C
           value  ------------- Distribution ------------- count   
              -1 |                                         0       
               0 |                                         80      
               1 |                                         3       
               2 |                                         0       
               4 |                                         137     
               8 |                                         988     
              16 |@@                                       5719    
              32 |@@@@@                                    10977   
              64 |                                         779     
             128 |@@@                                      6805    
             256 |@@@@@@@@@@@                              25462   
             512 |                                         508     
            1024 |@@                                       5108    
            2048 |@@@@@@@@@@@@@@@@                         39011   
            4096 |                                         8       
            8192 |                                         0       
           16384 |                                         16      
           32768 |                                         0
将来のエントリで、fbtプロバイダやperfプロバイダを使った例を説明する予定にしています。

[Java] Style Guidelines for Local Variable Type Inference in Java

原文はこちら。
http://openjdk.java.net/projects/amber/LVTIstyle.html

注意:2018/03/25(JST)時点の内容です。

Introduction

Java SE 10では、ローカル変数の型推論が導入されました。以前は、すべてのローカル変数宣言では、左側に明示的な(マニフェスト)型が必要でした。型推論では、明示的な型を、イニシャライザ(初期化子)を持つローカル変数宣言の予約型の名前 var に置き換えることができます。変数の型は、イニシャライザの型から推測されます。

この機能には様々な論争があり、一方ではこの機能が可能にする簡潔性を歓迎する声があるのに対し、他方では、コードを読む人にとって重要な型情報が奪われ、読みやすさが損なわれる恐れがある、という声もあります。いずれのグループの声も間違ってはいません。冗長な情報を排除してコードをより読みやすくすることもできれば、有益な情報を逃すことでコードを読みにくくすることもできます。他には、 var を過度に使用した結果、より悪いJavaコードが書かれることを懸念するグループもいます。これも正しい指摘ではありますが、より良いJavaコードが書かれる可能性もあります。すべての機能と同様に、判断して使用する必要があります。いつ利用すべき、べからずの一般規則はありません。

ローカル変数宣言は単独では存在しません。 周囲のコードによって、 var を使用した場合の影響に影響が及んだり、圧倒されたりする可能性があります。 このドキュメントの目的は、周囲のコードが var 宣言に与える影響を調べ、トレードオフを説明し、 var を効果的に使用するためのガイドラインを提供することです。

Principles

P1. Reading code is more important than writing code.

コードは書かれるより読まれることのほうがずっと多く、さらに、コードを書くとき、私たちは通常、頭の中には全体のコンテキストがあり、時間を掛けますが、コードを読んでいるときには、コンテキスト・スイッチが頻繁に行われ、もっと急いでいる可能性があります。特定の言語機能が使用されているかどうかは、元のコード記述者ではなく、プログラム読者に与える影響によって決定されるべきです。プログラムが短ければ短いほうが望ましいかもしれませんが、短くするとプログラムを理解するのに役立つ情報が省略される可能性があります。ここでの中心的な問題は、わかりやすさを最大化するようにプログラムの適切なサイズを見つけることです。

特にここでは、プログラムの入力や編集に必要なキーボードを叩く量には関心がありません。簡潔さはコード記述者にとっては素晴らしいボーナスになるかもしれませんが、それに注力すると、結果として得られるプログラムのわかりやすさを向上させるという、主要な目的を失ってしまいます。

P2. Code should be clear from local reasoning.

コードの読者は、宣言された変数の利用とともに var の宣言を見て、何が起きているのかをすぐに理解できるはずです。理想的には、スニペットまたはパッチのコンテキストのみを使用して、コードを容易に理解できるようにする必要があります。 var 宣言を理解するためにコードの周りのいくつかの場所を見る必要がある場合は、 var を使うには良い状況ではないかもしれません。そして再度申し上げますが、コード自体に問題がある可能性があります。

P3. Code readability shouldn't depend on IDEs.

IDEでコードを読み書きすることが多いため、IDEのコード解析機能に大きく依存したくなります。型宣言は、型を決める変数を常に指し示すことができるので、どこでも var を使うだけでいいのではないでしょうか。

2つの理由があります。1個目の理由は、コードはIDEの外で読み込まれることが多いということです。コードは、IDE機能が利用できない多くの場所、例えばドキュメント内のスニペット、インターネット上のリポジトリの参照、またはパッチファイルに現れます。コードが何をするのかを理解するためだけに、コードをIDEにインポートする必要があるのは非生産的です。

もう一つの理由は、IDE内でコードを読み込んでいるときでも、変数に関する詳細情報をIDEに問い合わせるために明示的なアクションが必要な場合が多いということです。例えば、 var を使って宣言された変数の型を問い合わせるために、変数上にポインタを置いてポップアップを待たなければならないかもしれません。これはほんの一瞬しか時間がかからないかもしれませんが、コードリーディングの流れを妨害します。

コードは自明でなければなりません。ツールの助けを必要とせずに、その正面から理解できる必要があります。

P4. Explicit types are a tradeoff.

歴史的に、Javaでは、型を明示的に含めるためにローカル変数の宣言が必要でした。明示的な型は非常に役立つことがありますが、時にはそれほど重要ではないこともあり、時には邪魔になることがあります。明示的な型を必要とすると、有用な情報に押し寄せるノイズを増やす可能性があります。

明示的な型を省略すると、ノイズを減少できますが、それは省略してもわかりやすさが損なわれない場合に限ります。型はコードリーダーに情報を伝える唯一の方法ではありません。 他の手段には、変数の名前とイニシャライザ式があります。これらのチャンネルの1つをミュートしても問題ないかどうかを判断するには、使用可能なすべてのチャンネルを考慮する必要があります。

Guidelines

G1. Choose variable names that provide useful information.

これは一般的には良い方法ですが、 var の文脈ではもっと重要です。  var 宣言では、変数の意味と使用に関する情報を変数の名前を使って伝えることができます。明示的な型を var に置き換えるには、変数名を改善する必要があります。 例えば以下のような具合です。
// ORIGINAL
List<Customer> x = dbconn.executeQuery(query);

// GOOD
var custList = dbconn.executeQuery(query);
この例では、役に立たない変数名を、変数の型をイメージできる名前に置き換えました。変数名は、var宣言で暗黙的に記述されています。

変数の型をその名前に記号化して、論理的な結論に達すると、ハンガリアン記法(Hungarian Notation)になります。 明示的な型と同様に、これは時として役に立つこともあれば、混乱することもあります。 この例では、 custList という名前は、 List を返すことを暗示していますが、重要ではないかもしれません。 厳密な型の代わりに、変数名が「顧客(customers)」のよう変数の役目や性質を表現するほうが良い場合もあります。
// ORIGINAL
try (Stream<Customer> result = dbconn.executeQuery(query)) {
    return result.map(...)
                 .filter(...)
                 .findAny();
}

// GOOD
try (var customers = dbconn.executeQuery(query)) {
    return customers.map(...)
                    .filter(...)
                    .findAny();
}

G2. Minimize the scope of local variables.

ローカル変数のスコープを制限することは一般的には良い方法です。この方法は、Effective Java(第3版)のItem 57に記述されています。 var を使う場合は余分な力を加えて適用します。

次の例では、addメソッドが特別な項目を最後のリスト要素として明示的に追加するので、期待通り最後に処理されます。
var items = new ArrayList<Item>(...);
items.add(MUST_BE_PROCESSED_LAST);
for (var item : items) ...
今度は、重複した項目を削除するために、プログラマーがこのコードを修正して、 ArrayList の代わりに HashSet を使用することにします。
var items = new HashSet<Item>(...);
items.add(MUST_BE_PROCESSED_LAST);
for (var item : items) ...
このコードにはバグがあります。Setには定義済みの反復順序がないためです。 しかし、プログラマーは items 変数の使用が宣言に隣接しているので、すぐにこのバグを修正する可能性があります。

ここで、このコードが items 変数の大きなスコープを持つ大きなメソッドの一部であるとします。
var items = new HashSet<Item>(...);

// ... 100 lines of code ...

items.add(MUST_BE_PROCESSED_LAST);
for (var item : items) ...
ArrayListからHashSetへの変更の影響は、 items が宣言から遠く離れて使用されるため、もはやわかりづらくなっているため、このバグがずっと長く生き残る可能性があります。

 items が  List<String> として明示的に宣言されている場合は、イニシャライザを変更すれば、型も Set<String> に変更する必要があります。これにより、プログラマは、メソッドの残りの部分を調べて、そのような変更の影響を受けるコードを調べることができます(そして再度、そうならない場合もあります)。  var を使うとこの教唆がなくなるため、このようなコードでバグが導入される危険性が増す可能性があります。

これは var を使用していることに対する議論のように思えるかもしれませんが、実際はそうではありません。 var を使用する最初の例は全く問題ありません。この問題は、変数のスコープが大きい場合にのみ発生します。このような場合に単に var を避けるのではなく、ローカル変数のスコープを狭めるようにコードを変更すべきで、その後に var で宣言するだけです。

G3. Consider var when the initializer provides sufficient information to the reader.

ローカル変数はコンストラクタで初期化されることが多く、コンストラクトされたクラスの名前は左側で明示的な型として頻繁に繰り返されます。型の名前が長い場合、 var を使用して情報を失わずに簡潔にすることができます。
// ORIGINAL
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

// GOOD
var outputStream = new ByteArrayOutputStream();
また、イニシャライザがコンストラクタではなく静的なファクトリメソッドなどのメソッド呼び出しである場合、そしてその名前に十分に型情報が含まれる場合にも、合理的な var の利用と言えるでしょう。
// ORIGINAL
BufferedReader reader = Files.newBufferedReader(...);
List<String> stringList = List.of("a", "b", "c");

// GOOD
var reader = Files.newBufferedReader(...);
var stringList = List.of("a", "b", "c");
これらのケースでは、メソッド名が特定の戻り値の型を強く示唆しているため、変数の型推論に利用されます。

G4. Use var to break up chained or nested expressions with local variables.

文字列のコレクションを取り、最もよく発生する文字列を発見するというコードを考えてみましょう。以下のような感じです。
return strings.stream()
              .collect(groupingBy(s -> s, counting()))
              .entrySet()
              .stream()
              .max(Map.Entry.comparingByValue())
              .map(Map.Entry::getKey);
このコードは正しいですが、単一のストリームパイプラインのように見えるため、混乱を招く可能性があります。実際、それは短いストリームであり、第1のストリームの結果に対する第2のストリーム、続いて第2のストリームの Optional の結果のマッピングが続きます。最も読みやすいこのコードの表現は、2、3行のステートメントでしょう。最初にグループエントリをマップにいれ、続いてそのMapを縮小した後に、(存在する場合は)結果からキーを取り出します。以下のような感じです。
Map<String, Long> freqMap = strings.stream()
                                   .collect(groupingBy(s -> s, counting()));
Optional<Map.Entry<String, Long>> maxEntryOpt = freqMap.entrySet()
                                                       .stream()
                                                       .max(Map.Entry.comparingByValue());
return maxEntryOpt.map(Map.Entry::getKey);
しかし、中間変数の型を書くことはあまりにも負担に思えるので、コード記述者はそうすることをやめて、そのかわりにコントロール・フローを歪めたのです。 var を使うと、高コストな中間変数の型の明示的な宣言をせずに、より自然にコードを表現できます。
var freqMap = strings.stream()
                     .collect(groupingBy(s -> s, counting()));
var maxEntryOpt = freqMap.entrySet()
                         .stream()
                         .max(Map.Entry.comparingByValue());
return maxEntryOpt.map(Map.Entry::getKey);
最初のスニペットは、メソッド呼出しの1つの長いチェーンで正当で好まれるかもしれませんが、長いメソッドチェーンを分割する方がよい場合もあります。これらのケースでの var の使用は実行可能なアプローチですが、2番目のスニペットで中間変数の完全な宣言を使用すると、それは合理性の欠ける選択肢になります。 他の多くの状況と同様に、 var を正しく使用するには、何かを取り除く(明示的な型)と何かを追加する(より良い変数名、コードのより良い構造化)の両方が必要かもしれません。

G5. Don't worry too much about "programming to the interface" with local variables.

Javaプログラミングの一般的なイディオムは、具象型のインスタンスを構築し、それをインタフェース型の変数に割り当てることです。これは、コードを実装(implementation)の代わりに抽象(abstraction)に結びつけるため、将来コードを保守する際の柔軟性が保持されます。
// ORIGINAL
List<String> list = new ArrayList<>();
しかし、 var を使うと、インターフェースではなく具象型を推論します。
// Inferred type of list is ArrayList<String>.
var list = new ArrayList<String>();
ここで、 var はローカル変数に対してのみ使用できることを再考する必要があります。 var はフィールド型、メソッドパラメータ型、およびメソッド戻り値の型を推測するために使用できません。「インターフェイスに対するプログラミング」の原則は、これまでのコンテキストと同じくらい重要です。

主な問題は、変数を使用するコードが具体的な実装に依存する可能性があることです。変数のイニシャライザが将来変更された場合、推測される型が変更され、結果としてその変数を使用する後続のコードでエラーやバグが発生する可能性があります。

ガイドラインG2で推奨されているように、ローカル変数のスコープが小さい場合、後続コードに影響を与える可能性がある具体的な実装の「漏れ」によるリスクは限定的です。変数が数行離れたコードでのみ使用されている場合は、問題を回避したり、問題発生時に問題を緩和したりするのは簡単です。

この特定のケースでは、 List にはない2つのメソッド、つまり ensureCapacity と trimToSize  が ArrayList にのみ含まれています。これらのメソッドはリストの内容には影響しません。したがって、それらのメソッドの呼び出しはプログラムの正確さに影響しません。これは、インタフェースではなく、具体的な実装である推論型の影響をさらに減らします。

G6. Take care when using var with diamond or generic methods.

 var とダイアモンド演算子の両方の機能を使用すると、既に存在する情報から派生可能な場合に、明示的な型情報を省略できます。では、同じ宣言で両方とも使用できるのでしょうか?

以下の例を考えてみましょう。
PriorityQueue<Item> itemQueue = new PriorityQueue<Item>();
これをダイアモンド演算子や var を使って型情報を失わずに書き直すことができます。
// OK: both declare variables of type PriorityQueue<Item>
PriorityQueue<Item> itemQueue = new PriorityQueue<>();
var itemQueue = new PriorityQueue<Item>();
 var とダイアモンド演算子を使うことは問題ありませんが、推論される型は変わります。
// DANGEROUS: infers as PriorityQueue<Object>
var itemQueue = new PriorityQueue<>();
この推論のために、ダイアモンド演算子はターゲット型(通常は宣言の左側)やコンストラクタの引数の型を利用できます。いずれも存在しない場合、最も広く適用可能な型、通常は Object にフォールバックします。これは通常意図したものではありません。

ジェネリックメソッドは型推論を採用しているので、プログラマが明示的な型引数を提供することはほとんどありません。十分な型情報を提供する実際のメソッド引数がない場合、ジェネリックメソッドの推論はターゲットの型に依存します。 var 宣言では、ターゲットの型がないため、ダイヤモンド演算子の場合と同様の問題が発生する可能性があります。
// DANGEROUS: infers as List<Object>
var list = List.of();
ダイヤモンド演算子とジェネリックメソッドの両方を使えば、コンストラクタまたはメソッドへの実際の引数が追加の型情報を提供しているため、意図された型を推論できます。
// OK: itemQueue infers as PriorityQueue<String>
Comparator<String> comp = ... ;
var itemQueue = new PriorityQueue<>(comp);

// OK: infers as List<BigInteger>
var list = List.of(BigInteger.ZERO);
ダイヤモンド演算子やジェネリックメソッドと共に var を使用する場合は、推論された型があなたの意図と一致するように、メソッドまたはコンストラクタの引数が型情報を十分に提供するようにする必要があります。そうできない場合には、同一宣言で var とダイアモンド演算子もしくはジェネリックメソッド両方を使わないでください。

G7. Take care when using var with literals.

プリミティブなリテラルは、 var 宣言のイニシャライザとして使用できます。これらのケースでは var を使用すると、型名が一般に不足するため、大きな利点が得られるとは考えにくいのですが、変数名を整列するなど、 var が有用な場合があります。

boolean、character、 long 、およびstringリテラルに問題はありません。 これらのリテラルから推論される型は正確なので、 var の意味は明白です。
// ORIGINAL
boolean ready = true;
char ch = '\ufffd';
long sum = 0L;
String label = "wombat";

// GOOD
var ready = true;
var ch    = '\ufffd';
var sum   = 0L;
var label = "wombat";
イニシャライザが数値、特に整数リテラルの場合、とりわけ注意が必要です。左側に明示的な型がある場合、数値は暗黙的に int 以外の型に拡大または縮小されます。 var を使用すると、値は意図せずに int として推測されることがあります。
// ORIGINAL
byte flags = 0;
short mask = 0x7fff;
long base = 17;

// DANGEROUS: all infer as int
var flags = 0;
var mask = 0x7fff;
var base = 17;
小数点リテラルはほとんどの場合明確です。
// ORIGINAL
float f = 1.0f;
double d = 2.0;

// GOOD
var f = 1.0f;
var d = 2.0;
 float (浮動小数点)リテラルは、暗黙のうちに double に広げる場合があることの注意してください。 3.0f のような明示的なfloatリテラルを使用して double 変数を初期化するのはやや気が利きませんが、 double 変数が float フィールドから初期化される場合があります。ここで var に関する注意をアドバイスします。
// ORIGINAL
static final float INITIAL = 3.0f;
...
double temp = INITIAL;

// DANGEROUS: now infers as float
var temp = INITIAL;
(実際には、この例はガイドラインG3に違反しています。なぜなら、コードの読者が推論された型を見るために十分な情報がイニシャライザにないからです。)

Examples

このセクションでは、 var を使えば最大のメリットを得られる場所の例をご紹介します。

次のコードは、多くとも max 個の一致するエントリをMapから削除します。メソッドの柔軟性を向上させるためにワイルドカード型の境界を使用しているため、結果としてかなりの冗長性が生じます。残念ながら、これはイテレータ(Iterator)の型がネストされたワイルドカードでなければならず、そのため宣言がより冗長になっています。この宣言は長すぎるため、forループのヘッダーが1行に収まらなくなり、コードが読みにくくなっています。
// ORIGINAL
void removeMatches(Map<? extends String, ? extends Number> map, int max) {
    for (Iterator<? extends Map.Entry<? extends String, ? extends Number>> iterator =
             map.entrySet().iterator(); iterator.hasNext();) {
        Map.Entry<? extends String, ? extends Number> entry = iterator.next();
        if (max > 0 && matches(entry)) {
            iterator.remove();
            max--;
        }
    }
}
ここで var を使うと、ローカル変数のノイジーな型宣言が減ります。この種のループでは、IteratorおよびMap.Entryのローカルの明示的な型を持つ必要はほとんどありません。これにより、forループ制御を1行に収めることができ、はるかに読みやすくなります。
// GOOD
void removeMatches(Map<? extends String, ? extends Number> map, int max) {
    for (var iterator = map.entrySet().iterator(); iterator.hasNext();) {
        var entry = iterator.next();
        if (max > 0 && matches(entry)) {
            iterator.remove();
            max--;
        }
    }
}
try-with-resourcesを使って、ソケットから1行のテキストを読み取るコードを考えてみましょう。ネットワークおよびI/O APIはイディオムをラップしたオブジェクトを使用します。中間オブジェクトをそれぞれリソース変数として宣言して、後続のラッパーを開くときにエラーが発生したら適切にクローズしなければなりません。これを実現するためのこまでのコードであれば、変数宣言の左右でクラス名を繰り返す必要があり、結果として多くのノイズが発生しました。
// ORIGINAL
try (InputStream is = socket.getInputStream();
     InputStreamReader isr = new InputStreamReader(is, charsetName);
     BufferedReader buf = new BufferedReader(isr)) {
    return buf.readLine();
}
var の利用により、大幅にノイズを削減します。
// GOOD
try (var inputStream = socket.getInputStream();
     var reader = new InputStreamReader(inputStream, charsetName);
     var bufReader = new BufferedReader(reader)) {
    return bufReader.readLine();
}

Conclusion

宣言用途で var を利用すると、混乱が減ることでコードの品質が向上します。そのため、より重要な情報を際立たせることができます。対して、無差別に var を採用すると、状況が悪化する可能性があります。適切に var を利用すれば、よいコードを改善するのに役立ち、理解度を損なわずにコードをより短く、明確にできます。

References

JEP 286: Local-Variable Type Inference
http://openjdk.java.net/jeps/286
Wikipedia: Hungarian Notation
https://en.wikipedia.org/wiki/Hungarian_notation
Bloch, Joshua. Effective Java, 3rd Edition. Addison-Wesley Professional, 2018.
https://www.pearson.com/us/higher-education/program/Bloch-Effective-Java-3rd-Edition/PGM1763855.html

[Linux] btrfs Development: Year in Review

原文はこちら
https://blogs.oracle.com/linuxkernel/btrfs-development%3a-year-in-review

このbtrfs開発のアップデートはLiu Bo(Oracle Linux Kernel開発者であり、主要なアップストリームbtrfsコントリビュータ)によるものです。

btrfsコミュニティは引き続き繁栄しています。2017年、btrfsには富士通、Facebook、Oracle、SuSEの主要開発者といくつかのNAS企業の貢献がありました。btrfsの主な使用例は2つのカテゴリに分類されます、 すなわち、'/'と '/ home'のための1個のディスクでのbtrfsの利用と、NASタイプのワークロードのための複数のディスクでのbtrfsの利用です。

過去1年間で、btrfsを安定させることを最優先課題とし、 "btrfs: fix ..."で始まる117個のコミットがありますので、基本的に全ての領域でbtrfsを修正しています。

BTRFSの主な特長は以下の通りです。
  • Linux kernel v4.13
    新しい圧縮アルゴリズム 'zstd'がbtrfsに導入されました。これはlzoと同じくらい速く、zlibと同等の圧縮率を提供します。ベンチマークの詳細は「btrfs: Add zstd support」で入手できます。
    btrfs: Add zstd support
    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5c1aab1dd5445ed8bdcdbb575abc1b0d7ee5b2e7
  • Linux kernel v4.14
    圧縮ヒューリスティックサポートがbtrfsに導入されました。圧縮前にデータにいくつかのヒューリスティックを適用して、スペースを節約できるかどうかを判断できます。
  • Linux kernel v4.15
    内部の遅延参照に対するデバッグ機能を提供するため、新しいマウントオプションref-verifyと新しいconfig CONFIG_BTRFS_FS_REF_VERIFYが追加されました。
  • 将来的には、ホットスペア、DAXによる永続メモリのサポート、RAID 56ジャーナル(ライトホールを塞ぐため)、iomapインフラストラクチャへの変換の作業を継続する予定です。これらの作業すべてにはすでに少なくともRFCパッチがありますので、メーリングリストで上がっている懸念やフィードバックに対処するために、それらを改訂し改善する必要があります。
これらの特長に加え、不具合も修正してきました。
  • ENOSPC : チケット予約メカニズムをbtrfsが採用した後でさえも、初期のno spaceエラーが発見されており、改善のための修正が行われてきました。問題はほぼすべてがbtrfsファイルシステムでのみ発生します。この変更により、ファイルシステムのサイズが増えても全体のパフォーマンスが向上します。
  • send : btrfs sendは、インクリメンタルアップデートをサポートするためによく使われており、いくつかのNASソリューションに統合されていますが、rmdirを送信する際の誤った動作や、NO_HOLE機能とインライン・エクステントが協調する際のその他の不具合を発見し、修正しました。
  • (オフライン重複排除のための)backref巡回(backref walking): オフライン重複排除は、多数の共有エクステントを生成する可能性があります。これにより、複数のファイル(または同じファイル内でも)が共有されるかどうかをチェックする際にFIEMAPを使用するツールが遅くなることがあります。これらの変更により、メモリ内のbackrefは、リストではなくrb-treeに格納されるようになりました。これにより、挿入マージが可能になり、共有エクステントを簡単に発見し、backrefを挿入しながら即座に返すことができるようになりました。
  • raid6 とスクラブ(scrub) :  btrfsのマウントを妨げるraid6再構成プロセスにある不具合を確認しました。アップストリームとstableカーネルの両方で修正を提供済みです。さらに、コミュニティはraid6でのスクラブのサポートで不具合を見つけて修正しました。この不具合は、特定のデータストライプで誤ったパリティを引き起こす可能性があります。
上記に加えて、btrfs-progsをpythonライブラリ(libbtrfsutil)として書き換え、ライセンスをGPLからLGPLに変更するというbtrfs-progsへの変更提案もあります。このライセンスの変更により、単体テストやサードパーティのツールとの統合が容易になることでしょう。
これは、btrfsの多くの優れた機能のちょっとした例です。btrfsの現在の機能を引き続き改善していきます。

[Docker, WLS, Kubernetes] Announcing the Oracle WebLogic Server Kuberentes Operator

原文はこちら。
https://blogs.oracle.com/developers/announcing-oracle-weblogic-server-kuberentes-operator

Oracle WebLogic Server Kubernetes Operatorを発表でき非常にわくわくしています。これは、現在テクノロジープレビューとして入手可能で、オープンソースで提供されています。
Oracle Weblogic Server Kubernetes Operator
https://github.com/oracle/weblogic-kubernetes-operator
Operatorは、Kubernetes環境で実行されている任意の数のWebLogicドメインを管理できます。具体的には、ドメインの作成、ドメイン起動の自動化、手動(オンデマンド)、またはWebLogic Diagnostics FrameworkまたはPrometheusと統合したWebLogicクラスタのスケールアップ/ダウン、WebLogicクラスタにデプロイされたWebアプリケーションの負荷分散の管理、ElasticSearch、logstash、Kibanaとの統合が可能です。
Operatorは、標準のOracle WebLogic Server 12.2.1.3 Dockerイメージを使用します。このイメージはDocker StoreまたはOracle Container Registryにあります。Operatorはこのイメージが不変(immutable)であるとみなし、すべての状態はKubernetes永続ボリュームに保持されます。これにより、すべてのPodを使い捨て可能かつ置き換え可能なものとして扱うことができ、実行時にDockerコンテナに書き込まれた状態を管理する必要性が完全に排除されます(書き込まれるものが存在しないためです)。
以下の図は、Operatorを使用する場合のKubernetesのドメインのレイアウトの概要を示しています。

Operatorは、WebLogic Server管理コンソールを(必要であれば、たとえばWLST用に)外部ユーザに公開し、外部のT3アクセスを許可することもできます。 ドメインは互いに対話できるため、分散トランザクションなども可能です。すべてのPodにはKubernetesのlivenessプローブとreadinessプローブが設定されているため、Kubernetesは自動的に障害の発生したPodを再起動し、実際にユーザーの要求に対応できる管理対象サーバーのみをクラスタに含めることができます。
デザイン哲学とアーキテクチャ、Operatorの使い方、Operatorのビデオデモンストレーション、Operatorへのコントリビュートに関心のある人々向けの開発者ページなど、多くのドキュメントがGitHubのプロジェクトページに用意されています。テクノロジープレビューで遊んでいただければ幸いです。皆様のフィードバックをお待ちしております。

Getting Started

Oracle WebLogic Server Kubernetes Operator利用にあたっては以下の前提条件があります。
  • Kubernetes 1.7.5+, 1.8.0+ (kubectl versionで確認)
  • Flannel networking v0.9.1-amd64 (docker images | grep flannelで確認)
  • Docker 17.03.1.ce (docker versionで確認)
  • Oracle WebLogic Server 12.2.1.3.0
Kubernetes上でのWebLogic Serverの動作保証ならびにサポートについては、My Oracle Supportの以下のサポートドキュメントをご覧ください。
WebLogic Server 12.2.1.3 Certification on Kubernetes (Doc ID 2349228.1)
https://support.oracle.com/rs?type=doc&id=2349228.1
Operatorの動画は以下のURLからご覧いただけます。
  • Operatorのインストール手順とOperatorのREST APIの利用
  • 2個のWebLogicドメインを作成し、管理コンソールへのアクセスとKubernetesで作成された種々のリソース(services、ingresses、pods、ロードバランサなど)を確認
  • Webアプリケーションのデプロイ、Operatorを使ったWebLogicクラスタのスケール、負荷分散の確認
  • Kubernetesで実行中のドメインに対してWLSTを利用して、Kubernetes上で動作するOracle Databaseに接続するためのデータソースを作成
  • WLDF(WebLogic診断フレームワーク)を使ったWebLogicクラスタのスケール
  • Prometheusとの統合により、WebLogic ServerのメトリックをPrometheusにエクスポートし、スケールするためのトリガーとなるPrometheusのアラートを作成
Operatorのインストールと構成、およびOperatorを使ったWebLogicドメインの管理に使用する全体的なプロセスは、以下のステップで構成されています。提供されたスクリプトでこれらの手順のほとんどを実行できますが、一部手動で実行する必要があります。
  • Oracle Container Registryへのアクセス登録
  • Oracle Container Registryへアクセスするためのシークレットの設定
  • Operatorのパラメータ・ファイルのカスタマイズ
  • OperatorのKubernetesクラスタへのデプロイ
  • 管理サーバの資格証明のためのシークレットの設定
  • WebLogicドメインのための永続ボリュームの作成
  • ドメインパラメータファイルのカスタマイズ
  • WebLogicドメインの作成
最新の手順は、以下のURLをご覧になるか、上記動画の簡略版をご覧ください。
Installation
https://github.com/oracle/weblogic-kubernetes-operator/blob/master/site/installation.md

Build the Docker image for the operator

KubernetesクラスタでOperatorを実行するには、Dockerイメージをビルドしてクラスタにデプロイする必要があります。
まず、以下のコマンドでビルドします。
mvn clean install
続いて、Dockerイメージを以下のコマンドで作成します。
docker build -t weblogic-kubernetes-operator:developer --no-cache=true 
イメージを識別しやすくするため、latest以外のタグを使うことを推奨します。上記の例では、タグは開発者のGitHub IDです。
続いて、Kubernetesサーバにイメージをアップロードします。
# ビルドマシン上で
docker save weblogic-kubernetes-operator:developer > operator.tar
scp operator.tar YOUR_USER@YOUR_SERVER:/some/path/operator.tar 

# Kubernetesサーバ上で
docker load < /some/path/operator.tar

# 正しいイメージであるかどうかを確認するには、以下のコマンドを両マシンで実行し、イメージIDを比較する
docker images | grep webloogic-kubernetes-operator
Oracle Container Registryでイメージを公開する予定で、使用可能になった時点で手順を更新します。公開後は、ご自身でイメージを構築する必要はなく、レジストリからイメージをプルすることもできます。

Customizing the operator parameters file

Operatorをインストールスクリプトを使ってデプロイします。
create-weblogic-operator.sh
このスクリプトへの入力はcreate-weblogic-operator-inputs.yamlファイルで、ターゲット環境を反映するようにファイルの内容を更新する必要があります。
入力ファイルには、次のパラメータを指定する必要があります。

CONFIGURATION PARAMETERS FOR THE OPERATOR

Parameter Definition Default
externalOperatorCert OperatorがRESTエンドポイントにアクセスするクライアントに提示するX.509証明書を含むbase64エンコードされた文字列。externalRestOptionがcustom-certに設定されている場合にのみこの値を使用する。
externalOperatorKey 秘密鍵を含むBase64エンコードされた文字列。externalRestOptionがcustom-cert.に設定されている場合のみこの値を使用する。
externalRestOption 許容値は以下の3種類。
- none : RESTサーバを無効化
- self-signed-cert : Operatorは、RESTサーバ用に自己署名証明書を使用する。この値を指定すると、externalSansパラメータも設定する必要がある。
- custom-cert : この値を指定すると、externalOperatorCertおよびexternalOperatorKeyも指定する必要がある。
none
externalSans カンマ区切りのSubject Alternative Name(SAN、サブジェクトの別名)のリスト。これにはX.509証明書を含む。このリストには以下のような値が含まれる。
DNS:myhost,DNS:localhost,IP:127.0.0.1
.
namespace Operatorのデプロイ先のKubernetes名前空間。名前空間defaultではなく、Operator用に名前空間を作成することを推奨。 weblogic-operator
targetNamespaces Operatorが管理するWebLogicドメインを含むKubernetes名前空間のリスト。Operatorはこのリストに含まれていないドメインに対して何らアクションを取らない。 default
remoteDebugNodePort Debugパラメータがonの場合、OperatorはJavaリモートデバッグサーバを指定したポートで起動し、リモートデバッガがアタッチされるまで実行を停止する。 30999
restHttpsNodePort HTTPSリクエストをリスニングするOperator RESTサーバに割当てられるNodePort番号 31001
serviceAccount Kubernetes API サーバにリクエストする際にOperatorが利用するサービスアカウントの名前 weblogic-operator
loadBalancer WebLogicクラスタの負荷分散のためにインストールされるロードバランサ。許容値は以下の通り。
- none – ロードバランサを構成しない
- traefik – Traefik Ingressプロバイダを構成
- nginx – 将来の利用のために予約
- ohs – 将来の利用のために予約
traefik
loadBalancerWebPort ユーザからのトラフィックを受け付けるロードバランサのNodePort 30305
enableELKintegration ELK統合を有効にするかどうかを決定する。trueに設定すると、ElasticSearch、Logstash、およびKibanaがインストールされ、LogstashがOperatorのログをElasticSearchにエクスポートするように構成する。 false

Decide which REST configuration to use

Operatorでは3個のREST証明書オプションが利用できます。
  • none : RESTサーバを無効化します。
  • self-signed-cert : 自己署名証明書を生成します。
  • custom-cert : 別の手段で作成、署名された証明書を提供するメカニズムを提供します。

Decide which optional features to enable

Operatorには設定ファイルで有効にできるオプション機能があります。

Load Balancing

OperatorはTraefik Ingressプロバイダをインストールして、WebLogicクラスタで実行されているWebアプリケーションの負荷分散が可能です。有効にすると、各WebLogicクラスタに対してTraefikのインスタンスとIngressが作成されます。ドメインの作成時に追加の構成が実行されます。
テクノロジープレビューリリースでは基本的な負荷分散のみ可能です。
  • HTTP(S)のみサポートします。他のプロトコルはサポートしません。
  • 各クラスタに対してルートパスルールが作成されます。DNS名または '/'以外のURLパスに基づくルールはサポートしません。
  • このリリースでは、デフォルト以外のロードバランサ構成は実行されません。 デフォルト構成ではラウンドロビンルーティングを実施し、WebLogic ServerはCookieベースのセッションアフィニティを提供します。
管理サーバを含む、WebLogicクラスタに属しないサーバに対してIngressを作成しないことにご注意ください。Ingressが作成されないサーバは、NodePortサービスを使用して外部に公開されます。

Log integration with ELK

OperatorはELKスタックをインストールし、ログをELKにパブリッシュします。有効化すると、ElasticSearch と Kibana をdefault名前空間にインストールし、LogstashのPodをOperator名前空間に作成します。OperatorのログをElasticsearchにパブリッシュするようにLogstashを構成すると、ログはKibanaで可視化および分析できるようになります。
To enable the ELK統合を有効化するためには、enableELKintegrationオプションをtrueにしてください。

Deploying the operator to a Kubernetes cluster

Operatorをデプロイするには、インプットファイルの場所を指定してデプロイメント・スクリプトを実行します。
./create-weblogic-operator.sh –i /path/to/create-operator-inputs.yaml

What the script does

スクリプトは以下のアクションを実行します。
  • 指定された入力から一連のKubernetes YAMLファイルを作成
  • Operatorの名前空間を作成
  • その名前空間でサービスアカウントを作成
  • ELK統合が有効になっている場合は、ELKの永続ボリュームを作成
  • 一連のRBACロールとバインディングを作成
  • Operatorのデプロイ
  • 要求された場合、ロードバランサのデプロイ
  • 要求された場合、ELKをデプロイし、Operatorのログ用にlogstashを構成
スクリプトは、処理が進む前に各アクションを検証します。
これにより、KubernetesクラスタにOperatorがデプロイされます。RESTサービスの使用、WebLogicドメインの作成、ドメインの開始を含む以後の手順については、以下のドキュメントを参照してください。
Oracle Weblogic Server Kubernetes Operator - Readme.md
https://github.com/oracle/weblogic-kubernetes-operator/blob/master/README.md

[Docker, Kubernetes, WLS] Processing the Oracle WebLogic Server Kubernetes Operator Logs using Elastic Stack

原文はこちら。
https://blogs.oracle.com/weblogicserver/processing-the-oracle-weblogic-server-kubernetes-operator-logs-using-elastic-stack

Oracleは、WebLogicコミュニティとともに、重要なワークロードをWebLogic Serverで実行する組織が、それらのワークロードをクラウドに移行するための、できるだけ簡単に行う方法を探しています。その取り組みの1つの側面として、Oracle WebLogic Server Kubernetes Operatorを提供しています。
Announcing the Oracle WebLogic Server Kubernetes Operator
https://blogs.oracle.com/developers/announcing-oracle-weblogic-server-kuberentes-operator
https://orablogs-jp.blogspot.jp/2018/03/announcing-oracle-weblogic-server.html
この記事では、Kubernetes環境におけるWebLogicドメインの管理を支援する重要な機能、すなわち、Elastic Stackの製品を使用してオペレータからのログを公開および分析する機能について説明します。

What Is the Elastic Stack?

Elastic Stack(ELK)は、Elasticsearch、Logstash、Kibanaなどのいくつかのオープンソース製品で構成されています。Elastic Stackをログデータとともに使用すると、アプリケーションのパフォーマンスをほぼリアルタイムで把握できます。
ElasticsearchはLuceneをベースにしたスケーラブルで分散型かつRESTfulな検索エンジンです。さまざまなデータセットに対するインデックス作成と高速検索を柔軟に制御できます。
Logstashは、複数のソースからのデータを同時に取得、変換し、選択した宛先にルーティングできるサーバーサイドのデータ処理パイプラインです。
Kibanaは、Elasticsearchのブラウザベースのプラグインで、収集したデータを視覚化して探索するために使用します。ダッシュボードでデータをナビゲート、選択、配置するための数多くの機能が含まれています。
Kubernetes環境でOperatorを使用してWebLogic Serverクラスタを実行する顧客は、Operatorとサーバを監視する必要がありますが、これはElasticsearchとKibanaを組み合わせることで実現できます。以下の手順でこれを設定する方法を説明します。

Processing Logs Using ELK

この例では、OperatorとLogstashエージェントは1つのPodにデプロイされ、ElasticsearchとKibanaはdefault名前空間に2つの独立したPodとしてデプロイされています。OperatorとLogstashコンテナ間で共有され、ログの保存に使用するメモリバックアップボリュームを使用します。Operatorインスタンスは、ログを共用ボリューム(/logs)に入れます。Logstashはボリュームからログを収集し、フィルタリングされたログをElasticsearchに転送します。最後に、KibanaとブラウザベースのUIを使用してログを分析し、視覚化します。ELKIntegration.png

Operator and ELK integration

OperatorとELKの統合を有効にするには、まずcreate-weblogic-operator-inputs.yamlファイルのelkIntegrationEnabledパラメータをtrueに設定する必要があります。
create-weblogic-operator-inputs.yaml
https://github.com/oracle/weblogic-kubernetes-operator/blob/master/kubernetes/create-weblogic-operator-inputs.yaml
これにより、Elasticsearch、LogstashおよびKibanaがインストールされ、LogstashがOperatorのログをElasticsearchにエクスポートするように設定されます。その後、インストール手順に従って、Operatorをインストールして始動してください。
weblogic-kubernetes-operator Installation
https://github.com/oracle/weblogic-kubernetes-operator/blob/master/site/installation.md
ELKとの統合がアクティブ化されていることを確認するには、以下のコマンドで生成された出力を確認します。
$ . ./create-weblogic-operator.sh -i create-operator-inputs.yaml
このコマンドで、以下のELKに関する情報が出力されるはずです。
Deploy ELK...

deployment "elasticsearch" configured

service "elasticsearch" configured

deployment "kibana" configured

service "kibana" configured 
3つのデプロイメントがすべて実行されていることを確認するには、次の手順で確認します。
1. ElasticsearchとKibanaのPodがデプロイされ、起動済みであることを確認します(defaultのKubernetes名前空間で実行されます)。
$ kubectl get pods
以下のような出力が出ていればOKです。

2. OperatorのPodがデプロイ済みで起動済みであることを確認します。なお、weblogic-operator名前空間で実行されていることに注意してください。
$ kubectl -n weblogic-operator get pods 
以下のような出力が出ていればOKです。

3. OperatorとLogstashコンテナがOperator Pod内で動作していることを確認します。
$ kubectl get pods -n weblogic-operator --output json    | jq '.items[].spec.containers[].name'
以下のような出力が出ていればOKです。

4. ElasticsearchのPodが起動済みであることを確認します。
$ kubectl exec -it elasticsearch-3938946127-4cb2s /bin/bash

$ curl   "http://localhost:9200"

$ curl  "http://localhost:9200/_cat/indices?v”
Elasticstashが無事に起動していれば、以下のような情報が得られるはずです。

Logstashがリストに現れない場合は、Logstashのログ出力を確認してみましょう。
$ kubectl logs weblogic-operator-501749275-nhjs0 -c logstash   -n weblogic-operator
Logstashログにエラーがない場合は、ElasticsearchのPodがLogstashコンテナの後に起動されている可能性があります。そのような場合は、単にLogstashを再起動して修正してください。

Using Kibana

Kibanaはログを閲覧するためのWebアプリケーションです。KibanaのKubernetesサービス構成には、NodePortが含まれているため、Kubernetesクラスタ外からKibanaにアクセスできます。ポート番号を見つけるため、以下のコマンドを実行します。
$ kubectl describe service kibana
このコマンドを実行すると、以下のようなサービスのNodePort情報が出力されるはずです。

この例では、NodePortの値は30911です。KibanaのWebアプリケーションには、http://[NODE_IP_ADDRESS]:30911でアクセスできます。

Kibanaが正しくインストールされていることを確認し、Kibanaのステータスを確認するには、http://[NODE_IP_ADDRESS]:30911/statusのWebページに接続してください。ステータスはGreenでなければなりません。

続いて、Kibanaのインデックスパターンを定義します。これを行うには、左側のパネルでDiscoverをクリックします。デフォルトのインデックスパターンはlogstash- *で、デフォルトの時間フィルタフィールド名は@timestampです。Createをクリックします。

Managementページではlogstash*インデックスのフィールドを表示しています。

続いて、オペレータログの表示方法をカスタマイズします。時間間隔と自動リフレッシュの設定を行うには、Discoverページの右上隅をクリックし、Auto-refreshタブをダブルクリックして、希望の間隔を選択します。たとえば、10秒といった具合です。

また、時間範囲を設定し、特定の時間間隔に生成されたログメッセージに絞ることもできます。

Logstashを構成し、Operatorログレコードを別々のフィールドに分割します。例えば以下のような感じです。
method:
dispatchDomainWatch

level:

INFO

log:
Watch event triggered for WebLogic Domain with UID: domain1

thread:
39

timeInMillis:
1518372147324

type:
weblogic-operator

path:
/logs/operator.log

@timestamp:
February 11th 2018, 10:02:27.324

@version:
1

host:
weblogic-operator-501749275-nhjs0

class:
oracle.kubernetes.operator.Main

_id:
AWGGCFGulCyEnuJh-Gq8

_type:
weblogic-operator

_index:
logstash-2018.02.11

_score:
表示するフィールドを制限できます。例えば、level、method、logfieldsを選択してaddをクリックすると、選択したフィールドのみ表示されます。

フィルタを使用して、式に一致するフィールドを持つログメッセージのみを表示することもできます。Discoverページの上部にあるAdd a filterをクリックしてフィルタ式を作成します。 たとえば、method、is one of、onFailureを選択すると…

KibanaにはonFailureメソッドからの全てのメッセージが表示されます。
ここまでの設定で、KibanaでOperatorログを収集できるようになりました。ブラウザベースのビューアを使用して、ログを簡単に表示、分析できます。

Summary

このエントリでは、Elastic StackとOracle WebLogic Server Kubernetes Operatorの統合アーキテクチャを紹介した後、Operatorログと対話するためにKibanaを設定および構成する方法について詳しく説明しました。Kubernetes環境でのWebLogicドメインの監視にあたり、機能、柔軟性、および豊富な機能が非常に有用な資産であることがおわかりいただけたかと思います。

[Linux] Faster Startup Times with Oracle Linux 7

原文はこちら。
https://blogs.oracle.com/linuxkernel/faster-startup-times-with-oracle-linux-7

Steve Sistareは、Oracleのカーネル開発アーキテクトです。 このエントリでは、システムの起動を高速化するためのヒントとテクニックを紹介します。

10月にPasha Tatashinが、特に大規模なシステム向けに、カーネルの起動を大幅に高速化するという成果をブログで公開しました。
Accelerating Linux Boot Time
https://blogs.oracle.com/linuxkernel/accelerating-linux-boot-time
しかし、カーネルの起動は、作業の一部にすぎません。というのも、ユーザランドでサービスを開始する必要があるためです。とはいえ、起動時間は重要なものであり、設定に依存します。Oracle Linuxは、デフォルトで幅広い要件を満たすように構成されていますが、構成を調整すれば、起動時間を大幅に短縮できます。

Silence the console

設定できる単一の改善ポイントは、カーネルのコマンドラインを "quiet"に設定することです。これにより、カーネルのメッセージがコンソールに表示されなくなります。これらのメッセージは、コンソールが低ボーレート設定のシリアルインターフェイス経由で接続されているときに、起動中に長時間かかることがあります。Oracle Linux 7を実行するx86システムではデフォルトのILOMシリアルコンソール速度が9600ボーなので、quietオプションを有効にすると、systemd-analyzeによって報告されたkernel + initrd + userspace時間が62.259秒から21.425秒に短縮されました。代わりにシリアルレートを115200ボーに増やすことができますが、それは面倒な作業を伴います。ILOM、BIOS、GRUB、およびカーネルのコマンドライン引数でシリアルレートを変更する必要があります。その設定をしたとしても、115200ボーよりもquietのほうが数秒速いです。また、カーネルメッセージは失われません。カーネルが正常に起動した場合には、dmesgとjournalコマンドで閲覧できます!失敗時にカーネルの出力を見る必要があるカーネル開発時は、quietを使用しないでください。最後に、(エミュレートされたコンソールデバイスとは対照的に)準仮想化コンソールデバイスを使用するVMをブートする場合、シリアルボーレートによって制限されないため、quietではほとんど改善されません。

quietオプションを有効化するには…
  • /etc/default/grubを編集
  • GRUB_CMDLINE_LINUX 文字列に"quiet"を追加
  • "grub2-mkconfig -o /boot/grub2/grub.cfg"を実行

Use up-to-date packages

可能な限り最新のOracle Linuxアップデートを使用して、最新のパッケージと最適化を入手してください。たとえば、古いバージョンのNetworkManagerパッケージには、余計な「キャリア待機」タイムアウトが有効になっていて、起動を5秒遅らせるバグがありました。これはOL7.4で修正されました。同様に、グラフィカルコンソールを持たないKVMゲストで、kbdパッケージがPUT_FONT ioctlが成功するために5秒間待機していたため、待ち時間は無駄でした。さらに悪いことに、これはinitdブートフェーズ中、userspaceフェーズ中にそれぞれ1回ずつ発生し、結果として10秒の遅延が発生しました。これもOL7.4で修正されています。

Tune grub

grubの遅延を減らすか、またはなくしましょう。デフォルトでは、grubは5秒間休止するので、別のカーネルを選択したり、カーネルパラメータを変更することができますが、これは設定可能です。緊急時にこの補助が必要な場合は1に設定します。 KVMで実行している場合は0に設定します。カーネルのブートに失敗したときに、ゲストイメージを手動でマウントしてgrubファイルを直接編集するなど、パラメータを変更する他の方法があります。

タイムアウト設定を変更するには…
  • /etc/default/grubを編集
  • GRUB_TIMEOUT=5 を GRUB_TIMEOUT=1 (または 0)に変更
  • "grub2-mkconfig -o /boot/grub2/grub.cfg"を実行

Check autofs

autofsが正しく設定されていることを確認しましょう。/etc/nsswitch.confのautomountエントリが誤って設定されていると、このパッケージの最近の変更によりブート時に10秒の遅延が発生し、"automount[969]: problem reading master map, maximum wait exceeded"(automount [969]:マスターマップの読み込みに問題があり、最大待機時間を超過しました)というメッセージがジャーナルに記録されます。詳細については以下のURLを参照してください。
[ANNOUNCE] autofs 5.1.3 release
https://lkml.org/lkml/2017/5/26/64
上記のTipsに従った後、私たちがどうやっているかを見てみましょう。systemd-analyzeコマンドを使用して、全体の起動時間と最上位のサービスが使用した時間を確認します。ここでは、Intel Xeon Platinum CPU上のOL7.4 KVMゲストを起動します。
<... boot and login to the console ...>

# systemd-analyze
Startup finished in 697ms (kernel) + 879ms (initrd) + 3.877s (userspace) = 5.454s
# systemd-analyze blame
           1.799s kdump.service
           1.166s NetworkManager-wait-online.service
           396ms postfix.service
           321ms network.service
           247ms systemd-udev-settle.service
           244ms tuned.service
           151ms dev-mapper-ol\x2droot.device
           148ms lvm2-monitor.service
           119ms lvm2-pvscan@251:2.service
           113ms plymouth-quit.service
           112ms plymouth-quit-wait.service
           104ms systemd-vconsole-setup.service
           ...

Tune the bridge

次に、ホストとゲスト間はブリッジインターフェイスでKVMを使用しており、ネットワークトポロジにループがないことがわかっている場合は、ブリッジ上のSTP(Spanning Tree Protocol)を無効にします。これにより、2秒以上のゲストブート時間が節約されます。STPが有効の場合、ブリッジは、転送遅延が切れるまで、新しく検出されたアドレスから受信したすべてのパケットをドロップします。これは、ループが存在するときにパケットのフラッディングを回避するためです。したがって、ゲストのDHCP要求パケットは廃棄され、dhclientタイムアウトと再試行につながります。

ブリッジを確認するには…
# brctl show
    bridge name     bridge id               STP enabled     interfaces
    virbr0          8000.525400fe7ca3       yes             virbr0-nic
転送遅延を確認するには…
# brctl showstp virbr0 | grep forward
    forward delay       2.00       bridge forward delay       2.00
STPを無効化するには…
# brctl stp virbr0 off
libvirtをお使いの場合、デフォルトの設定でSTPを無効化し、変更を永続化するためにホストを再起動します。
# virsh net-edit default
    "<bridge name='virbr0' stp='on' delay='0'/>を見つけて、onをoffに変更
(一見すると、delay = '0'で問題が解決すると思うかもしれませんが、カーネルは最小値2秒を強制します)。

STPを無効にすると、起動時間は以下のようになりました。DHCPの遅延をなくしたため、NetworkManager-wait-onlineの時間がはるかに小さいことに着目してください。
$ systemd-analyze
Startup finished in 678ms (kernel) + 903ms (initrd) + 2.746s (userspace) = 4.328s
$ systemd-analyze blame 
          1.700s kdump.service
           397ms postfix.service
           294ms network.service
           252ms systemd-udev-settle.service
           206ms tuned.service
           203ms dev-mapper-ol\x2droot.device
           168ms NetworkManager-wait-online.service
           157ms plymouth-quit-wait.service
           157ms plymouth-quit.service
           135ms lvm2-monitor.service
            95ms systemd-vconsole-setup.service
           ...

Disable optional services

"systemctl disable <name.service>"を使用して、不要なサービスを無効にします。 上記のように、"systemd-analyze blame"コマンドを使用して候補を表示しましょう。たとえば、パニック後にカーネルクラッシュダンプを取得する必要がない場合や、問題が発生して初めて有効化したい場合は、kdump.serviceを無効にすると、起動時間が約2秒短縮されます。メールサーバーを実行していない場合は、postfix.serviceを無効にします。tuned.serviceは目立つチューニングをしていないと確信しているなら、無効にしましょう。

全部まとめると、こんな感じです。
$ systemctl disable kdump.service
$ systemctl disable postfix.service
$ systemctl disable tuned.service

<... 再起動してコンソールにログイン ...>

$ systemd-analyze
Startup finished in 681ms (kernel) + 863ms (initrd) + 1.136s (userspace) = 2.681s

$ systemd-analyze blame
           299ms network.service
           273ms systemd-udev-settle.service
           178ms dev-mapper-ol\x2droot.device
           160ms NetworkManager-wait-online.service
           149ms lvm2-monitor.service
           148ms plymouth-quit-wait.service
           136ms plymouth-quit.service
            94ms systemd-vconsole-setup.service
           ...

[Java] Introducing Java SE 10

原文はこちら。
https://blogs.oracle.com/java-platform-group/introducing-java-se-10

Java SE 10 (OpenJDK)
http://jdk.java.net/10Java SE 10 (Oracle JDK)
http://www.oracle.com/technetwork/java/javase/downloads/index.html
過去22年間にわたって、Javaは、比類なき規模に達した活気のあるコミュニティに成長しました。Javaは引き続き世界中の開発者や企業に価値をもたらし続けています。思慮深い計画とエコシステムの関わりのおかげで、Javaは地球上で最も使用されているプログラミング言語の1つに成長しました。世界中で1,200万人以上の開発者と共に、Javaは、ソフトウェアプログラマが選択する第1位のプログラミング言語であり続けています。今後は、Javaがクラウドにおけるモダンな開発と成長のためによい位置につけることを確保したいと考えています。
2017年、OracleとJavaコミュニティは、Javaの新しい6か月のケイデンス(リリースサイクル)に移行し、メジャーリリース間のレイテンシを短縮する意向を発表しました。
Faster and Easier Use and Redistribution of Java SE
https://blogs.oracle.com/java-platform-group/faster-and-easier-use-and-redistribution-of-java-se
https://orablogs-jp.blogspot.com/2017/09/faster-and-easier-use-and.html
同時に、OracleはOpenJDKバイナリを構築して出荷する計画も発表しました。このリリースモデルは、他のプラットフォームや最新のアプリケーション開発環境に対応したさまざまなオペレーティングシステムのディストリビューションで使用されているリリースモデルからインスピレーションを得ています。イノベーションのペースはますます速くなっています。この新しいリリースモデルによって、開発者はできるだけ早期に本番環境で新しい機能を活できます。モダンなアプリケーション開発では、シンプルなオープンライセンスと予測可能な時間ベースのリズムが期待されています。新しいリリースモデルは、その両方をうまくやり遂げています。
そんなわけで、Oracleは、新しい6か月のリリース・サイクルの一環として初めてタイム・バウンド・リリースであるJava 10の一般提供を発表でき喜ばしく思っています。このリリースは、Java SE 9に比べて単純な安定性とパフォーマンスが向上しただけでなく、開発者がすぐに使い出せるJDK拡張提案(JDK Enhancement Proposals / JEPS)で定義された12個の新しい拡張機能が導入されています。
JDK Enhancement Proposals (JEPS)
http://openjdk.java.net/jeps/0
  1. JEP 286 : ローカル変数型推論(Local-Variable Type Inference)
    http://openjdk.java.net/jeps/286
    型推論をイニシャライザを持つローカル変数の宣言に拡張するようにJava言語を拡張する。この目的でJavaにvarに導入する。これは他の言語でよく見られるものである。
  2. JEP 296 : JDKフォレストの単一リポジトリへの統合(Consolidate the JDK Forest into a Single Repository)
    http://openjdk.java.net/jeps/296
    JDKフォレストの多数のリポジトリを1つのリポジトリにまとめて、開発を簡素化し合理化する。
  3. JEP 204 : ガベージ・コレクタ・インターフェース(Garage Collector Interface)
    http://openjdk.java.net/jeps/304
    クリーンなガベージ・コレクタ・インターフェースを導入して、異なるガベージ・コレクタのソースコード分離を改善する
  4. JEP 307 : G1のパラレルフルGC(Parallel Full GC for G1)
    http://openjdk.java.net/jeps/307
    フルGCを並列化することでG1における最悪の場合のレイテンシを改善する
  5. JEP 301 : アプリケーションデータクラスの共有(Application Data-Class Sharing)
    http://openjdk.java.net/jeps/301
    起動およびフットプリントを改善するため、既存のクラスデータ共有(CDS)機能を拡張して、アプリケーションクラスを共有アーカイブに配置できるようにする。
  6. JEP 312 : スレッドローカルハンドシェイク(Thread-Local Handshakes)
    http://openjdk.java.net/jeps/312
    グローバルVMセーフポイントを実行せずにスレッドでコールバックを実行する方法を提供する。すべてのスレッドだけでなく、個々のスレッドを停止することも簡単。
  7. (JEP 313)ネイティブ・ヘッダー・ジェネレーター・ツールの削除(Remove the Native-Header Generator Tool)
    http://openjdk.java.net/jeps/313
    javahツールはjavacの優れた機能に取って代わられているため、JDKからjavahツールを除去する。
  8. JEP 314 : 追加のUnicode言語タグ拡張(Additional Unicode Language-Tag Extensions)
    http://openjdk.java.net/jeps/314
    java.util.Localeおよび関連するAPIを拡張し、BCP 47言語タグのUnicode拡張を追加実装する。
  9. JEP 316 : 代替メモリー・デバイスでのヒープ割り振り(Heap Allocation on Alternative Memory Devices)
    http://openjdk.java.net/jeps/316
    HotSpot VMが、ユーザーが指定したNV-DIMMなどの代替メモリー・デバイスにJavaオブジェクト・ヒープを割り振ることを可能にする。
  10. JEP 317 : 実験的なJavaベースのJITコンパイラ(Experimental Java-Based JIT Compiler)
    http://openjdk.java.net/jeps/317
    JavaベースのJITコンパイラGraalをLinux/x64プラットフォーム上の実験的なJITコンパイラとして使用できるようにする。
  11. JEP 319 : ルート証明書(Root Certificates)
    http://openjdk.java.net/jeps/319
    JDK内のルート証明機関(Certification Authority、CA)証明書のデフォルトセットを提供する。
  12. JEP 322 : 時間ベースのリリースのバージョニング(Time-Based Release Versioning)
    http://openjdk.java.net/jeps/322
    現在および将来のタイムベースのリリースモデルのために、Java SE PlatformおよびJDKのバージョン文字列スキームおよび関連するバージョン情報を改訂する。
Javaエコシステムは引き続き多様な開発者集団であり続けます。Javaの未来を形作るための継続的な参加を歓迎します。OpenJDKプロジェクトに参加して、Javaの進化を速めるために協力してください。
OpenJDK project
http://openjdk.java.net/