API サーバー ソースコード分析: エントリ ポイント分析

API サーバー ソースコード分析: エントリ ポイント分析


Kubernetes (K8s) クラスターで最も重要なコンポーネントの 1 つは、すべてのクラスター管理アクティビティのエントリ ポイントである API サーバーです。この記事から、K8s API サーバーのコードを詳細に分析し、アプリケーションのエントリ ポイント、フレームワーク、etcd との通信について説明します。

アプリケーションのエントリポイント

K8s API サーバーのメイン エントリ ポイントは、cmd/kube-apiserver/apiserver.go ファイルにあります。

 // cmd/kube-apiserver/apiserver.go

// apiserver はクラスターのメイン API サーバーおよびマスターです。
// クラスター管理 API を提供する役割を担います。
パッケージメイン

輸入
「オス」

「k8s.io/コンポーネントベース/cli」
_ "k8s.io/component-base/logs/json/register" // JSON ログ形式の登録に使用
_ "k8s.io/component-base/metrics/prometheus/clientgo" // すべてのprometheus client-goプラグインをロードします
_ "k8s.io/component-base/metrics/prometheus/version" // バージョンインジケーターの登録に使用
「k8s.io/kubernetes/cmd/kube-apiserver/app」


関数main (){
コマンド: = app新しいAPIサーバーコマンド()
コード: = cli実行(コマンド)
os終了(コード)
}

app.NewAPIServerCommand() は cobra コマンド オブジェクトを構築し、cli.Run はコマンドを実行するため、NewAPIServerCommand 関数が cobra.Command オブジェクトを構築する方法を直接確認できます。

 // cmd/kube-apiserver/app/server.go

// NewAPIServerCommand はデフォルトのパラメータを持つ *cobra.Command オブジェクトを作成します
func NewAPIServerCommand () *コブラ指示{
// NewServerRunOptions はデフォルトのパラメータを使用して新しい ServerRunOptions オブジェクトを作成します。
// apiserver を実行するには ServerRunOption オブジェクトが必要です
s : =オプション新しいサーバー実行オプション()
cmd : = &コブラ指示{
使用方法: "kube-apiserver"
Long : ` Kubernetes APIサーバーはデータを検証し構成します
ポッドサービスレプリケーションコントローラおよび
その他APIサーバーREST操作提供
他のすべてのコンポーネントが相互作用するクラスターの共有状態。`,

// ......
RunE : func ( cmd * cobra .コマンド, args []文字列)エラー{
verflag.PrintAndExitIfRequested ( )
fs : = cmdです。フラグ()

err : = sの場合ログ検証して適用します();エラー!=ゼロ{
エラーを返す
}
クリフラグ印刷フラグ( fs )

エラー: = checkNonZeroInsecurePort ( fs )
err != nil の場合{
エラーを返す
}
// デフォルトオプションを設定する
完了オプションエラー: =完了( s )
err != nil の場合{
エラーを返す
}
// オプションを確認する
エラーの場合: = completedOptions検証します(); len (エラー) != 0 {
utilerrors.NewAggregate ( errs )を返す
}
Run ( completedOptionsgenericapiserver.SetupSignalHandler ())返します
},
}

// ......

戻りコマンド
}

この関数の中心的な機能は、Complete(s) 関数を使用して、apiserver の起動に必要なデフォルトのパラメータを生成し、起動のためにそのデフォルトのパラメータを Run 関数に渡すことです。

 // cmd/kube-apiserver/app/server.go
// 実行は指定された APIServer を実行し、終了できません。
func Run ( completeOptionscompletedServerRunOptions , stopCh <- chan struct {} ) error {

// サービス チェーンを作成する (3 つのサーバー コンポーネントを含む)
サーバーerr : = CreateServerChain ( completeOptionsstopCh )


// ヘルスチェック、生存チェック、OpenAPI ルート登録など、サービスを開始する前の準備。
準備完了エラー: =サーバー準備実行()

// 正式に実行を開始する
返却準備完了実行( stopCh )
}

