atomizer

所属分类:超算/并行计算
开发工具:GO
文件大小:0KB
下载次数:0
上传日期:2023-05-16 12:03:21
上 传 者sh-1993
说明:  想象一下,跨多个云实例和数据中心的数千台机器以最小的深度为您执行同步处理...,
(Imagine thousands of machines across multiple cloud instances and data centers executing simultaneous processing for you with minimal deployment effort. Enter Atomizer - a Go library that facilitates massively parallel and distributed computing. Fashioned after Go itself using similar CSP paradigms.)

文件列表:
.golangci.yml (3914, 2023-12-13)
.pre-commit-config.yaml (1144, 2023-12-13)
.secrets.baseline (2323, 2023-12-13)
LICENSE (11357, 2023-12-13)
atom.go (421, 2023-12-13)
atomizer.go (10102, 2023-12-13)
atomizer_exported.go (3613, 2023-12-13)
atomizer_mock_test.go (6588, 2023-12-13)
atomizer_test.go (17923, 2023-12-13)
conductor.go (913, 2023-12-13)
docs/ (0, 2023-12-13)
docs/definitions.md (1064, 2023-12-13)
docs/design-methodologies.md (4433, 2023-12-13)
docs/media/ (0, 2023-12-13)
docs/media/design.jpg (166843, 2023-12-13)
docs/media/design_small.jpg (61559, 2023-12-13)
electron.go (3311, 2023-12-13)
electron_test.go (3225, 2023-12-13)
error.go (1930, 2023-12-13)
error_test.go (2398, 2023-12-13)
event.go (2173, 2023-12-13)
event_test.go (1237, 2023-12-13)
go.mod (407, 2023-12-13)
go.sum (4256, 2023-12-13)
helpers.go (1007, 2023-12-13)
instance.go (4117, 2023-12-13)
instance_test.go (4298, 2023-12-13)
properties.go (2944, 2023-12-13)
properties_test.go (4270, 2023-12-13)
... ...

