Xref: utzoo comp.protocols.tcp-ip:12507 comp.protocols.nfs:1153 Path: utzoo!attcan!uunet!cs.utexas.edu!know!zaphod.mps.ohio-state.edu!uakari.primate.wisc.edu!sdd.hp.com!decwrl!sun-barr!newstop!sun!nibroc.Eng.Sun.COM!corbin From: corbin@nibroc.Eng.Sun.COM (John Corbin) Newsgroups: comp.protocols.tcp-ip,comp.protocols.nfs Subject: Re: Books on RPC programming? Message-ID: <140323@sun.Eng.Sun.COM> Date: 7 Aug 90 22:13:22 GMT References: <296@uucs1.UUCP> <28186@joshua.athertn.Atherton.COM> <140113@sun.Eng.Sun.COM> <46559@brunix.UUCP> Sender: news@sun.Eng.Sun.COM Reply-To: corbin@sun.UUCP (John Corbin) Organization: Sun Microsystems, Mountain View Lines: 75 In article <46559@brunix.UUCP> jhc@iris.brown.edu (Jim Coombs writes: >Do you discuss techniques for getting a server to fork() copies of >itself, one per client? I have been looking through the RPC 4.0 >distribution and am beginning to think that the RPC communications >model has been implemented too strictly to permit the reasonable use of >fork(). I can modify the code to implement an optional fork, but then >I find that the server does not shut down when the client shuts down. >I have no trouble implementing these requirements (e.g., keepalives) >when working at the socket level. > >If you have a way to do this, I would like to hear about it. Also, if >you have comments on the RPC communications model, that would be >interesting. Perhaps you do this already, but it would useful to >include a critique of RPC in your book: what is it good for and what is >it not good for, how should it be improved? I have not implemented a service that forks copies as you described above and the book does not specifically discuss this subject. The book has a section on implementing your own svc_run() routine and why you might want to do it. Something I forgot to mention in my original posting is that the book is based upong the 4.0 release of the RPC Library and that I am a novice user of the socket based API. I typically use the RPC Library in its vanilla form when programming applications (for portability reasons). I don't beleive that the RPC model was implemented too tight to allow the reasonable use of fork(). I don't know if you have already thought of this, but if you want one server process per client, you could have the parent process register via the portmapper. When it gets a request from a client, it could spawn a child process that would bind to a different port number than the parent process. The child would not register itself with the portmapper. The child would attach itself to a port using the necessary socket calls and then pass the socket descriptor into the svcXXX_create() routine. The child would specify a zero for the protocol argument to the svc_register() routine to prevent the child service from being registered with the portmapper and thus unregistering the parent. The child would then return its portnumber to the parent process which in turn would return the portnumber to the client. The client would then have to bind to this portnumber (i.e. passing in a filled in sockaddr_in, including the port number, to the clntXXX_create() routine. From then on you should be able to use the vanilla RPC routines. One of the advantages of the RPC library is that it allows you to do your own binding if you don't want to take advantage of the portmapper. For those of you that don't want to mess around with the socket API, you could register the children using dynamic program numbers. A potential problem of having one server process per client is that you have now limited the number of clients that your service can handle (bounded by max processes per user). Another approach is to do dynamic load balancing on your server by spawning X processes to handle incoming requests. Where X is a dynamic variable dependent upon the incoming request rate (or some averaged value) and of course application specific information (weighting of remote procedures). I have not done a rigorous study on this so I can't give you hard numbers. Some potential problems with this approach is that the port can become the bottleneck (if using UDP) and you will have to modify the svc_run() routine. An alternative to forking is the use of light weight processes or threads. When 4.0 first came out, I looked at spawning light weight processes for every incoming request to a server. The problem with doing this under 4.0 was that certain system calls would still block the entire server (i.e. reading data from a disk file). Sun provided a special library of non-blocking system calls that could be used but then you had to modify your application to handle non-blocking system calls. This could be a problem if you are using a special purpose library for which you don't have the source for (ex: ISAM library). The fix for this is to make the LWP primitives available as true system calls. I am just getting into the issues of true multi-threaded servers and do not have any examples or insight to provide. John Corbin (jcorbin@Sun.COM) NFS Group Sun Microsystems (These are my opinions and should not be construed as coming from my employer)