All RPGs and Storygames by Tod Foley are now available at DrivethruRPG and RPGnow. Bring these games to your table!
This module integrates Drupal with Google Tag Manager, allowing you to developing complex dataLayers.Sponsors
This module provides a simple SEPA (Single Euro Payments Area) payment method with IBAN validation for Drupal Commerce. After completing the order a mail with the SEPA Direct Debit Mandate can be sent to the customer with all necessary information that the customer must return completed and signed.Sponsors
This module provides an entity config for dynamic library declarations.Recommended projects
Simple JSON Viewer is the module built to beautify the given JSON.
- It can be used with any editor by using simple class "simple-json-viewer"
- it can be used in custom js by using simpleJsonViewer function
- it can be used as ajax by using simpleJsonViewer function
Just add some JSON in any html tag with the class name "simple-json-viewer"
This module adds a Stripe Webhook endpoint to to receive notifications of the desired events and launch Symfony events.
This module provides a highly flexible progress bar form element based on SVG,
using LoadingBar.js library.
It’s not easy to find a development partner you can trust. Particularly if you’ve never been immersed in the world of web development, it may take you some time to learn the language. That can make it even more difficult to know whether your partner is really staying on track with what you want to accomplish.
Luckily, knowing what to look for in a business partner can save you from all of the potential troubles later on. Ratings and reviews sites like Clutch can help you get there. This platform focuses on collecting and verifying detailed client feedback, and then using a proprietary research algorithm to rank thousands of firms across their platform. Ultimately, Clutch is a resource for business buyers to find the top-ranked service providers that match their business needs.
Luckily for us, users on Clutch will also find Kanopi Studios at the top of the list to do just that. Kanopi has been working with Clutch for a few months to collect and utilize client feedback to find out what we should focus on in the coming year. Through the process, we’ve coincidentally been named among the firm’s top digital design agencies in San Francisco.
Here are some of the leading client reviews that led us to this recognition:
“They were fantastic overall. We had great success communicating to their team via video conferencing, and they were able to answer every question we had. They also worked quickly and were very efficient with their time, so we got a great value overall.”
“Kanopi Studios’ staff members are their most impressive assets — extremely intelligent, experienced, and personable. Building a website is never easy, but working with people you both respect and like makes a huge difference.”
“Kanopi Studios successfully migrated our Drupal platform while preserving all the content that we’ve built up over the years. They worked hard to achieve a responsive design that works well on both mobile and large desktop displays.”
Not only have these kind words earned us recognition on Clutch, but we’ve also gained the attention of the how-to focused platform, The Manifest (where we are listed among top Drupal developers in San Francisco), and the portfolio-focused site, Visual Objects (where we are gaining ground among top web design agencies site-wide).
Thank you, as always, to our amazing clients for the reviews and the support.
The module integrates Drupal Commerce with GoCardless.com, and creates direct debit mandates for new orders upon check out. GoCardless is a recurring payment specialist, and is very competitive compared with other payment services, charging just 1% on transactions, with a minimum of 20p (or an equivalent amount in other currencies).
This module includes the Blockquote Attribution plugin, an extension of the standard CKEditor
Blockquote button. This button inserts <figure> and <figcaption> markup around the <blockquote> element. This is the standard way to indicate that a piece of content is quoted from another source.
When it comes to ecommerce, a fast site can make a big difference in overall sales. I recently went through an exercise to tune a Drupal 7 Commerce site for high traffic on a Black Friday sales promotion. In previous years, the site would die in the beginning of the promotion, which really put a damper on the sale! I really enjoyed this exercise, finding all the issues in Commerce and Drupal that caused the site to perform sub-optimally.
FYI, We also have a Drupal 8 Commerce Performance Tuning guide here.Scenario
In our baseline, for this specific site the response time was 25 seconds and we were able to handle only about 1000 orders an hour. With a very heavy percentage of 500s, timeouts and general unresponsiveness. CPU and memory utilization on web and database servers was very high.
Fast-forward to the end of all the tuning and we were able to handle 12K-15K orders an hour! The load generator couldn’t generate any more load, or the internet bandwidth on the load generators would get saturated, or something external to the Drupal environment became the limiter. At this point, we stopped trying to tune things. Horizontal capacity by adding additional webheads was linear. If we had added more webheads, they could handle the traffic. The database server wasn’t deadlocking. Its CPU and memory was very stable. CPU on the web servers would peak out at ~80% utilization, then more capacity would get added by spinning up a new server. The entire time, response time hovered around 500-600ms.
Enough about the scenario. Let’s dive into things.
The first step in tuning a site for a high volume of users and orders is to build a script that will create synthetic users and populate and submit the form(s) to add item(s) to the cart, register new users, input the shipping address and any other payment details. There’s a couple options to do this. JMeter is very popular. I’ve used it in the past with pretty decent success. In my most recent scenario, I used locust.io because it was recommended as a good tool. I hadn’t used it before and gave it a try. It worked well. And there are other load testing tools available too.
OK, now you are generating load on the site. Now start tuning the site. I used New Relic's APM monitoring to flag transactions and PHP methods that were red flags. Transactions that take a long time or happen with great frequency are all good candidates for red flags. If you don’t have access to New Relic, another option is Blackfire. Regardless what you use for identifying slow transactions, use something.
Make sure that there’s nothing crazy going on. In my case, there was a really bad performing query that was called in the theme’s template.php and it was getting loaded on every single page call. Even when it wasn’t needed. Tuning that query gave use an instant speed-up in performance.
After that, we starting digging into things. There are several core and contrib patches I’ll mention and explain why and when you should consider applying them on your site.
In your specific commerce site, things might be different. You might have different payment gateways or external integration points. But the process of identifying pain points it the same. Run a 30-60 minute load test and find long running PHP functions. Then fix them so it doesn’t take as long.
As a first step, install the Memcache (or Redis) module and set it up for locking. Without that one step, you’ll almost immediately run into deadlocks on the DB for the semaphore table. This is a critical first step. From my experience, deadlocks are the number one issue when running a site under load. And deadlocks on the semaphore table is probably the most common scenario. Do yourself a favor. Install Memcache and avoid the problem entirely.
Then see if you can disable form caching on checkout and user registration. This helped save a TON of traffic against the database for forms that really don’t need to be cached. More about that later in specific findings.
One last thing before diving into some findings...
SHOW ENGINE INNODB STATUS
...will become your favorite friend. Use it to find deadlocks on your MySQL server.Specific Findings The following section describes specific problems and links to issues and patches related to the problems.
- Do not attempt field storage write when field content did not change
Commerce and Rules run and reprocess an order a lot. And then blindly save the results. If nothing has changed, why re-save everything again? So don’t. Apply this patch and see fewer deadlocks on order saves.
- field_sql_storage_field_storage_load does use an unnecessary sort in the DB leading to a filesort
Many times it makes sense to use your database to process the query. Until it doesn’t make sense. This is a case it leads to a filesort in MySQL (which you can discover using EXPLAIN in MySQL) and locking of tables and deadlocks. It is not that hard to do the sort in PHP. So do it.
- Do not make entries in "cache_form" when viewing forms that use #ajax['callback'] (Drupal 7 port)
This is a huge win, if you can pull it off. For transient form processing like login and checkout, disabling form cache is a huge relief to the DB. You might need to put the entire cart checkout onto a single page. No cart wizard. But the gains are pretty amazing.
- If you are using captcha or anything with ajax on it on the login page, then you’ll need to make sure you are running the latest versions of Captcha and Recaptcha. See issues #2449209 and #2219993. Also, side note: if using the timing feature of recaptcha, the page this form falls on will not be cacheable and tends to bust page cache for important pages (like homepages that have a newsletter sign up form).
- form_get_cache called when no_cache enabled
You’ve done all that work to cut down on what is stored in cache. Great. But Drupal still wants to retrieve from cache. Let’s fix that. Cut down more DB calls.
- commerce_payment_pane_checkout_form uses form_state values instead of input
If your webshop is like most webshops, it is there to generate revenue. If you disable form caching on checkout, without this patch the values in your payment (including the ones for receiving payment) aren’t captured. Oops. Let’s fix that too.
- Variable set stampede for js and css during asset building
If you are using any auto scaling system and building out new servers when the site is under heavy load, you might already be using Advagg. But if you aren’t and are still using Drupal core’s asset system, spinning up a new system or two will cause some issues. Deadlocks galore when generating the CSS and JS aggregates. So either install Advagg or this patch.
- Reduce database load by adding order_number during load
Commerce and Rules really like to reprocess orders. An easy win is to reduce the number of one-off resaves and assign the order number after the first load.
- Never use aggregation in maintenance mode
While the site is under heavy load, the database sometimes becomes unreachable. Drupal treats this as maintenance mode. And tries to aggregate the JS/CSS and talk to the database. But the database isn’t reachable. It is a little ridiculous to aggregate JS/CSS on the maintenance page. And even more to try to talk to the database. So cut out that nonsense.
- drupal_goto short circuits and doesn't set things to cache
If you have any PHP classes you are using during the checkout, Drupal’s classloader auto loads them into memory. It then keeps track of where the files exist on the disk and this makes the next load of those classes just that much faster. Well, drupal_goto kills all this caching. And drupal_goto gets called when navigating through checkout.
Wow! That was a long list of performance enhancements. Here’s a quick recap though. Identify critical flow of your application. Generate load on that flow. Use a profiler to find pain points in that process. Then start picking things off, looking on drupal.org for existing issues, filing bugs, applying patches. Many of the identified issues discussed here will apply to your site. Others won’t apply and you’ll have different issues.
Surprisingly, or maybe not surprisingly, the biggest wins in our discovery process were the low hanging fruit, not the complex changes. That query in the template.php was killing the site. After that, switching to use Memcache for the semaphore table and eliminating form cache for orders also cut down on a lot of chatter with the database.
I hope you too can tune that Drupal 7 Commerce site to be able to handle thousands of orders an hour. The potential exists in the platform, it is just a matter of giving performance bottlenecks a little attention and fine tuning for your particular use case. Of course, if you need a little help we'd be happy to assist. A little bit of time spent can have you reaping the rewards from then on.
Here are some performance tuning tips and instructions for setting up a very performant Drupal 8 Commerce site using Varnish, Redis, Nginx and MySQL. I’ve got this setup running nicely for at least 13,000 concurrent users and it should scale well past that.
FYI, We also have a Drupal 7 Commerce Performance Tuning guide here.Varnish Config
You’ll need some specific config for Drupal as well as some extra config to work nicely with BigPipe caching. These are standard for Varnish and Drupal and not specific to Commerce.Drupal
You’ll want to setup the Purge and Varnish Purge modules to handle tag based cache invalidation, nothing here is unique to Commerce, so you can follow the standard instructions. You will, however, want to make sure your pages actually are cached, as often modules or small misconfigurations can make a page not cacheable. To work nicely with Varnish, you want the entire page to be cacheable so your webserver doesn’t even get hit. An underused module that I find very helpful is Renderviz, which will show you a 3D breakdown of what cache tags are attached to what parts and can help you identify problem parts. I run
renderviz(‘max-age’, ‘0’) to show me anything that can’t be cached. Usually the parts you find can be corrected and made cacheable.
For example: In a recent set of performance testing I was doing, I found a newsletter signup that appeared on the bottom of every page had an overly aggressive honeypot setting, which rendered the page uncacheable. Changing the settings to only apply to necessary forms, as well as correcting a language selector, turned tons of uncached pages into cacheable pages. Now these pages return <10ms and put zero load on my web servers or database.
Use the most modern version of PHP you can, preferably the latest stable. Never ever ever use PHP 5 which is terrible, terrible, terrible. Otherwise, make sure you have sufficient memory and allowed threads, and that will cover most of your PHP tuning. This is almost certainly the most resource heavy part of your Drupal stack, but it is also easy to scan horizontally, pretty much indefinitely. Also, the more you can make use of Varnish, the less this will get used.Nginx/Apache
Most of this is just making sure you can handle the number of connections. You may need to up the file limit...
...of your web user to allow for more than 1024 connections per nginx instance.Database
A Commerce site is usually more write-heavy than your standard site, as your users create lots of "content" (aka carts and orders). This will usually change your MySQL config a bit, although the majority of your queries will still be reads. A pretty simple way to tune your site is to run...
...against it after getting some real traffic data for at least a couple days, or simulating high traffic. It’s recommendations will get you a pretty good setup.
There is one other VERY important thing you need to do, you need to change your transaction isolation level from READ-REPEATABLE to READ-COMMITTED. READ-REPEATABLE is much too aggressive at table locking to work with most Drupal sites, especially anything write heavy. You will suffer from constant deadlocks even at fairly low traffic levels without this. Frankly, I think this should be a flag in the status page, but my patch hasn’t gotten any traction.Cache Server
Nothing special here, but you are going to want use a separate caching option. It could be Memcache, Redis or even just a separate MySQL database. Redis is nice and fast, but the biggest gain is just splitting your cache away from the rest of your db so you can scale them easier.Patches
There are a few specific patches that will be a great help to your performance._list cache tag invalidation
Every entity type has an entity_type_list cache tag, which gets invalidated any time an entity of that type is added or changed and that those lists will need to get rebuild. This happens a LOT, but is a relatively simple query.
update cachetags set invalidation=invalidation+1 where tag=’my_entity_list’
This is an update, which is a blocking query, nothing else can edit this row while this query is running, which wouldn’t be so bad except...
This query often gets run as a part of larger tasks, in our case, such as when placing an order. A big task like this is run in a transaction, which basically means we save up all the queries and run them at once so they can be rolled back if something goes wrong. This means though, that this row stays locked for the whole duration of the transaction, not just the short time it takes this little query to run. If this invalidation happens near the start of the transaction, it can take a query that would talk 0.002 seconds and make it take 0.500 seconds, for example. Now, if we have more than 2 of these happening a second, we start to back up and build a queue of these queries, which just keeps getting longer and longer until we just start returning timeouts. Since this query is part of the bigger order transaction, it stops the whole order from being processed and can bring your checkout flow to a halt.
Thankfully, the above listed patch allows these cache invalidations to be deferred so as to not block large transactions. I think the update query for invalidating cache tags is still a bottleneck as you could eventually reach it without these long transactions, but at this point that problem is more hypothetical than something you will practically encounter.Add index to profiles
As you start getting more and more customers and orders, you will get more profiles. Loading them, especially for anonymous users, will really start to slow down and become a bottleneck. The listed patch simply adds an index to prevent that. Please note, this is a patch for the Profile module, not Commerce itself.Make language switcher block cacheable
This issue is unfortunately on hold pending some large core changes, but once it does land, this will allow the language switcher block to be used without worry of it blocking full page caching.Conclusion
You should be able to scale well above 10,000 concurrent users with these tips. If you encounter any other bottlenecks or bugs, I’d love to hear about them. If you want help with some performance improvements from Acro Media and yours truly, feel free to contact us.
The company says itâ€ s making the switch to more hands-on anti-toxicity measures by pairing chat filters with human moderation. ...
Practice and more practice are the keys to adopting modern software engineering practices. It doesn’t matter if you’re using WordPress or Drupal to manage website content, trying to learn unit testing, get hired, or looking for better ways to manage date and time data—there’s always an opportunity to learn how to do it better. This issue rounds up articles on each of these topics to help you deepen your problem-solving skills.