# Atomizer - Massively Parallel Distributed Computing [![CI](https://github.com/devnw/atomizer/actions/workflows/build.yml/badge.svg)](https://github.com/devnw/atomizer/actions) [![Go Report Card](https://goreportcard.com/badge/go.atomizer.io/engine)](https://goreportcard.com/report/go.atomizer.io/engine) [![codecov](https://codecov.io/gh/devnw/atomizer/branch/main/graph/badge.svg)](https://codecov.io/gh/devnw/atomizer) [![Go Reference](https://pkg.go.dev/badge/go.atomizer.io/engine.svg)](https://pkg.go.dev/go.atomizer.io/engine) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) Created to facilitate simplified construction of distributed systems, the Atomizer library was built with simplicity in mind. Exposing a simple API which allows users to create "Atoms" ([def](docs/definitions.md#atom)) that contain the atomic elements of process logic for an application, which, when paired with an "Electron"([def](docs/definitions.md#electron)) payload are executed in the Atomizer runtime. ## Index - [Atomizer - Massively Parallel Distributed Computing](#atomizer---massively-parallel-distributed-computing) - [Index](#index) - [Getting Started](#getting-started) - [Test App](#test-app) - [Conductor Creation](#conductor-creation) - [Atom Creation](#atom-creation) - [Electron Creation](#electron-creation) - [Properties - Atom Results](#properties---atom-results) - [Events](#events) - [Element Registration](#element-registration) - [Init Registration](#init-registration) - [Atomizer Instantiation Registration](#atomizer-instantiation-registration) - [Direct Registration](#direct-registration) ## Getting Started To use Atomizer you will first need to add it to your module. ```go go get -u go.atomizer.io/engine@latest ``` I highly recommend checking out the [Test App](#test-app) for a functional example of the Atomizer framework in action. To create an instance of Atomizer in your app you will need a Conductor ([def](docs/definitions.md#conductor)). Currently there is an AMQP conductor that was built for Atomizer which can be found here: [AMQP](https://github.com/devnw/amqp), or you can create your own conductor by following the [Conductor creation instructions](#conductor-creation). Once you have registered your Conductor using one of the [Element Registration](#element-registration) methods then you must create and register your Atom implementations following the [Atom Creation](#atom-creation) instructions. After registering at least one Conductor and one Atom in your Atomizer instance you can begin accepting requests. Here is an example of initializing the framework and registering an Atom and Conductor to begin processing. ```go // Initialize Atomizer a := Atomize(ctx, &MyConductor{}, &MyAtom{}) // Start the Atomizer processing system err := a.Exec() if err != nil { ... } ``` Now that the framework is initialized you can push processing requests through your Conductor for your registered Atoms and the Atomizer framework will execute the Electron([def](docs/definitions.md#electron)) payload by bonding it with the correct registered Atom and returning the resulting `Properties` over the Conductor back to the sender. ## Test App Since the concepts here are new to people seeing this for the first time a capstone team of students from the University of Illinois Springfield put together a test app to showcase a working implementation of the Atomizer framework. This Test App implements a MonteCarlo *π* simulation using the Atomizer framework. The Atom implementation can be found here: [MonteCarlo *π*](https://github.com/devnw/montecarlopi). This implementation uses two Atoms. The first Atom "MonteCarlo" is a [Spawner](docs/design-methodologies.md#atom-types) which creates payloads for the Toss Atom which is an [Atomic](docs/design-methodologies.md#atom-types) Atom. To run a simulation follow the steps laid out in [this blog post](https://benjiv.com/pi-day-special-2021/) which will describe how to pull down a copy of the Monte Carlo π docker containers running Atomizer. [Atomizer Test Console](https://github.com/devnw/atomizer-test-console) This test application will allow you to run the same MonteCarlo *π* simulation from command line without needing to setup a NodeJS app or pull down the corresponding Docker container. Thank you to - Matthew N Meyer ([@MatthewNormanMeyer](https://github.com/MatthewNormanMeyer)) - Megan Pugliese ([@mugatupotamus](https://github.com/mugatupotamus)) - Nick Heiting ([@nheiting](https://github.com/nheiting)) - Benji Vesterby ([@benjivesterby](https://github.com/benjivesterby)) ## Conductor Creation Creation of a conductor involves implementing the Conductor interface as described in the Atomizer library which can be seen below. ```go // Conductor is the interface that should be implemented for passing // electrons to the atomizer that need processing. This should generally be // registered with the atomizer in an initialization script type Conductor interface { // Receive gets the atoms from the source // that are available to atomize Receive(ctx context.Context) <-chan *Electron // Complete mark the completion of an electron instance // with applicable statistics Complete(ctx context.Context, p *Properties) error // Send sends electrons back out through the conductor for // additional processing Send(ctx context.Context, electron *Electron) (<-chan *Properties, error) // Close cleans up the conductor Close() } ``` Once you have created your Conductor you must then register it into the framework using one of the [Element Registration](#element-registration) methods for Atomizer. ## Atom Creation The Atomizer library is the framework on which you can build your distributed system. To do this you need to create "Atoms"([def](docs/definitions.md#atom)) which implement your specific business logic. To do this you must implement the Atom interface seen below. ```go type Atom interface { Process(ctx context.Context, c Conductor, e *Electron,) ([]byte, error) } ``` Once you have created your Atom you must then register it into the framework using one of the [Element Registration](#element-registration) methods for Atomizer. ## Electron Creation Electrons([def](docs/definitions.md#atom)) are one of the most important elements of the Atomizer framework because they supply the `data` necessary for the framework to properly execute an Atom since the Atom implementation is pure business logic. ```go // Electron is the base electron that MUST parse from the payload // from the conductor type Electron struct { // SenderID is the unique identifier for the node that sent the // electron SenderID string // ID is the unique identifier of this electron ID string // AtomID is the identifier of the atom for this electron instance // this is generally `package.Type`. Use the atomizer.ID() method // if unsure of the type for an Atom. AtomID string // Timeout is the maximum time duration that should be allowed // for this instance to process. After the duration is exceeded // the context should be canceled and the processing released // and a failure sent back to the conductor Timeout *time.Duration // CopyState lets atomizer know if it should copy the state of the // original atom registration to the new atom instance when processing // a newly received electron // // NOTE: Copying the state of an Atom as registered requires that ALL // fields that are to be copied are **EXPORTED** otherwise they are // skipped CopyState bool // Payload is to be used by the registered atom to properly unmarshal // the []byte for the actual atom instance. RawMessage is used to // delay unmarshal of the payload information so the atom can do it // internally Payload []byte } ``` The most important part for an Atom is the `Payload`. This `[]byte` holds data which can be read in your Atom. This is how the Atom receives state information for processing. Decoding the `Payload` is the responsibility of the Atom implementation. The other fields of the Electron are used by the Atomizer internally, but are available to an Atom as part of the Process method if necessary. Electrons are provided to the Atomizer framework through a registered Conductor, generally a Message Queue. ## Properties - Atom Results The results of Atom processing are contained in the `Properties` struct in the Atomizer library. This struct contains metadata about the processing that took place as well as the results or errors of the specific Atom which was executed from a request. ```go // Properties is the struct for storing properties information after the // processing of an atom has completed so that it can be sent to the // original requestor type Properties struct { ElectronID string AtomID string Start time.Time End time.Time Error error Result []byte } ``` The Result field is the `[]byte` that is returned from the Atom that was executed, and in general the Error property contains the `error` which was returned from the Atom as well, however if there are errors in processing an Atom that are not related to the internal processing of the Atom that error will be returned on the `Properties` struct in place of the Atom error as it is unlikely the Atom executed. ## Events Atomizer exports a method called `Events` which returns an `go.devnw.com/events.EventStream` and `Errors` which returns an `go.devnw.com/events.ErrorStream`. When you call either of these methods with a buffer of 0 they utilize an internal channel within the `go.devnw.com/event` package which then **MUST** be monitored for events/errors or it will block processing. The purpose of these methods is to allow for users to monitor events occurring inside of Atomizer. Because these use channels either pass a buffer value to the method or handle the channel in a `go` routine to keep it from blocking your application. Along with the `Events` and `Errors` methods, Atomizer exports two important structs. `atomizer.Error` and `atomizer.Event`. These contain information such as the `AtomID`, `ElectronID` or `ConductorID` that the event applies to as well as any message or error that may be part of the event. Both `atomizer.Error` and `atomizer.Event` implement the `fmt.Stringer` interface to make for easy logging. `atomizer.Error` also implements the `error` interface as well as the `Unwrap` method for nested errors. `atomizer.Event` also implements the `go.devnw.com/events.Event` interface to ensure the the `event` package can correctly handle the event. ```go // Event indicates an atomizer event has taken // place that is not categorized as an error // Event implements the stringer interface but // does NOT implement the error interface type Event struct { // Message from atomizer about this error Message string `json:"message"` // ElectronID is the associated electron instance // where the error occurred. Empty ElectronID indicates // the error was not part of a running electron instance. ElectronID string `json:"electronID"` // AtomID is the atom which was processing when // the error occurred. Empty AtomID indicates // the error was not part of a running atom. AtomID string `json:"atomID"` // ConductorID is the conductor which was being // used for receiving instructions ConductorID string `json:"conductorID"` } // Error is an error type which provides specific // atomizer information as part of an error type Error struct { // Event is the event that took place to create // the error and contains metadata relevant to the error Event *Event `json:"event"` // Internal is the internal error Internal error `json:"internal"` } ``` ## Element Registration There are three methods in Atomizer for registering `Atoms` and `Conductors`. - [Init Registration](#init-registration) - [Atomizer Instantiation Registration](#atomizer-instantiation-registration) - [Direct Registration](#direct-registration) ### Init Registration Atoms and Conductors can be registered in an `init` method in your code as seen below. ```go func init() { err := atomizer.Register(&MonteCarlo{}) if err != nil { ... } } ``` ### Atomizer Instantiation Registration Atoms and Conductors can be passed as the second argument to the `Atomize` method. This parameter is variadic and can accept *any* number of registrations. ```go a := Atomize(ctx, &MonteCarlo{}) ``` ### Direct Registration Direct registration happens when you use the `Register` method directly on an Atomizer instance. NOTE: The `Register` call can happen before or after the `a.Exec()` method call. ```go a := Atomize(ctx) // Start the Atomizer processing system err := a.Exec() if err != nil { ... } // Register the Atom err = a.Register(&MonteCarlo{}) if err != nil { ... } ```

近期下载者

相关文件


收藏者