building scalable php applications using google's app engine

Post on 07-Jan-2017

218 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Building Scalable PHP ApplicationsUsing Google’s App Engine

Mandy Waite google.com/+MandyWaite@tekgrrl

Amy Unruhgoogle.com/+AmyUnruh@amygdala

Scale on Demand

Analytics

Fast Access to Cloud-Scale Services

Global Availability

Focus on developing your

App

Why Cloud for PHP?

App Engine

Simple to Scale- AutoScale

Trivial to manage- Fully managed- No patches- 24x7 operation by Google SREs

Easy to develop- Free to start- Local dev environment- Service abstractions

Handling variable load

Volatile Demand Fluctuation Steady Demand Growth

Inefficiency

With App Engineonly pay for what you use

With App Enginescale with efficiency and reliability

Downtime

Inefficiency

App Engine’s Cloud Scale Services

Cloud SQL

...and more

PageSpeedCloud Datastore

Cloud Storage

Cron JobsMemcache

Why PHP?

Top feature request for App Engine

Real World Example

Converting joind.in to App Engine

PHP on App Engine:what’s the environment like?

github.com/GoogleCloudPlatform/appengine-php - 5.4.19http://php-minishell.appspot.com/phpinfo: Production phpinfo()

How do we start?

application: <your-app-name>version: unoruntime: phpapi_version: 1

handlers:- url: /inc static_dir: inc- url: /.* script: index.php

app.yamlappengine.google.com

What is the environment like?

google_app_engine.enable_functions = "php_sapi_name"

php.ini

How do we log?

How do we log?function write_log($level = 'error', $msg, $php_error = FALSE){ if ($this->_enabled === FALSE) { return FALSE; } $level = strtoupper($level); if ( ! isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold)) { return FALSE; }

syslog($level == 'ERROR' ? LOG_ERR : LOG_INFO, $msg); return TRUE;}

How do we log?

Hmmm… now we have a database error

What about the database?

What about the database?

$db['default']['hostname'] = ":/cloudsql/<PROJECT>:<INSTANCE>";$db['default']['username'] = "joindin";$db['default']['password'] = "password";$db['default']['database'] = "joindin";$db['default']['dbdriver'] = "mysql";$db['default']['dbprefix'] = "";$db['default']['pconnect'] = TRUE;

How do we call APIs?

Recommended:

use App Engine’s URLFetch service via standard HTTP stream wrappers and functions like file_get_contents()

Calling APIs?

$opts = array( 'http' => array( 'method' => 'POST', 'header' => "Content-type: application/x-www-form-urlencoded\r\n" . "Content-length: ".strlen($msg)."\r\n", 'content' => $msg));$ctx = stream_context_create($opts);

$resp = file_get_contents( 'http://api.defensio.com' . $loc, false, $ctx);

How do we cache?

Output Cachingfunction _write_cache($output) { $CI =& get_instance(); $path = $CI->config->item('cache_path'); $cache_path = ($path == '') ? BASEPATH . 'cache/' : $path; $uri = $CI->config->item('base_url') . $CI->config->item('index_page') . $CI->uri->uri_string(); $cache_path .= md5($uri);

$mc = new Memcache; $mc->set($cache_path, $output, $this->cache_expiration * 60); return;}

Can we upload files?

Uploads?

cloud.google.com/console

App Engine Access to Cloud Storage

$options = [ 'gs_bucket_name' => 'joindin' ];

$upload_url = CloudStorageTools::createUploadUrl( '/event/edit/'.$this->edit_id, $options);

echo form_open_multipart($upload_url);

Uploads?

Uploads?— and Cloud Storage stream wrapper

$gs_name = $_FILES[$field]['tmp_name'];$gs_type = $_FILES[$field]['type'];

$options = [ "gs" => [ "Content-Type" => $gs_type, "acl" => 'public-read']];$ctx = stream_context_create($options);

rename($gs_name, $this->upload_path . $this->file_name, $ctx);

Public URLs from Cloud Storage Files?

<?php $path = "gs://joindin/inc/img/event_icons/';$img = ( !empty($event->event_icon) && is_file($path.$event->event_icon)) ? escape($event->event_icon) : 'none.gif'; $public_url = CloudStorageTools::getPublicUrl($path.$img, true);?>

Can we send email?

Can we send email?

require_once 'google/appengine/api/mail/Message.php';use google\appengine\api\mail\Message;

... $message = new Message($mail_options); $message->send();

How can we send email in the background?

Web Request Worker

Task Queue

foreach ($send_to as $email) { // Send mail in a worker. $task = new PushTask('/tasks/email', [ 'from' => $from, 'to' => $email, 'subject' => $subj, 'msg' => $msg ]); // Use the default queue. $task_name = $task->add();}

Using Task Queues to send email in the background

The task handler mapping

handlers:- url: /inc static_dir: inc- url: /tasks/email script: workers/email.php login: admin

app.yaml

Can we send email? - the task handler

require_once 'google/appengine/api/mail/Message.php';use google\appengine\api\mail\Message;

if (!isset($_SERVER['HTTP_X_APPENGINE_QUEUENAME'])) { exit(); }...

Can we send email? - the task handler (cont.)

...$mail_options = [ "sender" => $_POST['from'], "to" => $_POST['to'], "subject" => $_POST['subject'], "htmlBody" => $_POST['msg']];

try { $message = new Message($mail_options); $message->send();} catch (\InvalidArgumentException $e) { syslog(LOG_ERR, $e->getMessage());}

Migrating a Typical Application

PHP

Use streams API for network calls

Cache to Memcache

Mail API to send email

Cron, Task Queues for background jobs

MySQL to Cloud SQL,or Cloud Datastore for NoSQL

File Writes and Uploads to Google Cloud Storage

Create App Engine application

Configureapp.yaml, php.ini

Apply at goo.gl/Bc1sA

Use Promo Code: fphpp-con

Google Cloud Platform Starter Pack allows developers from affiliated partners to receive $2,000 of credit - $1,000 for Google App Engine and $1,000 for Google Compute Engine and other Cloud Platform services

Google Cloud Platform Starter Pack

Thank you!

</end>

top related