|
NAMEUbic::Manual::Multiservices - Multiservices - dynamic generation of service treeVERSIONversion 1.58DESCRIPTIONMultiservice is an object which tells ubic what services you have.In other words, multiservices populate service tree by providing simple list/get, virtual-filesystem-like API. This API is documented in Ubic::Multiservice abstract class. Even the configs in your ubic service dir are loaded by Ubic::Multiservice::Dir instance. This instance is named root_service and can be obtained via "root_service()" method in Ubic module. EXAMPLESThere are several common use cases for multiservices.Simple multiservice with several partsSome services are meant to work together. For example, your project can consist of PSGI app, memcached process and nginx frontend (yes, you can run nginx with ubic if you want to). You can just put them all in subdirectory in your service dir:$ ls -1 /etc/ubic/service/my/ app memcached nginx They all will be loaded by root multiservice, since "Ubic::Multiservice::Dir" does traverse subdirectories: $ ubic status my my my.app running my.memcached running my.nginx running (You can see another example in "ubic.*" services which you have out of the box in common ubic installation). On the other hand, maybe your three services are tightly coupled and you don't want to copy-paste memcached port both to my.app service declaration and my.memcached. In this case, you can create all three services in one file: # content of the file /etc/ubic/service/my use Ubic::Multiservice::Simple; my $app_service = ...; my $memcached_service = ...; my $nginx_service = ...; Ubic::Multiservice::Simple->new({ app => $app_service, memcached => $memcached_service, nginx => $nginx_service, }); Simple multiservice with several workersThis example is similar to the previous one, but it solves a different task.What if you have only one program, but want to run several instances of it? For example, your process may be some kind of a fetching robot which fetches the list of urls and stores them in external database, and you want to make it run in parallel, either because with to utilize multiple CPUs, or you're just don't want to learn parallel programming techniques. Anyway, here is the example: # content of the file /etc/ubic/service/robot use Ubic::Multiservice::Simple; use Ubic::Service::SimpleDaemon; my $robot_service = Ubic::Service::SimpleDaemon->new(bin => "/usr/bin/fetching_robot.pl"); Ubic::Multiservice::Simple->new({ map { "robot$_" => Ubic::Service::SimpleDaemon->new(bin => "/usr/bin/fetching_robot.pl") } (1..10) }); Note that you could easily alter some properties of each service, for example, pass "stdout" option to SimpleDaemon constructor with different log file for every process. By the way, this example is easy and powerful, but please consider other options if your number of services will get high (more than tens of workers). Ubic watchdog checks each service separately and forks once or even twice per service, so it can create pretty high CPU overhead. Dynamic multiservice with external configsLet's assume that a fetching robot from the previous example uses files in multiple local directories "/var/spool/fetching_robot/queues/*" as the list of urls to process. Let's also assume that you don't want to run multiple workers to parallel your fetching, but you want to process each queue in separate process.You may declare one service per queue, but it's double work. And there is a better solution: let's implement multiservice which creates as many services as there are queues. # content of the file /etc/ubic/service/robot use parent qw(Ubic::Multiservice); my $queue_dir = "/var/spool/fetching_robot/queues"; sub new { return bless {} => shift; } sub service_names { return map { s{^\Q$queue_dir/\E}{} } glob "$queue_dir/*"; } sub simple_service { my ($self, $name) = @_; return Ubic::Service::SimpleDaemon->new( bin => ["/usr/bin/fetching_robot.pl", "--queue-dir", "$queue_dir/$name"] ); } __PACKAGE__->new; You could also implement this multiservice as simple service, but this code is theoretically more efficient: it doesn't create subservice object until it is asked to do so. You can apply the similar technique to write service declarations in any config format you want, transforming these configs into service objects by some multiservice. Important side note: don't forget to stop the service before removing the config (or in this case, queue dir). Ubic won't remember that service was running if it's not present in service tree! AUTHORVyacheslav Matyukhin <mmcleric@yandex-team.ru>COPYRIGHT AND LICENSEThis software is copyright (c) 2015 by Yandex LLC.This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
Visit the GSP FreeBSD Man Page Interface. |