titan

package module
v0.0.0-...-471d7c0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 21, 2016 License: MIT Imports: 18 Imported by: 2

README

Titan

Build Status GoDoc

Titan is a messaging server for delivering chat messages to mobile devices and browsers. For each delivery target, the server uses different protocol. i.e. GCM for Android apps, WebSocket for browsers, etc. The server is completely written in Go and makes huge use of goroutines and channels. Client server communication is full-duplex bidirectional.

Getting Started

import "github.com/titan-x/titan"

s, _ := titan.NewServer(":80")
s.ListenAndServe()

An example is deployed at wss://titan-x.herokuapp.com. You can use the provided Titan client and start experimenting right away.

You can also use the provided command line tool to start a Titan server:

cd github.com/titan-x/titan
go install -v ./cmd/titan
titan

Architecture

Messaging server utilizes device specific delivery infrastructure for notifications and messages; GCM for Android, APNS for iOS, and WebSocket for the Web browsers. Any message too big for GCM/APNS size limit will be notified but will be delivered over WebSocket.

Following is the simplified server architecture:

+--------------------------------------------------------+
|  GCM  |  APNS  |  JSON-RPC over WebSockets (Neptulon)  |
+--------------------------------------------------------+
|                      RPC Methods                       |
+--------------------------------------------------------+
|        User Database      |       Message Queue        |
+--------------------------------------------------------+

Client-Server Protocol

(Titan server is entirely built on top of Neptulon framework. You can browse Neptulon repository to get more in-depth info.)

Client server communication protocol is based on JSON RPC 2.0 specs. Both mobile devices and the Web browsers utilizes the WebSocket endpoint. All connections are secured with TLS.

Client Authentication

First-time registration is done through Google+ OAuth 2.0 flow. After a successful registration, the connecting device receives a JSON Web Token to be used for successive connections.

Typical Client-Server Communication

Client-server communication sequence is pretty similar to that of XMPP, except we are using JSON RPC packaging for messages.

[Client]                    [Server]
+                                  +
|<<<------GCM Notification---------|
|                                  |
|                                  |
|------------[auth.jwt]--------->>>|
|                                  |
|<<<-----------[ACK]---------------|
|                                  |
|                                  |
|<<<---------[msg.recv]------------|
|                                  |
|--------------[ACK]------------>>>|
|                                  |
|                                  |
|------------[msg.send]--------->>>|
|                                  |
|<<<-----------[ACK]---------------|
+                                  +

Any message that was not acknowledged by the client will be delivered again (hence at-least-once delivery principle). Client implementations will be ready to handle occasional duplicate deliveries of messages by the server. Message IDs will remain the same for duplicates.

Command Line Tool

You can install titan command to $GOPATH/bin directory to be universally available from your shell using following:

go install -v ./cmd/titan
titan

Or you can simply use go run cmd/titan/main.go without installing.

Docker Build and Deployment

To build and run a Docker container:

docker build -t titan .
docker run --publish 80:80 --name titan --rm titan

The --publish flag tells docker to publish the container's port 80 on the external port 80. The --name flag gives our container a predictable name to make it easier to work with. The --rm flag tells docker to remove the container image when the Titan server exits.

Now you can browse to the WebSocket Test Page and type in ws://192.168.99.100:80 (you might need to replace the IP with the IP of you Docker host depending on your system).

One you're done, shut down the running container from another terminal window:

docker stop titan

Docker Registry

You can pull prebuilt Titan Docker image via:

docker pull titanx/titan

You can find all the published tags at Docker Hub: titanx/titan

You can also reference the repo by URL using docker.io/titanx/titan

If something goes wrong and you want to stop all containers and delete all containers & images:

# stop then delete all containers
docker stop $(docker ps -a -q)
docker rm -f $(docker ps -a -q)
# delete all images
docker rmi -f $(docker images -q)

Heroku Deployment

Deploy

Procfile and app.json are ready making this repo readily available for Heroku deployment. You can start by clicking the above button.

A sample deployment is at wss://titan-x.herokuapp.com where you can connect with any Titan client.

AWS Deployment

data/aws module adds support for Amazon Web Services using AWS SDK for Go. Consult Configuration section of the SDK guide for configuration options. In most cases, all info will be read from the deployed EC2 instance (with an IAM role attached), and you won't have to do anything.

Users

NBusy server is running on top of Titan server. You can visit its repo to see a complete use case of Titan server.

Testing

All the tests can be executed with GORACE="halt_on_error=1" go test -race -cover ./... command. Optionally you can add -v flag to observe all connection logs. Integration tests require environment variables defined in the next section. If they are missing, integration tests are skipped.

Environment Variables

Following environment variables needs to be present on any dev or production environment:

export GOOGLE_API_KEY=
export GOOGLE_PREPROD_API_KEY=

Logging and Metrics

Only actionable events are logged (i.e. server started, client connected on IP ..., client disconnected, etc.). You can use logs as event sources. Anything else is considered telemetry and exposed with expvar. Queue lengths, active connection/request counts, performance metrics, etc. Metrics are exposed via HTTP at /debug/vars in JSON format.

Performance Notes

The messaging server is designed to make max usage of available CPU resources. However exceeding 100% CPU usage will cause a memory usage spike as marshalled/unmarshalled messages and other allocated byte buffers will have to reside in memory much longer. Ideally, 95% CPU usage should trigger the clustering mechanism which should spawn more server instances. Currently there is no clustering support built-in, but it is a priority.

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func InitConf

func InitConf(env string)

InitConf initializes application configuration. If given, env parameter overrides environment configuration. This is useful for testing.

Types

type App

type App struct {
	Env   string // One of the following: development, test, production.
	Debug bool   // Enables verbose logging to stdout.
	Port  string // Listener port.
}

App contains the global application variables.

func (*App) JWTPass

func (app *App) JWTPass() string

JWTPass retrieves the JWT signing password.

type AuthGoogReqParams

type AuthGoogReqParams struct {
	// contains filtered or unexported fields
}

AuthGoogReqParams is the Google+ OAuth token wrapper.

type Config

type Config struct {
	App App
	GCM GCM
}

Config describes the global configuration for the titan server.

var Conf Config

Conf contains all the global configuration for the titan server.

type GCM

type GCM struct {
	CCSHost  string
	SenderID string
}

GCM describes the Google Cloud Messaging parameters as described here: https://developer.android.com/google/gcm/gs.html

func (*GCM) APIKey

func (gcm *GCM) APIKey() string

APIKey gets the GCM API key from environment variable.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server wraps a listener instance and registers default connection and message handlers with the listener.

func NewServer

func NewServer(addr string) (*Server, error)

NewServer creates a new server.

func (*Server) Close

func (s *Server) Close() error

Close the server and all of the active connections, discarding any read/writes that is going on currently. This is not a problem as we always require an ACK but it will also mean that message deliveries will be at-least-once; to-and-from the server.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

ListenAndServe starts the Titan server. This function blocks until server is closed.

func (*Server) SetDB

func (s *Server) SetDB(db data.DB) error

SetDB sets the database implementation to be used by the server. If not supplied, in-memory database implementation is used.

func (*Server) SetQueue

func (s *Server) SetQueue(queue data.Queue) error

SetQueue sets the queue implementation to be used by the server. If not supplied, in-memory queue implementation is used.

Directories

Path Synopsis
cmd
aws
Package aws provides AWS implementation of data interfaces.
Package aws provides AWS implementation of data interfaces.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL