April 2012 Archives

Ubic - status report

It's been almost a year since my last Ubic post.
So just a quick remainder: Ubic is a polymorphic service manager which makes creating daemons easy, while being extensible in a several different ways.
(github; cpan).

This post is going to be pretty long.
If the rest of it is tl;dr for you, but you have any opinion about what constitutes a perfect service manager / daemonizer tool, or about what would convince you to use one, please consider commenting anyway :)

Technical improvements

The most important improvement was the addition of ini config files. Now you can write this:
# cat /etc/ubic/service/foo.ini
[options]
bin = sleep 100
instead of this:
# cat /etc/ubic/service/foo
use Ubic::Service::SimpleDaemon;
Ubic::Service::SimpleDaemon->new({
  bin => 'sleep 1000',
});
This is important for reaching to people outside of perl community. But I'll get back to this a bit later. (Of course, perl-style configs are not going anywhere.)


Ubic::Service::SimpleDaemon now accepts 'cwd' and 'env' options.
There's still a lot SimpleDaemon can't do, but I'm considering renaming it to Ubic::Service::Daemon before it's too late.

Thanks to Dmitry Yashin, we got the proper FreeBSD port.

And then there's some smaller stuff:

  • Command-line ubic script now doesn't require '--force' when operating multiservices; this feature was annoying, so I removed it. (--force is still required for starting/stopping *everything*, though.)

  • Dmitry Yashin helped to get rid of LWP::UserAgent dependency by implementing the tiny Ubic::UA http useragent;

  • process guid (identifier which makes ubic pidfiles safer) calculation code was broken for a couple of releases, but I finally fixed it now;

  • there was an annoying bug on ext4, which broke services after reboot because empty pidfiles were considered invalid (I hate non-transactional POSIX filesystem semantics...);

  • finally, I butchered quite a few releases with stupid bugs and typos; now I know better and always upload trial releases first :) (cpantesters is great, even though it's a bit unstable lately);


There were also several releases of various Ubic::Service::* distributions:

  • Yury Zavarin wrote Ubic::Service::ZooKeeper and Ubic::Service::MongoDB for running Zookeeper and MongoDB as services;

  • I wrote Ubic::Service::InitScriptWrapper as a fun proof-of-concept for representing init scripts as ubic services (why would you want to do that? well, you would magically get your service monitored by the watchdog, at very least... also, colored command-line ubic script.)

  • William Wolf uploaded Ubic::Service::Starman just two days ago. I've been very happy to discover it - this is the first time someone not from our Yandex team releases an Ubic::Service::* extension.

Marketing :)

I couldn't go to YAPC::EU last year, so Alex Kapranoff gave the talk about Ubic for me.

This year at Perl Workshop in Israel, Thomas Maier showed these slides.

I myself talked about Ubic twice in Moscow - on DevConf 2011 (there were less than 10 people there, so I almost forgot about it).
And then I gave the talk at my $job at Yandex.
Yandex is pretty big these days, and now there are 11 projects using Ubic, and even more are going to; there were just 4 a year ago (Hope I won't get fired for violating my NDA ;) ).

Another cool thing that happened: Dancer now lists Ubic as one of the ways to create a service from an app.


All in all, I feel like this is still not enough :)
There are just 5 people on irc.perl.org's #ubic channel, including me.
There are no regular contributors besides me. (This is not a problem per se, but I usually hesitate to add features unless I'm going to use it or I know a user who's going to use it. Otherwise, it's just the dead code. "Every good work of software starts by scratching a developer's personal itch.").
So what am I going to do about it?

Where are we going now?

There are two things I'm trying to achieve with Ubic:


  • Providing the flexible and extensible platform;

  • Giving a useful functionality out-of-the-box.

Ubic was always intended to be flexible and extensible. Earlier its single-line description was "flexible perl-based service manager". I recently replaced it with "polymorphic service manager".
Replacing "flexible" with "polymorphic" is a minor change, removing "perl-based" from description is more important. It means Ubic can be used by people outside of perl community.
And at Yandex, they already do.
Our NodeJS guys use it and even try to promote it to Node community. Our sysadmins use it and generally like it. We even rewrote some system init scripts with it. (rsync init script, for example - it died because of OOM sometimes, it was pretty annoying.)
So, please recommend Ubic to non-perl folks you know :)

BTW, what does "flexible" mean?
There are 3 aspects for it:


  • ubic services are represented as perl objects which conform to Ubic::Service interface, but can have different implementations;

  • ubic service tree is usually populated by loading files from /etc/ubic/service/, but by using multiservices mechanism it can be populated dynamically;

  • you can describe services with .ini configs, and can even implement your own config loaders (implement Ubic::ServiceLoader::Ext::js, describe services in js)

Of course, Ubic still have to be extended in Perl.
...Unless you bridge Perl-based Ubic API to some IPC API,using Ubic::Service::InitScriptWrapper or some other implementation. (Ubic started as LSB-compatible service manager, but that's not the main reason for its existence anymore. You could implement Ubic::Service analogue in JS, or in IPC but return status not via exit code but via stdout.)

There are many things you can do once all your services are accessible via common API:


  • global watchdog (included in core Ubic distribution)

  • http ping service (included in core Ubic distribution)

  • html frontend with start/stop buttons (here's an attempt to build such frontend; unfortunately, its development is on indefinite hiatus right now)

  • decorating services with additional functionality (you can do it with inheritance/composition)

  • binding services from other service managers to ubic; Ubic::Service::InitScriptWrapper does this for init scripts, and we can try the similar approach for daemontools, upstart, etc.

Of course, you can't just invent an API and expect people to start using it.
Nobody would adopt PSGI if there were no Plack; you have to provide some useful stuff out-of-the-box.
So, without promising anything, here's a list of things I'd like to implement next:


  • Lots of people ask me for ulimit support in SimpleDaemon;

  • Related to the previous point, some people get confused by ubic's user/group semantics (ubic calls setuid to user as soon as possible, not after forking to daemon's process); so, we need to support the tranditional behaviour as well;

  • I'd love to add Windows support one day, and then declare Ubic "the only cross-platform service manager"... unfortunately, my knowledge of Windows is lacking;

  • reload_signal option;

  • parallel restart;

  • ubic fix-permissions command;

  • YAML configs (since ini configs allow only one level of options, and some SimpleDaemon options already require more (for example, 'env'))

I'm also thinking from time to time about adding a common mechanism for adding additional functionality to services without explicit inheritance.
Something like roles.
For example: "do you want to restart your daemon when code changes? take Ubic::Service::SimpleDaemon and add Ubic::Middleware::CodeChange". Or you might want to restart on memory leaks. Or simply once in a while.
We could then support such middlewares (wrappers? roles?) in ini/yaml configs, so that even non-perl users would use them.

Last but not least, I'm working on a proper website for Ubic.
I'm not ready to show it to public just yet, but hopefully it'll be ready soon.

Epilogue

Summarizing:


  • Ubic is not just for perl folks now; please recommend it to other people who might want to try it;

  • There are many features, but even more is to be done, and the main restraining factor right now is the number of active users and contributors (I don't want to add stuff just because someone may need it...).

So I'll repeat my initial question once again: how do you think a perfect service manager should work? What would convince you to use one? Which important features are missing in Ubic right now?

About Vyacheslav Matyukhin

user-pic I wrote Ubic. I worked at Yandex for many years, and now i'm building my own startup questhub.io (formerly PlayPerl). I'm also working on Flux, streaming data processing framework. CPAN ID: MMCLERIC.