Run 関数では、CreateServerChain 関数を使用して、委任を通じて接続された APIServer オブジェクトを作成します。

 // cmd/kube-apiserver/app/server.go

// CreateServerChain は委任を通じて接続された APIServer を作成します
func CreateServerChain ( completedOptionscompletedServerRunOptions , stopCh <- chan struct { } ) ( * aggregatorapiserver.APIAggregator , error ) {
// CreateKubeAPIServerConfig は、APIServer を実行するためのすべての構成リソースを作成しますが、リソースは実行しません。
kubeAPIServerConfigserviceResolverpluginInitializererr : = CreateKubeAPIServerConfig ( completeOptions ) を作成します。

// // APIExtensionsServer 構成を作成する
apiExtensionsConfig err : = createAPIExtensionsConfig ( * kubeAPIServerConfig.GenericConfigkubeAPIServerConfig.ExtraConfig.VersionedInformers pluginInitializer completedOptions.ServerRunOptions completedOptions.MasterCount
serviceResolverwebhookNewDefaultAuthenticationInfoResolverWrapper ( kubeAPIServerConfig.ExtraConfig.ProxyTransport kubeAPIServerConfig.GenericConfig.EgressSelector kubeAPIServerConfig.GenericConfig.LoopbackClientConfig kubeAPIServerConfig.GenericConfig.TracerProvider ) )

// APIExtensionsServerを作成し、ルートを登録する
apiExtensionsServererr : = createAPIExtensionsServer ( apiExtensionsConfiggenericapiserver.NewEmptyDelegateWithCustomHandler ( notFoundHandler ) )

// KubeAPIServerを作成し、ルートを登録する
kubeAPIServer エラー: = CreateKubeAPIServer ( kubeAPIServerConfigapiExtensionsServer。GenericAPIServer )

// // aggregatorServer 構成を作成する
aggregatorConfig err : = createAggregatorConfig ( * kubeAPIServerConfig.GenericConfigcompletedOptions.ServerRunOptionskubeAPIServerConfig.ExtraConfig.VersionedInformersserviceResolver kubeAPIServerConfig.ExtraConfig.ProxyTransport pluginInitializer )

// aggregatorServer を作成し、ルートを登録する
aggregatorServererr : = createAggregatorServer ( aggregatorConfigkubeAPIServer.GenericAPIServerapiExtensionsServer.Informers )

aggregatorServerを返すnil
}

上記の関数では、CreateServerChain によって APIExtensionServer、KubeAPIServer、AggregatorServer の 3 つのサーバーが作成されることがわかります。 APIServer は、さまざまな種類のリクエストを処理するために、次の 3 つのコンポーネントに依存しています。

  • APIExtensionServer: 主に CustomResourceDefinition (CRD) リクエストの処理を担当します。
  • KubeAPIServer: 一般的な処理、認証、承認に加えて、K8s 組み込みリソースに対するリクエストの処理を主に担当します。
  • AggregatorServer: 主にアグリゲーター処理を担当し、集約された K8s サービスにリクエストを転送するプロキシ サーバーとして機能します。

各サーバーには対応する構成があります。上記の関数の apiExtensionServer と aggregatorServer の構成は kubeAPIServerConfig に依存する必要があり、これらの ServerConfig はすべて GenericConfig に依存する必要があることがわかります。 CreateKubeAPIServerConfig 関数は kubeAPIServerConfig を作成します。この関数では、次のコードに示すように、buildGenericConfig を呼び出すことによって GenericConfig オブジェクトが作成されます。

 // cmd/kube-apiserver/app/server.go
