Search

@brendo, There might be a way. If we only start the session when there is data written to it or when the read function is called and the $_COOKIE['PHPSESSID'] variable is not null, the session should only be started when needed.

I haven't tested it yet; getting this project finished is a first priority, but I think it should work.

The problem is, AFAIK, $_SESSION array will always be empty until session_start is initialised. I didn't think to check the $_COOKIE array though, that could be a good place to start! A nice little rabbit hole for Christmas holidays :)

@brendo, if we take this on I think we should rework the entire session handling as it is now. From what I learnt, the current code is many years old, and times are changing... For instance, I think Cache-Ability is quite important for any website, and while the current code does a good job at keeping the session alive when multiple webservers share the same database it will most likely fail when there is a master-master replication setup and replication is lagging behind.

I have time to work on this (and the database stuff) mid January, would you be interested in joining me and Michael to get this rock-solid?

Sure

I have been experimenting with Varnish for my (Symphony) web app. I'd like to hear your thoughts on a very simple concept I have in mind.

In this app any personalized content is delivered using HTTPS. So I huddled together some simple rules:

  • Varnish listens on port 80, Apache on port 8080 (for Varnish) and 443 (for HTTPS).
  • Varnish unsets all client Cookie headers.
  • Varnish unsets all Set-Cookie headers set by Symphony.
  • Varnish sets a TTL for everything and always attempts to return the cached object.

So basically what I do is:

  • Cache everything on port 80 (Varnish)
  • Cache nothing on port 443 (Apache)

That seems to work great. Does anybody see any downsides of this approach?

I wondered if Symphony would create gazillions of orphaned sessions, but I could only test it on Symphony 2.3 (and not on 2.2). It looks like a session is only generated when a user logs in. Has this always been the case? (So why do I have 800,000 rows in my Symphony 2.2 session table? OK, that question may be off-topic…)

Does anybody see any downsides of this approach?

Nope, this is the way to do it (currently).

It looks like a session is only generated when a user logs in. Has this always been the case?

Afaik, the session is created every time (which is why you're having such a hard time getting varnish to work without writing your own rules), but it is only saved to the database when it actually contains data. I believe it's been this way for quite a while now, but there might have been a bug somewhere in 2.2 ;)

By the way: how do you like varnish? It's fast isn't it?

Fast? Are you kidding? It burns!!!

In fact, for me, the number of pages (or "objects") is only limited by the bandwith of the network. So if your peak bandwith is 100 Mbit/s (typical for a virtual server) and you are using GZIP (which means around 5 kB per HTML page, so approximately 50 kbit), you can deliver 2000 HTML pages/second. If you are benchmarking on the same server, without any outer network involved, you easily hit the 10k pages/s barrier. (All figures tested on a rather small virtual server, 17 Euro/month.)

Thanks for the clarification regarding the sessions!

If you are benchmarking on the same server, without any outer network involved, you easily hit the 10k pages/s barrier

Very true, and the best part is: the bottleneck will still be the TCP stack, not the CPU (which sits around 40% with 27.000 req/s (!!!) on my VPS).

It's an awesome peace of software, and I think it's a shame Symphony doesn't make using it easier. Ah well, I'll have time to rework the session handling next week, so things should improve after that:)

Have you had a look on Symfony's cache mechanisms, especially the Reverse Proxy or gateway cache? Would be nice to see Symphony CMS leveraging the httpkernel of Symfony2.

Not really, no. For the simple reason that for me the goal of a reverse proxy is to remove the overhead php gives altogether. Varnish will serve the page entirely from memory, making it very scalable and incredibly fast.

However, if you were to use a solution written in PHP like Symfony has, you are still tied to the number of php processes you can run on your server, and on how many requests your webserver can handle.

Even though we've seen a lot of progress here with FastCGI, nginx, and similar "new" technologies, Varnish will still blow them straight out of the water.

So, my vote would go to making Symphony cachable by a standard(!) installation of Varnish, with very little configuration needed on the backend (setting TTL's, that kind of stuff). Most providers will have some sort of Varnish layer they can tack on, or if they don't, you can always use CloudFront.

Just my two cents :-)

Ah, sorry for the confusion. What I wanted to say is, that symfony2 makes it easy to use varnish "out of the box" instead of using the php reverse proxy.

Because Symfony2's cache uses the standard HTTP cache headers, the Symfony2 Reverse Proxy can easily be replaced with any other reverse proxy. Varnish is a powerful, open-source, HTTP accelerator capable of serving cached content quickly and including support for Edge Side Includes.

@creativedutchmen - did the changes you made to the Cookie class ever get released? I need to do the same thing to my site and it would be great to use your setup.

did the changes you made to the Cookie class ever get released? I need to do the same thing to my site and it would be great to use your setup.

Would like to know the same. Can Varnish be used with Symphony 2.3.3 without further changes?

All important changes have been integrated. It boils down to this: As soon as session data is needed (because, for example, the user logs in, or you are saving data to the session using the Storage extension, the Device Categorizr extension or s.th. similar), the user will get a cookie from Symphony. As soon as session data is not used (no login, no other data from Storage or similar extensions), Symphony won't set resp. remove the cookie.

Nevertheless, regarding Varnish, I am by no means sure if it would work "out of the box". Last time I tried it Symphony's new session/cookie stuff was not in place, and my requirements were rather complicated. :-)

@michael-e Thanks.

@creativedutchmen I'm wondering if there's really a benefit when using a reverse proxy along with symphony. Ok, if you mostly deal with static sites I guess it would just work fine, but what is about dynamic or semi-dynamic pages? A real benefit for dynamic pages would require the page being partitially rendered, and with regards to reverse proxies, ESI would be the way to go. I think Symphony isn't capable of this, or is this something you can do with xslt?

Well, of course varnish caches are not for everyone. If you are certain you will need to render a different page for every user then a more modular caching method would be more appropriate (datasource caching, or ESI as you pointed out).

I am using Varnish because most (90%+) of my visitors are anonymous, and the speed gains when pages are served from cache are enormous.

ESI are just html tags, so Symphony sure supports it. Your pages will become a bit more fragmented, as you will require a different endpoint for each fragment, but if you have many visitors it sure could be worth it.

Outputting ESI statements using XSLT can be a bit tricky. If you also want to have a "fallback" (<esi:remove> element), this code could give you a start — I once tested it successfully:

<xsl:template name="foo">
    <div class="fragment-wrapper" xmlns:esi="http://www.edge-delivery.org/esi/1.0">
        <esi:remove>
            <xsl:apply-templates select="document(concat($root, '/path/to/your/widget/'))" mode="cached-fragment"/>
        </esi:remove>
        <xsl:comment>
            <xsl:text>esi</xsl:text>
            <xsl:value-of select="concat('&lt;esi:include src=&quot;', $root, '/path/to/your/widget/', '&quot; /&gt;')"/>
        </xsl:comment>
    </div>
</xsl:template>

<xsl:template match="*" mode="cached-fragment">
    <xsl:element name="{name()}">
        <xsl:apply-templates select="* | @* | text()" mode="cached-fragment"/>
    </xsl:element>
</xsl:template>

<xsl:template match="@*" mode="cached-fragment">
    <xsl:attribute name="{name()}">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

<xsl:template match="text()" mode="cached-fragment">
    <xsl:value-of select="."/>
</xsl:template>

You can probably use xsl:copy-of as well instead of identity transformation, which will make your code siginificantly shorter.

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details