Skip to content

Squid cache log configuration thoughts

I have found that debugging squid, the excellent web proxy, is difficult.

I believe this is for a number of reasons, but primarily because I’m a developer, and just want to get squid working. I’ve found that I do this with a lot of tasks that are required of the small independent developer with time pressures–CSS/UI development, database design, system administration. All these are things that can be done well by competent specialists, but my clients often don’t have the money to hire them, or time to find them, so they get me. What they get is not in depth CSS knowledge and in depth knowledge of the entire user interface problem domain, for example. Rather, clients get my ability to figure out the problem (based, to a large extent on internet knowledge and to a lesser extent on my deep understanding of web applications and how they should behave) and my tenacity to test and test again to ensure that corner cases are dealt with. It’s a tradeoff.

Regardless, squid is hard for me to debug, and I found this page which lists all the options for the cache.log debugging parameters useful. However, not all that useful–‘client side routines’, number 33, apparently includes squid ACL parsing. Rather, I’ve found the Squid FAQ to be the single most helpful document in terms of my understanding squid enough to ‘get things done’. However, this time I ended up viewing the access log of my http server, while deleting my browser cache multiple times, to confirm that caching was set up the way I thought I had configured it.

[tags]squid,getting things done[/tags]

Google Chrome First Impressions

Here are my thoughts on Google Chrome. Yup, I’m following the blogging pack about a week late. First off, the install process was smooth. The comic book stated that the rendering engine is Webkit, which should make testing relatively easy. This is borne out by the user agent string: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.29 Safari/525.13

They give you the ability to change the search engine, and other options, easily. It definitely follows a Macish configuration processs–you don’t have to apply or save the config changes you make, you just make them and close the options screen.
As Farhad Manjoo mentions, there is a lack of addons. (Addons are pieces of functionality that are extend the browser’s behavior [think adblock], as opposed to plugins which extend the browser’s ability to handle content [think flash]). I didn’t see much about addons or plugins for Chrome searching today, other than some strong desire for it. I don’t remember any mention of addons in the comic book or on the Chrome website. Also, as Manjoo mentions, opening a new tab by clicking next to the existing tabs doesn’t work (though there is a plus icon up there which it should not take too long to get used to).

It looks like there is already a way to create simple desktop applications like a calculator that use chrome as their ‘shell’, javascript as the programming language and HTML for user interface definition. That’s very similar to Adobe AIR (at least the ajax version) and something like the C#/XAML pairing as well. Let’s hear it for declarative markup for user interfaces!

The custom start page seems pretty neat, with the ability to have bookmarks not in a pulldown menu, but right on the start page, which also includesthe ‘most visited’ sites. Machine learning of this type can be a great time saver.

From a development standpoint, there is a javascript/DOM console, which looks similar to Safari’s. It is, however, much more responsive and stable, though I still can’t figure out what the ‘search’ box does. However, the wealth of development tools that I use everyday in FireFox (web developer, yslow, firebug, whois, live HTTP headers) will take time to migrate over to Chrome, if they do so at all. This will continue to make developing in FireFox first and testing in other browsers my default strategy.

Finally, Cringley has some interesting comments on Google’s motivation.

[tags]google chrome[/tags]

MySQL and memcached: notes from a webinar

Just listened to another mysql webinar. This time it was about mysql and memcached. I got in a little late, but here are my notes.

Memcached is a distributed caching mechanism. Not as robust as Coherence, for example, but free, open source, and widely used and supported.

There is a project that hooks mysql UDFs to memecached.

The main speaker worked at Grazr, a feed manipulation company. He presented some lessons and stated that some seemed obvious, but we all know how it is, you learn mistakes the hard way.

  1. Beware architecture momentum–early decisions influence later ones.
  2. Your scaling plan is wrong in some way!–grazr overbuilt.
  3. Testing is limited: they had issues with replication speed. Users are better at testing site than any perl script.
  4. Replication is fast, until it isn’t. It’s asynchronous nature can make it hard to program to.
  5. Memcached is your friend
  6. Sphinx, an open source SQL full text search engine (like Lucene), is your friend. It also has a mysql storage engine–virtual table that you can join with other data sources. This sounds cool.
  7. Do bulk insert and lazy writes–if you don’t need to immediately read it, do the write later.
  8. Emphasis on scaling hurt user experience. Fast, data correct transaction are available with two options: one server, or a sync buffer like memcached.
  9. Use instrumentation–he mentioned tools like nagios and cacti (cacti has mysql plugin [which I couldn’t find]) to help scaling–close the loop: when you make a change, find out what that change did.
  10. Try new things–for example, the MySQL blackhole storage engine for data that is only read on slaves, not on the master.
  11. Everyone has same problems–avoid Not Invented Here syndrome. Not just the obvious stuff (who writes a web server these days–oh wait), for example, there’s a batch job processor like gearman. Note that he also said they had to Invent a few things before they learned this lesson.
  12. Accept change–design for now+1, not now+100
  13. Listen–even folks not intimately familiar with your technology may have good ideas, and more brains are better.