// CreateKubeAPIServerConfig は、APIServer を実行するためのすべての構成リソースを作成します。
func CreateKubeAPIServerConfig ( s完了したServerRunOptions ) (
*コントロールプレーン.Config
aggregatorapiserver.ServiceResolver
[]入場料プラグイン初期化子
エラー
){
proxyTransport : = CreateProxyTransport ()
// 共通構成を構築する
genericConfigversionedInformersserviceResolverpluginInitializersadmissionPostStartHookstorageFactoryerr : = buildGenericConfig ( s.ServerRunOptionsproxyTransport )

// ......

config : = &コントロールプレーン.設定{
汎用設定:汎用設定
追加構成:コントロールプレーン追加構成{
APIリソース構成ソース:ストレージファクトリーAPIリソース構成ソース
ストレージファクトリー:ストレージファクトリー
イベントTTL : sイベントTTL
KubeletClientConfig : sKubeletConfig
EnableLogsSupport : sEnableLogsHandler
プロキシトランスポート:プロキシトランスポート

サービスIP範囲: sプライマリサービスクラスタIP範囲
APIServerServiceIP : s.APIServerServiceIP
セカンダリサービスIP範囲: sセカンダリサービスクラスタIP範囲

APIサーバーサービスポート: 443

ServiceNodePortRange : sサービスノードポート範囲
KubernetesServiceNodePort : sKubernetesServiceNodePort

EndpointReconcilerType :リコンサイラータイプ( s . EndpointReconcilerType )、
マスターカウント: sマスターカウント

サービスアカウント発行者: sサービスアカウント発行者
ServiceAccountMaxExpiration : sサービスアカウントトークン最大有効期限
有効期限を延長: s認証サービス アカウント有効期限を延長

バージョン管理された情報提供者:バージョン管理された情報提供者

IdentityLeaseDurationSeconds : sアイデンティティリース期間秒数
IdentityLeaseRenewIntervalSeconds : sアイデンティティリース更新間隔秒数
},
}

// ......

configserviceResolverpluginInitializersnil を返します
}

関数buildGenericConfig (
s *オプションサーバー実行オプション
プロキシトランスポート* http輸送
)(...){
// 一般的な構成オブジェクトを作成する
genericConfig = genericapiserverNewConfig (レガシースキーム.コーデック)

// ......

//認証インスタンスを作成する
lastErr = sの場合認証ApplyTo ( & genericConfig.Authentication genericConfig.SecureServinggenericConfig.EgressSelectorgenericConfig.OpenAPIConfigclientgoExternalClientversionedInformers ) ; lastErr != nil {
戻る
}

// ...
// openapi/swagger 構成、OpenAPIConfig は OpenAPI 仕様を生成するために使用されます
getOpenAPIDefinitions : = openapi ですGetOpenAPIDefinitionsWithoutDisabledFeatures (生成されたopenapiGetOpenAPIDefinitions )
一般的な設定OpenAPIConfig = genericapiserverDefaultOpenAPIConfig ( getOpenAPIDefinitions openapinamer.NewDefinitionNamer ( legacyscheme.Scheme extensionsapiserver.Schemeaggregatorscheme.Scheme ))
一般的な設定OpenAPIConfig情報タイトル= 「Kubernetes」
一般的な設定LongRunningFunc =フィルター基本的な長時間実行リクエストチェック (
セットしますNewString ( "watch""proxy" )、
セットしますNewString ( "attach""exec""proxy""log""portforward" )、


// storageFactoryConfig オブジェクトは、etcd 認証、アドレス、ストレージ プレフィックスなど、kube-apiserver が etcd と対話する方法を定義します。
// このオブジェクトは、リソース情報、リソース エンコーディング情報、リソース ステータスなどのリソースの保存方法も定義します。
storageFactoryConfig : = kubeapiserver新しいストレージファクトリー構成()
ストレージファクトリ構成。 APIリソース構成= genericConfigマージされたリソース構成
StorageFactoryConfig が完了しましたエラー: = storageFactoryConfigです。完了( s . Etcd )

storageFactorylastErr =完了したStorageFactoryConfig新しい()

lastErr = sの場合などなどストレージファクトリーストレージファクトリーを適用しますlastErr != nil {
戻る
}

// ......

// SharedInformerFactory を初期化する
kubeClientConfig : = genericConfig ですループバッククライアント構成
clientgoExternalClientエラー: = clientgoclientset新しいConfig ( kubeClientConfig )
versionedInformers = clientgoinformers ですNewSharedInformerFactory ( clientgoExternalClient10 *時間.)

// 認証構成。内部的に authenticatorConfig.New() を呼び出します。
// K8s は 9 つの認証メカニズムを提供しており、それぞれがインスタンス化されると認証子になります。
lastErr = sの場合認証ApplyTo ( & genericConfig.Authentication genericConfig.SecureServing genericConfig.EgressSelectorgenericConfig.OpenAPIConfigclientgoExternalClientversionedInformers ) ; lastErr != nil {
戻る
}

// 認証インスタンスを作成します。 K8s は 6 つの認証メカニズムも提供します。各承認メカニズムは、インスタンス化された後に承認者になります。
一般的な設定承認承認者genericConfigRuleResolvererr = BuildAuthorizer ( sgenericConfig . EgressSelectorversionedInformers )

// ...
//監査
lastErr = sです。監査適用先( genericConfig )

// アドミッションコントローラ
// k8s リソースは、認証と承認が通過した後、etcd に永続化される前に、アドミッション コントロール ロジックに入ります。
// アドミッション制御には、要求されたリソースに対するカスタム操作(検証、変更、拒否)が含まれます。
// アドミッションコントローラは、プラグインデータ構造を通じて一様に登録、保存、管理されます
admissionConfig : = & kubeapiserveradmission設定{
外部情報提供者:バージョン管理情報提供者
LoopbackClientConfig : genericConfigループバッククライアント構成
CloudConfigFile : sクラウドプロバイダーCloudConfigFile
}
serviceResolver = buildServiceResolver ( s.EnableAggregatorRouting genericConfig.LoopbackClientConfig.HostversionedInformers )
pluginInitializersadmissionPostStartHookerr = admissionConfig新規( proxyTransportgenericConfig . EgressSelectorserviceResolvergenericConfig . TracerProvider )

エラー= s入場料適用先(
ジェネリック構成
バージョン化された情報提供者
kubeClientConfig
機能.DefaultFeatureGate
プラグイン初期化子...)

// ...

}

それでは、これら 3 つのサーバーがどのように構築されているかを見てみましょう。

go-restfulフレームワーク

ここでは、APIServer がこのフレームワークを使用するため、まず go-restful フレームワークを理解する必要があります。次のコードは go-restful の公式例です。このデモを理解すると、基本的に go-restful フレームワークの使い方がわかります。

パッケージメイン

輸入
"ログ"
「ネット/http」

RESTfulスペック「github.com/emicklei/go-restful-openapi/v2」
レストフル「github.com/emicklei/go-restful/v3」
「github.com/go-openapi/spec」


// UserResource はユーザードメインへの REST レイヤーです
タイプUserResource構造体{
// 通常はDAO(データアクセスオブジェクト)を使用します
ユーザーマップ[文字列]ユーザー
}

// WebService は、ユーザー リソースに対する REST 要求を処理できる新しいサービスを作成します。
func ( u UserResource ) WebService () * restfulWebサービス{
ws : = new ( restful.WebService )追加します。
ws
パス( "/users" )。
( restful . MIME_XMLrestful . MIME_JSON )を消費します
( restful . MIME_JSONrestful . MIME_XML )を生成します// ルートごとにこれを指定することもできます

tags : = []文字列{ "users" }

wsルート( ws . GET ( "/" )。To ( u . findAllUsers )。
// ドキュメント
Doc ( 「すべてのユーザーを取得」 )。
メタデータ( restfulspec . KeyOpenAPITagstags )。
書き込みます([]ユーザー{})。
( 200"OK" 、[]ユーザー{})を返します

wsルート( ws . GET ( "/{user-id}" )。To ( u . findUser )。
// ドキュメント
Doc ( 「ユーザーを取得する」 )。
Param ( ws . PathParameter ( "user-id" , "ユーザーの識別子" ). DataType ( "integer" ). DefaultValue ( "1" )).
メタデータ( restfulspec . KeyOpenAPITagstags )。
書き込みますユーザー{})。 // レスポンスで
( 200"OK"User {} )を返します
( 404"見つかりません"nil )を返します)

wsルート( ws . PUT ( "/{user-id}" )。To ( u . updateUser )。
// ドキュメント
ドキュメント( 「ユーザーの更新」 )。
Param ( ws . PathParameter ( "user-id" , "ユーザーの識別子" ). DataType ( "string" )).
メタデータ( restfulspec . KeyOpenAPITagstags )。
リクエストから( User {})) //を読み取ります

wsルート( ws . PUT ( "" ). To ( u . createUser ).
// ドキュメント
Doc ( 「ユーザーを作成する」 )。
メタデータ( restfulspec . KeyOpenAPITagstags )。
リクエストから( User {})) //を読み取ります

wsルート( ws . DELETE ( "/{user-id}" )。To ( u . removeUser )。
// ドキュメント
Doc ( 「ユーザーを削除する」 )。
メタデータ( restfulspec . KeyOpenAPITagstags )。
Param ( ws . PathParameter ( "user-id" , "ユーザーの識別子" ). DataType ( "string" )))

WSを返す
}

// http://localhost:8080/users を取得します
//
func ( u UserResource ) findAllUsers ( request * restful . Requestresponse * restful . Response ) {
リスト: = []ユーザー{}
_についてそれぞれ: =範囲uユーザー{
list = append (リスト)
}
response.WriteEntity (リスト)
}

// http://localhost:8080/users/1 を取得します
//
func ( u UserResource ) findUser ( request * restful.Request , response * restful.Response ) {
id : =リクエストPathParameter ( "ユーザーID" )
usr : = uです。ユーザー[ ID ]
len ( usr.ID ) == 0の場合{
応答WriteErrorString ( http . StatusNotFound「ユーザーが見つかりませんでした。」 )
}それ以外{
レスポンス.WriteEntity (usr )
}
}

// http://localhost:8080/users/1 を配置します
// <User><Id>1</Id><Name>メリッサ ラズベリー</Name></User>
//
func ( u * UserResource ) updateUser ( request * restful . Requestresponse * restful . Response ) {
usr : = new (ユーザー)
エラー: =リクエストエンティティの読み取り( & usr )
エラー== nilの場合{
あなたユーザー[ usr . ID ] = * usr
レスポンス.WriteEntity (usr )
}それ以外{
応答書き込みエラー( http . StatusInternalServerErrorerr )
}
}

// http://localhost:8080/users/1 を配置します
// <User><Id>1</Id><Name>メリッサ</Name></User>
//
func ( u * UserResource ) createUser ( request * restful . Requestresponse * restful . Response ) {
usr : =ユーザー{ ID :リクエスト. PathParameter ( "ユーザーID" ) }
エラー: =リクエストエンティティの読み取り( & usr )
エラー== nilの場合{
あなたユーザー[ usr . ID ] = usr
応答WriteHeaderAndEntity ( http . StatusCreatedusr )
}それ以外{
応答書き込みエラー( http . StatusInternalServerErrorerr )
}
}

// http://localhost:8080/users/1 を削除
//
func ( u * UserResource ) removeUser ( request * restful.Request , response * restful.Response ) {
id : =リクエストPathParameter ( "ユーザーID" )
削除( u .ユーザーid )
}

関数main (){
u : = UserResource { map [ string ] User {}}
安らかなデフォルトコンテナ。 ( u.WebService ())追加します

config : = restfulspec です設定{
Web サービス: RESTfulRegisteredWebServices (), // 表示されるサービスを制御します
APIパス: "/apidocs.json"
PostBuildSwaggerObjectHandler :強化SwaggerObject }
安らかなデフォルトコンテナ。 ( restfulspec.NewOpenAPIService ( config ))追加します

// オプションとして、REST API に優れた Web UI を提供する Swagger サービスをインストールできます。
// Swagger HTML5 アセットをダウンロードし、以下の構成で FilePath の場所を変更する必要があります。
// http://localhost:8080/apidocs/?url=http://localhost:8080/apidocs.json を開く
http://www.youtube.com/watch?v=vUyQyYyxcハンドル( "/apidocs/"http . StripPrefix ( "/apidocs/"http . FileServer ( http . Dir ( "/Users/emicklei/Projects/swagger-ui/dist" ))))

ログPrintf ( "localhost:8080 でリッスンを開始します" )
ログ致命的( http .ListenAndServe ( ":8080"nil ))
}

関数enrichSwaggerObject ( swo * spec.Swagger ){
スウォ情報= &仕様.情報{
InfoProps :仕様情報プロパティ{
タイトル: 「UserService」
説明: 「ユーザーを管理するためのリソース」
お問い合わせ先: & spec .連絡先情報{
ContactInfoProps :仕様連絡先情報プロパティ{
名前: 「ジョン」
メールアドレス: "[email protected]"
URL : "http://johndoe.org"
},
},
ライセンス: & spec .ライセンス{
ライセンスプロパティ: specライセンスプロパティ{
名前「MIT」
URL : "http://mit.org"
},
},
バージョン: "1.0.0"
},
}
スウォタグ= [] specタグ{ spec .タグ{ TagProps : spec .タグプロパティ{
名前: 「ユーザー」
説明: 「ユーザーの管理」 }}}
}

// ユーザーは単なるサンプルタイプです
タイプUser構造体{
ID文字列`json : "id"説明: "ユーザーの識別子" `
名前文字列`json : "name"説明: "ユーザー名"デフォルト: "john" `
年齢int `json : "年齢"説明: "ユーザーの年齢"デフォルト: "21" `
}

このサンプル コードでは、go-restful のコア機能を使用して、ユーザーの追加、削除、クエリ、変更を実装するシンプルな RESTful API を実装します。コンテナ、Web サービス、ルートといういくつかのコア概念があります。

  • コンテナー: 複数の Web サービスと http.ServerMux を含むサーバー コンテナー。
  • WebService: サービスは複数のルートから構成されます。 WebService は実際には、上記の例の /users など、特定のオブジェクトに関連するサービスを表します。 /users の RESTful API を実装するには、追加、削除、確認、変更を行うルート (Route のコレクション) を追加する必要があります。
  • ルート: URL、http メソッド、受信および応答メディア タイプ、処理関数を含むルーティング。各ルートは、メソッドとパスに従って対応するメソッドにマッピングされます。これは、メソッド/パスから関数へのマッピング関係を抽象化したものです。たとえば、上記の例の ws.Route(ws.GET("/{user-id}").To(u.findUser)) は、パス /users/{user-id} に対する GET リクエストであり、findUser メソッドにルーティングされて処理されます。
  • コンテナは Web サービスのコレクションです。コンテナに複数の Web サービスを追加できます。コンテナーは ServeHTTP() メソッドを実装しているため、本質的には http ハンドラーであり、http サーバーで直接使用できます。

Kubernetes での go-restful の使用は比較的基本的なものであり、最も基本的なルーティング機能が使用されます。 K8s には、CRD などのカスタム リソース オブジェクトを含む多くの組み込みリソース オブジェクトがあるため、これらのリソースに対応するインターフェースは最初から直接ハードコードされているのではなく、一連のコードを通じて動的に登録されます。したがって、次の分析は、APIServer が次のルーティング処理を提供できるようにする方法を見つけることです。

 GET / apis / apps / v1 / namespaces / { namespace } /デプロイメント/ { name }
POST / apis / apps / v1 / namespaces / { namespace } /デプロイメント

GET / apis / apps / v1 / namespaces / { namespace } / daemonsets / { name }
POST / apis / apps / v1 /名前空間/ {名前空間} /デーモンセット

go-restful の基本を理解した後、これら 3 つのサーバーがどのようにインスタンス化されるかを学習できます。

<<:  チップの革新に10年を費やしたAmazon Web Servicesは、デジタル変革のためのクラウドハードウェア「アクセラレータ」を提供します

>>:  クラウド ストレージのセキュリティ: データ暗号化メカニズムとセキュリティ レベルの簡単な分析

推薦する

友好的なリンクを交換する際に注意すべき「型破りな」側面(I)

ウェブサイトの最適化プロセスにおいて、友好リンクの交換は最も重要な部分の一つです。友好リンクを交換す...

Baiduは非常に謙虚で、個々のウェブマスターからPVを増やす方法を学んでいます。

Baidu News に小さな変更を加えただけで、誰にも気づかれずに PV が 2 倍になりました。...

企業の公会計の効率的な運用は難しい。どう打開するか?

現在、企業は無限のマーケティングモデルの中で常に革新と探求を求めています。Weiboマーケティングの...

JVM仮想マシンの全体構造とオブジェクトメモリ割り当ての分析

[[414275]] JVM仮想マシンの全体構造の分析全体構造の紹介jvm は次のように分かれていま...

Qvodは著作権侵害で2億6000万元の罰金を科される可能性がある。これは中国のインターネット企業に課された罰金としては過去最高額だ。

【世界技術総合レポート】経済観察報は20日午後、深セン市市場監督管理局が行政処罰審問案の「通知」を提...

タオバオの野望:キャッシュバック型のタオバオ顧客を禁止し、業界のクローズドループを構築する

タオバオは、咳をするだけで広範囲に影響を及ぼすほど巨大だ。タオバオ・アライアンスが来年からキャッシュ...

SEO効果評価指標について

ビジネス目標を決定することは、SEO プロジェクトを開始する前に実行できる最も重要なことの 1 つで...

テンセントミーティングが中国で初めてSOC2タイプ2監査に合格したビデオ会議製品に

Tencent Meeting は再び国際的に権威のある組織から認められました。 Tencent M...

ウェブサイトのホームページでは、ランダムな製品を呼び出して毎日スナップショットを更新しています

誰もが新しいものが好きで、検索エンジンのクローラーも新しいものが好きです。SEO の友人の中には、ウ...

業界のウェブサイトから効果的なキーワードを合理的に抽出する方法

みなさんこんにちは。私はHongtu Internetです。数日前、エンジニアリング情報ネットワーク...

世界人工知能会議: AWS が人工知能と機械学習の新たなトレンドを明らかに

AWS は、2019 年の世界人工知能会議 (WAIC) で、Amazon Transcribe 自...

Inspur Cloud が福建省人民病院の「1+1+N」スマート病院構築を支援

病院に直接行かなくても遠隔ビデオで診療を受けることができます。医師はカルテを見なくても患者の病歴や診...

Google 検索が 3 つの重要な変更と SEO への影響を発表

全文は、こちらの記事をご覧ください:「GOOGLE 検索が 20 周年に発表した 3 つの重要な調整...

外部リンクは過去のものになりつつあるのでしょうか?どのように見るべきか

最近、百度のアルゴリズムは絶えず更新されており、止まることはありません。6月から今まで、波が次々とあ...

アリババクラウドは、自社開発の第4世代神龍アーキテクチャを搭載し、RDMA強化インスタンスを含む多数の新製品をリリースした。

12月21日、アリババクラウドは自社開発の神龍アーキテクチャをベースにしたRDMA強化インスタンス、...