電子公共サービスを扱う会社で働いていたとき、私たちがやったまたは近代化したシステムが時間とともに非常に複雑になったことにいつも驚きました。 彼らは大量の依存症でゆるくなり、信頼できなくなりました。 赤い巨人のように、システムは膨張し、いつでも崩壊する可能性があります。
システムの開発は、機能の拡張だけでなく、システムの削減と最適化でもあります。
it球体でも同じことが起こっているように思えます。 Windows 8.1を見てください。Windows8.1はマーケティングのアイデアの犠牲者です。 Azureusトレントクライアントを覚えていますか? これがVuzeメディアプロセッサ全体です。
私はいつも自分のためにプログラムを書きたかった。 単純なもので複雑ではないもの。Webインターフェースを介して動作します。トップタスクマネージャーのように、ブラウザを介してのみ動作します。 この種の機能を実行できる多くのシステムがありますが、それらはシリーズのものです。
PHP + Apache + MySQL + ...を提供します。 つまり 私の意見では、不必要に「肥大化」しました。
言語を選択したとき、GOに注意を向けました。 最近、「habr」で彼について多くのことが書かれています。
彼に関する本や記事を読み始めるとすぐに、私はこの驚くべき簡潔で自然な言語にすぐに恋をしました。 どれだけクリエーターの意見が私の意見と一致したかに感銘を受けました
以下に例を示します。
- テンプレートはありません。 テンプレートはマクロの遺産です。 アルゴリズムとクラスを一般化する問題、テンプレートの使用を解決することは、コードの理解を一桁複雑にしました。
- GOには継承がありません。 多重継承がないため、通常の継承はありません。 継承の場所は、より明確な埋め込みメカニズムとインターフェイスを使用します。
- デフォルトでは、コンパイルされたファイルは静的にリンクされます。 これは、依存関係を気にせずに任意のシステムで実行できることを意味します。
- すぐに使用できるクロスコンパイルがサポートされています。
- 単体テストがあります。
プロセスおよびシステム統計に関する情報を取得するために、wtopはproc仮想ファイルシステムを使用します。 したがって、それはそれを使用するすべてのシステムで動作します(androidおよび... Plan9についてはわかりません)。 バックエンドとして、goに組み込まれたhttpサーバーが使用されます。 フロントエンドのhtml / javaスクリプトとして。 frontenfとバックエンドの間でデータを交換するために、jsonメッセージが使用されます。 開始するには、実行可能ファイルを実行し、ブラウザでxxxx :9977 / index.htmlに移動します
上記のスクリーンショットは、データを収集するときに、Texas Instruments 4430デュアルコアプロセッサ、1.2 GHzを搭載した電話機で、wtopがプロセッサ時間の約10%を消費し、メモリが4.5メガバイトしかないことを示しています。 デスクトップ上で、ubuntuオペレーティングシステムを使用-プロセッサ時間の0.5%と同じ4.5 MBのメモリ 5秒以内にクライアントからの要求がなかった場合、新しいjson要求が彼を起こすまで、彼は眠りに落ちます。
次は、プログラムコード内のハイライトを使用する任意の構造を記述します。
http.Requestオブジェクトを受信すると、ProduceJsonRequestメソッドはリクエスト本文を解析し、リクエストオブジェクトを作成します。 次に、Dispatchメソッドによってディスパッチ可能です:
func (fabric *JsonFabric) ProduceJsonRequest(request *http.Request) (Request, error) { bodyData, err := ioutil.ReadAll(request.Body) if err != nil { stErr := "error: Can't read request body" log.Println(stErr) return nil, errors.New(stErr) } defer request.Body.Close() var basicRequest BasicRequest err = json.Unmarshal(bodyData, &basicRequest) if err != nil { stErr := "error: Can't parse basic data" log.Println(stErr) return nil, errors.New(stErr) } switch basicRequest.Type { case ServiceStatus: var serviceStateRequest ServiceStateRequest err := json.Unmarshal(bodyData, &serviceStateRequest) if err != nil { stErr := "error: Can't parse service state request" log.Println(stErr) return nil, errors.New("error: Can't parse service state request") } return serviceStateRequest, nil ...... ...... ...... } return nil, errors.New("error: Unknown request type")
func (requestSelector *RequestSelector) Dispatch(request Request, responseWriter http.ResponseWriter, httpRequest *http.Request) error { //don't need protect multiple read in different thread if selector, contains := requestSelector.selectorRequestMap[request.RequestType()]; !contains { stErr := "error: Usupported message type" log.Println(stErr) return errors.New(stErr) } else { return selector.Dispatch(request, responseWriter, httpRequest) } }
要求をディスパッチすると、対応するハンドラーの辞書が検索され、その後にその呼び出しが続きます。
リクエストの処理に興味深いものはありません。
関心はBatchJob構造によって提供されます。 これを施設で使用すると、特定のアクション(この場合は測定)の周期性を保証できます。
type BatchJob struct { Job func() runJob bool done chan bool } func (batchJob *BatchJob) Start() error { if batchJob.runJob { return errors.New("error: can't stop not stopped job") } if batchJob.Job == nil { return errors.New("error: empty job function") } if !batchJob.runJob { batchJob.done = make(chan bool, 1) } go batchJob.execution(batchJob.done) batchJob.runJob = true return nil } func (batchJob *BatchJob) IsRunning() bool { return batchJob.runJob } func (batchJob *BatchJob) Stop() error { if !batchJob.runJob { return errors.New("error: can't stop not stopted job") } batchJob.runJob = false isDone := <-batchJob.done if isDone { close(batchJob.done) return nil } return errors.New("error: failed stop job") } func (batchJob *BatchJob) execution(done chan bool) { for { if batchJob.runJob { batchJob.Job() } else { done <- true return } } }
これを行うために、各要求ハンドラーにはBatchJob構造のオブジェクトが含まれています。 測定機能への参照を使用して、Jobフィールドをインスタンス化します。
top.collectInfoJob.Job = top.collectInfo top.lastRequestTime = time.Now() err := top.collectInfoJob.Start()
上記で述べたように、5秒後に誰もサービスに問い合わせをしないと、彼は眠りに落ちます。
私の意見では、プログラムは非常にシンプルで論理的であることが判明しました。 各モジュールは特定の機能を実行し、互いに独立して動作できます。
すべてのソースコードはGitHubリポジトリgithub.com/Loafter/WebTopで入手できます。
私自身から、GOは驚くほど強力な言語であるともう一度言いたいと思います。 彼が新世代の言語の中で支配的な役割を果たすことを願っています。
最後まで読んだ人のために、異なるアーキテクチャ用にコンパイルされたバイナリへのリンクを提供します。
index.html -Webインターフェイス。
wtop-armv5-linux -Linux(Android)arm v5のバージョン。
wtop-armv6-linux -Linux(Android)arm v6のバージョン。
wtop-x64-linux -Linuxバージョン(Ubuntu ...など)X86-64。