End notes

Looks like a couple of interesting whitepapers are available (you’ll have to register and get pinged via email a few times by sales folks): “Designing and Implementing Scalable Applications with Memcached and MySQL”. And there are future webinars on the MySQL/memcached topic, one on SAAS applications and one on Scalable web architecture.

In a meta note, I enjoy the webinars because:

  1. Easy to get to
  2. Free
  3. High quality
  4. One can bail if you want (which I did a few weeks ago when MySQL proxy http://forge.mysql.com/wiki/MySQL_Proxy didn’t turn out to be all that interesting to me).
  5. The give me something to blog about 🙂

[tags]webinar, memcached, users are the best testers[/tags]

GWT Mini Pattern: Bare Bones Entry Point Class

Don’t ever let your entry point class do anything. Why? Because the constructor of the entry point class will be called twice. Once when the object is being instantiated so that onModuleLoad can be called, and then once if your code does anything useful in the constructor. You can also have a constructor that does nothing active (XHR, modifying the DOM) in which case it won’t matter that it is called twice (except it will slow down the user’s computer a little bit.)
Here’s an example of how not to do it (sorry for the [lack of] code formatting):

 

public class Display implements EntryPoint {  public void onModuleLoad() {  final RootPanel rootPanel = RootPanel.get(COMPONENT_HOME_ID);  if (rootPanel != null) {  Display fd = new Display();  } }  public Display() { Window.alert("new date: "+new Date()); // more stuff }  // more stuff }

If you were to compile and execute the code above, you'd see two different alerts. Instead you want:

public class DisplayEntry implements EntryPoint {  public void onModuleLoad() {  final RootPanel rootPanel = RootPanel.get(COMPONENT_HOME_ID);  if (rootPanel != null) {  Display fd = new Display();  } }  }  class Display { // or it could be in a separate java file public Display() { Window.alert("new date: "+new Date()); // more stuff }  // more stuff }

You can also get around it by having a no-op no arg constructor (which all EntryPoint classes are required to have) and one that takes arguments that you'll use in your class to do something.

Tested on Windows, GWT 1.4.62.

Useful Tools: Skype

Skype is something that I’m relatively late to the game on, but now I can’t believe I lived without it. I use it as a secondary line for my business.  (I know, I know, next thing you know I’ll be telling y’all that the “internet” is the next big thing.) I have a relatively old plan and get nailed whenever I go over in minutes–35 cents a minute. I am planning to get a new plan and phone sometime soon, but want to make sure I get a great phone, and haven’t had time to comparison shop.

Skype is letting me postpone getting a new phone by letting me use my minutes more effectively. Check out my sweet old phone–a super solid Nokia:

Phone

At first, I only had Skype Out, which let me call people in the US for the measly sum of $6 dollars a month. Just recently, I signed up for Skype In, which is actually less expensive–$24/year, and lets me receive phone calls.
However, I won’t be passing out my new Skype number–I want people to associate me with the same number I’ve had since I first got my cell phone. Instead, I’ll just forward all calls from my phone to my Skype number when I m in front of a computer.

I originally got Skype because of the cost savings, but it also makes me more effective on the phone. With a headset that I bought for $40 a year ago, I can type and talk at the same time, as opposed to using speaker phone and/or craning my neck.

The only thing I use my phone for that Skype doesn’t replace is text messages–I use teleflip.com for that, because it is free.

I haven’t really explored the other features of Skype–computer to computer calls or conference calling–but right now Skype does what I need it to do.

State/survey of GWT widgets

GWT does not provide as near a complete set of widgets with GWT as, say, YUI. It does provide a way to integrate existing javascript widgets, as the gwt-ext and gwt-widget projects do. However, this approach is lacking compared to native GWT widget sets because

  1. They require external javascript source files, which you then have to version and your user has to download (even if you only use some of the code). These files are not subject to the GWT optimization/compilation process.
  2. The JSNI methods used to access the third party widgets can cause trouble when you’re debugging in hosted mode. See one example.

I think it would be worth the GWT team taking more action to standardize the GWT widget set. Yes, the incubator is a start, but some of the widgets there are months old. Among other things, I could not find a carousel component that didn’t depend on kilobytes of external YUI javascript.

Here’s an informal list of GWT widget toolkits that I’ve found in my searches. Most I’ve tried and found useful, some I just have looked at. Some are native, some are wrappers.

  • The GWT incubator: these are widgets, as well as documents and other tools, that might make it into GWT in the future.
  • gwt-widget: I’ve used this project in the past. Some wrappers (of scriptaculous) and some native classes (SimpleDateFormat, LightBox).
  • sphene: I like the slider and am planning to use it in a project very soon.
  • GWT-Rocket: This provides a whole framework, including many widgets and some replacements for core GWT functionality. I installed and tested their slider functionality, but haven’t looked closer than that.
  • gwt-ext: This project wraps the fine extjs js library, plus more if you pay. I have used this for grid tables and found it great.
  • ext-gwt: This project apparently re-implements extjs, by the folks who wrote extjs. Here’s more about the differences between ext-gwt and gwt-ext.
  • GWTcomponents, which appears abandoned, but might have useful components.
  • gwt-fx: not strictly a widget toolkit, but rather a way to do effects natively.

Here is a page with other libraries that I don’t have a lot of experience with, but might be worth investigating. And looking on google code turns up a large number of projects devoted to GWT extensions.

[tags]widgets, ajax toolkits[/tags]

Article on Building “Normal” Websites with GWT

Here’s an interesting article about building websites with GWT.  By ‘normal’ this author is talking about integrating GWT components into existing HTML pages, or making widgets available to non technical users.  This is in contrast to what seems like the sweet spot of GWT–building rich web applications.  (I’ve talked about these two use cases before.)  I was impressed by the author’s assessment of the GWT widget landscape and the machinations to create a vertical TabPanel and the follow up about internationalization.  I haven’t done any i18n with GWT, but the fact that you can’t change locale after load time certainly seems like a large flaw.

Setting headers in a PHP include directive

I am currently working on a project that uses a PHP CMS for the bulk of the site. However, it pulls some content from a page generated by JSTL on a tomcat. I was using the fmt tag to do some pretty printing of numbers, and it looked fine when I viewed the content as served by tomcat. However, none of the formatting was carrying through when the PHP page included the jsp. Why? It appears that the fmt tag needs a locale. I confirmed that with wget.

Now, how to set the header with the PHP include. The include man page was no help, and mod_rewrite won’t let you modify headers, as far as I can tell. Once the request arrived to tomcat, that was too late.

Some digging around in the PHP documentation on fopen turned up this gem:

Custom headers may be sent with an HTTP request prior to version 5 by taking advantage of a side-effect in the handling of the user_agent INI setting. Set user_agent to any valid string (such as the default PHP/version setting) followed by a carriage-return/line-feed pair and any additional headers. This method works in PHP 4 and all later versions.

Click through for a code example. The aforementioned documentation talks about custom headers, but it worked for sending the Accept-Language header that the fmt tags needed.

JSTL 1.2 and “Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found” exception

I am using JSTL for a project. For such a standard, it’s a bit wierd to get started with. Sun provides a spec, but as far as I can see, you have to download the entire J2EE stack to get the jarfile. There’s not a lot of good documentation on getting started with it (this page, though dated and focusing on JSTL 1.0 and 1.1, was helpful).

One exception in particular dogged me. If you are trying to get started using Tomcat (my version is 6.0) and JSTL, and are getting this exception when you are using the JSTL tags, run, don’t walk to your nearest Xerces download center and place xercesImpl.jar, in your lib directory (I also needed Xalan, for JSTL 1.2, which I had to download from here):



HTTP Status 500 -


type Exception report message description The server encountered an internal error () that prevented it from fulfilling this request. exception
javax.servlet.ServletException: javax.xml.parsers.FactoryConfigurationError: Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:274)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
com.cohomefinder.eightz.servlet.RequestDispatcher.doGet(RequestDispatcher.java:30)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

root cause

javax.xml.parsers.FactoryConfigurationError: Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found
javax.xml.parsers.SAXParserFactory.newInstance(Unknown Source)
org.apache.taglibs.standard.tlv.JstlBaseTLV.validate(JstlBaseTLV.java:161)
org.apache.taglibs.standard.tlv.JstlCoreTLV.validate(JstlCoreTLV.java:105)
org.apache.jasper.compiler.TagLibraryInfoImpl.validate(TagLibraryInfoImpl.java:761)
org.apache.jasper.compiler.Validator.validateXmlView(Validator.java:1774)
org.apache.jasper.compiler.Validator.validate(Validator.java:1743)
org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:178)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:306)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:286)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:273)
org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:566)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:317)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
com.cohomefinder.eightz.servlet.RequestDispatcher.doGet(RequestDispatcher.java:30)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

note The full stack trace of the root cause is available in the Apache Tomcat/6.0.14 logs.


Apache Tomcat/6.0.14