【BAE专业版】搭建kibana对日志进行分析

  • 简介
上一篇文章中,我们介绍了如何将日志写入到ElasticSearch,但查询和展示需要自己编写代码。在这篇文章中,我们将介绍如何在BAE专业版上快速搭建kibana。
  • 准备kibana镜像

Kibana 4.1官方Docker镜像:https://github.com/docker-library/kibana/tree/7ce21f8aa1e58443c3031fdbdf83a08ce34e49a4/4.1

这里需要对Dockerfile进行简单修改,修改后的代码如下(更改部分已标):

FROM debian:jessie

# add our user and group first to make sure their IDs get assigned consistently
RUN groupadd -r kibana && useradd -r -m -g kibana kibana

RUN apt-get update && apt-get install -y \
		ca-certificates \
		wget \
	--no-install-recommends && rm -rf /var/lib/apt/lists/*

# grab gosu for easy step-down from root
ENV GOSU_VERSION 1.7
RUN set -x \
	&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \
	&& wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \
	&& export GNUPGHOME="$(mktemp -d)" \
	&& gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
	&& gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
	&& rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \
	&& chmod +x /usr/local/bin/gosu \
	&& gosu nobody true

# grab tini for signal processing and zombie killing
ENV TINI_VERSION v0.9.0
RUN set -x \
	&& wget -O /usr/local/bin/tini "https://github.com/krallin/tini/releases/download/$TINI_VERSION/tini" \
	&& wget -O /usr/local/bin/tini.asc "https://github.com/krallin/tini/releases/download/$TINI_VERSION/tini.asc" \
	&& export GNUPGHOME="$(mktemp -d)" \
	&& gpg --keyserver ha.pool.sks-keyservers.net --recv-keys 6380DC428747F6C393FEACA59A84159D7001A4E5 \
	&& gpg --batch --verify /usr/local/bin/tini.asc /usr/local/bin/tini \
	&& rm -r "$GNUPGHOME" /usr/local/bin/tini.asc \
	&& chmod +x /usr/local/bin/tini \
	&& tini -h

ENV KIBANA_VERSION 4.1.11
ENV KIBANA_SHA1 13655cf94f5c47e8ab4d94c8170128f63be46ad5

RUN set -x \
	&& wget -O kibana.tar.gz "https://download.elastic.co/kibana/kibana/kibana-${KIBANA_VERSION}-linux-x64.tar.gz" \
	&& echo "${KIBANA_SHA1} *kibana.tar.gz" | sha1sum -c - \
	&& mkdir -p /opt/kibana \
	&& tar -xz --strip-components=1 -C /opt/kibana -f kibana.tar.gz \
	&& chown -R kibana:kibana /opt/kibana \
	&& rm kibana.tar.gz \
	\
# ensure the default configuration is useful when using --link
        && sed -ri "s!^(\#\s*)?(elasticsearch_url:).*!\2 'http://your_elastic_search/url'!" /opt/kibana/config/kibana.yml \
        && sed -ri "s!^(\#\s*)?(kibana_elasticsearch_username:).*!\2 'your_elastic_search_user_name'!" /opt/kibana/config/kibana.yml \
        && sed -ri "s!^(\#\s*)?(kibana_elasticsearch_password:).*!\2 'your_elastic_search_password'!" /opt/kibana/config/kibana.yml \
        && sed -ri "s!^(\#\s*)?(port:).*!\2 8080!" /opt/kibana/config/kibana.yml \
        && sed -ri "s!^(\#\s*)?(log_file:).*!\2 \/home\/bae\/log\/kibana.log!" /opt/kibana/config/kibana.yml

RUN mkdir -p /home/bae/log \
        && chmod a+rwx /home/bae/log

ENV PATH /opt/kibana/bin:$PATH

COPY docker-entrypoint.sh /

EXPOSE 8080
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["kibana"]

其中,http://your_elastic_search/url,需要填入你的ElasticSearch集群的地址;your_elastic_search_user_name和your_elastic_search_password填入你的账号和密码

主要的修改点是elasticSearch的配置,kibana的监听端口以及日志的位置。

为了方便我们修改kibana配置,我们还可以更改docker-entrypoint.sh,可以通过上传部署代码更换配置,docker-entrypoint.sh修改如下(更改部分已标):

#!/bin/bash
set -e

MY_KIBANA_CONF="/home/bae/app/kibana.yml"
KIBANA_CONF="/opt/kibana/config/kibana.yml"

# Add kibana as command if needed
if [[ "$1" == -* ]]; then
        set -- kibana "$@"
fi

# Run as user "kibana" if the command is "kibana"
if [ "$1" = 'kibana' ]; then
        if [ -f "$MY_KIBANA_CONF" ]; then
                cp $MY_KIBANA_CONF $KIBANA_CONF
        fi

        set -- gosu kibana tini -- "$@"
fi

exec "$@"

这样我们上传代码时,在根目录中包含文件kibana.xml就可以使用新的配置文件。

将Dockerfile和docker-entrypoint.sh放在同一个目录下,在该目录下运行创建镜像代码,参考代码如下:

docker build -t registry.bce.baidu.com/user_id/image_name:tag_name .

其中,user_id为用户的ID,请查看自己的账号信息;image_name和tag_name分别为镜像名称和标签名,用户可以自行定义。
制作好后,将镜像上传到BAE专业版中,参考代码如下:

docker push registry.bce.baidu.com/user_id/image_name:tag_name

自定义镜像可参考:https://cloud.baidu.com/doc/BAE-Pro/GUIGettingStarted.html#.E8.87.AA.E5.AE.9A.E4.B9.89.E9.95.9C.E5.83.8F

  •   创建应用

使用我们上传的自定义镜像创建应用,具体操作流程请参考:https://cloud.baidu.com/doc/BAE-Pro/GUIGettingStarted.html#.E8.87.AA.E5.AE.9A.E4.B9.89.E9.95.9C.E5.83.8F

  • 配置Logstash

Logstash可以配置到你的其他应用中,将log导入到ElasticSearch中。

Logstash需要java8运行环境,所以可以直接将logstash放入到已有的Bae专业版的java应用用,对于其他语言的,需要制作包含java8和所需环境的镜像。

这里以已有的java应用为例。

(1)将logstash放入代码根目录。可到官网下载logstash的tar.gz:https://www.elastic.co/downloads/logstash,解压到代码根目录。

(2)写入logstash配置文件,参考如下:

input {
    file {
        path => ["/home/bae/log/*.log"]
        type => "bae"
        start_position => "beginning"
    }
}

output {
    elasticsearch {
        hosts => ["http://your_elastic_search_url"]
        index => "logstash-%{type}-%{+YYYY.MM.dd}"
        document_type => "%{type}"
        workers => 1
        flush_size => 20000
        idle_flush_time => 10
        template_overwrite => true
        user => "elastic_search_user"
        password => "elastic_search_password"
    }
}

(3)添加cronb到app.conf中,定时启动logstash,可参考配置app.conf,代码如下:

crond :
  service : on
  crontab :
    - "*/1 * * * *  sh /home/bae/app/run_logstash_if_not.sh"

(4)启动logstash脚本run_logstash_if_not.sh,参考如下:

#!/bin/bash

ps axu | grep logstash | grep -v grep

if [ "$?" -eq 0 ]; then
    nohup /home/bae/app/logstash-2.3.4/bin/logstash -f /home/bae/app/logstash.conf > /home/bae/log/logstash.log 2>&1 &
fi

最终,代码目录结构如下:

+ (baeapp_xdsfsfds)
----app.conf
----logstash.conf
----run_logstash_if_not.sh
----ROOT                    // 你的java应用代码

将代码部署到你的java应用中,即可启动logstash,将log传输到ElasticSearch中。

  • 使用kibana

刚打开kibana会让你配置用户名密码,之后即可使用账户密码登录查看log。

第一次进入会让你配置,只有logstash已经将数据传入,这一步配置就会有相应的选项可以选择(这里需要等logstash运行并把数据传入ElasticSearch)。

如果需要查询相应的关键字,只需要在搜索框写入相应的值。

更多的使用方法,可以参考官网文档:https://www.elastic.co/guide/en/kibana/current/index.html

发表在 BAE使用 | 留下评论

【BAE专业版】如何将日志写入到ElasticSearch

  • 简介

当拥有大量的BAE应用,查看日志和定位日志变得较为繁琐,而将日志写入到ElasticSearch,再通过ElasticSearch的强大搜索功能,即可满足日志的各种查询需求。这里将讲解一个简单的demo,将日志写入到ElasticSearch中。

  • 创建百度ElasticSearch集群

百度ElasticSearch是一项托管服务,让您可以在百度云中轻松地部署、操作和扩展 Elasticsearch,完全兼容ElasticSearch开源API。这里我们以百度ElasticSearch为例,当然也开源自己搭建ElasticSearch集群。

ElasticSearch的url信息:

ElasticSearch Url为http://elastic.baidu.com:8999/集群ID。百度ElasticSearch采用BasicAuthorization,user为superuser,password为创建时设置。

  • 写日志到ElasticSearch中

因为百度ElasticSearch需要BasicAuth,可以通过如下代码创建认证的client:

private WebResource createWebResource() {
    String url = "http://elastic.baidu.com:8999/cluser_id/index/type";
    String user = "superuser";
    String password = "password";
    final ClientConfig config = new DefaultClientConfig();
    Client client = Client.create(config);
    client.addFilter(new HTTPBasicAuthFilter(user, password));
    return client.resource(url);
}

这里所使用的Client、WebResource、ClientConfig和DefaultClientConfig都是jersey-client的1.18.5版本中的类。

ElasticSearch提供了RESTful API,在程序中,可以将日志发送到elasticSearch中。代码大致如下:

public void wirteToElasticSearch(String message) {
    WebResource webResource = createWebResource();
    ClientResponse response = null;
    try {
        response = webResource.type("application/json")
                .post(ClientResponse.class, toJson(message));
    } catch (Exception e)
        e.printStackTrace();
    } finally {
        if (response != null) {
            response.close();
        }
    }
}

其中toJson函数是将message转为json字符串,形式如下:

{
    "createTime": "2016-08-10T16:00:00",
    "content": message"
}
  • 查询ElasticSearch中的日志

查询时,ElasticSearch提供了灵活的查询API,这里仅使用query_string来查询示例。代码如下:

public String queryWriteLog(String message) {
    WebResource webResource = createWebResource().path("/_search");
    return webResource.accept("application/json")
            .type("application/json")
            .post(String.class, toJsonRequest(message));
}

示例代码用于全文匹配包含message的内容,且限制最多返回50个结果。
其中toJsonRequest是将message转为查询请求体,形式如下:

{
    "query": {
        "query_string": {
            "query": "*" + message + "*"
        }
    },
    "size": 50
}

查询结果示例如下:

关于百度ElasticSearch API的使用可以参考:https://cloud.baidu.com/doc/BES/QuickStart.html#.E5.AF.BC.E5.85.A5.E6.9F.A5.E8.AF.A2

  • 总结

写入和查询,都是通过自己代码实现,可以根据各种使用场景进行灵活变化,但需要使用者对ElasticSearch的API较为熟悉。
ELK(ElasticSearch+Logstash+Kibana)日志分析平台,有更好的日志分析和展示,需要更多的资源和机器进行部署,适合有大量日志需要分析的用户。后续将有关于使用BAE专业版搭建ELK的文章。

发表在 BAE使用 | 留下评论

使用BAE快速搭建微信服务

最近BAE基础版已经支持微擎这个微信开源框架了,怀着尝鲜的心态去试用了一下,整体过程非常简单非常顺利,10分钟就完成了所有配置。下面来讲解一下主要的操作过程。

首先登陆到BAE基础版的控制面板,BAE将部署微信公众号作为一个单独场景提供给用户。

点击“部署微信公众号”的按钮,进入创建页面。
在创建页面,可以看到所有支持的微信建站模板,目前支持wemall和微擎两个开源的微信模板。

选择微擎作为建站模板。
接下来就是部署信息和执行单元套餐的配置项

在这些配置项里,有一个特别的地方需要注意,就是代码版本工具使用了打包上传的方式代替了svn/git的方式,根据bae官方的介绍,现在bae提供的所有模板,仅提供打包上传的代码管理方式,究其原因就是因为这些模板都会在运行过程中(初始化安装,升级,插件按照)在本地生产很多的代码和数据文件,如果用svn/git的方式,这些运行时文件是没办法自动提交到svn/git里面的,最直接的影响就是应用failover后,代码和数据都没了,应用一夜回到解放前。打包上传就是为了解决这个问题而产生的,bae会自动备份并打包用户的所有代码和数据,failover的时候会从备份包来恢复,这样就不会对应用产生任何的影响了。
现在看来,有了这个功能,用户再也不用担心数据丢失的问题了,免除了用户自行实现持久化的负担,关于这一点,我要给个大大的赞。

言归正传,选好配置支付订单,一个包含微擎模板的服务器就算搭建好了。
接下来就是去安装了。

访问刚才创建好的服务:http://weiqingtest.duapp.com,进入如下的安装页面

勾选页面下方的复选框,点击“继续”按钮,进入”环境监测”页面,看起来一切正常



继续到下一步配置数据库和管理选项,数据库的话,bae是免费提供mysql数据的,自己去创建一个就好了。

这里有一个坑要说一下,就是在数据库主机里面需要把端口号加上,bae提供的数据库的端口号是4050,不是默认的3306。
配置完成后点击“继续”,就看到下边的安装成功页面了

点击“访问网站首页”按钮,正式进入自己的微擎后端(此处省去了登陆页面,自行补脑吧),
根据微擎的建议,安装成功后先去注册站点,然后需要更新代码。
点击页面右上方的系统,进去之后可以看到“一键更新”和“注册站点”这个功能选项

注册站点

一键更新

更新完成之后会收入如下的弹框提示

这些事都做完,接下来该去配置微信了。
在微擎的公众号列表页,点击“添加公众号”的按钮


主要就是配置上面页面中的信息,配置完成后,微擎会自动帮你生成一个在微信端进行配置的引导页,类似如下的截图



按照上面的描述,在微信端完成配置,然后检测是否接入成功。
成功之后在公众号列表页就可以看到自己的微信号了,如下

到了这一步,所有基本的配置都完成了。微擎提供的应用市场上有各种各样的插件供选择,比如微商城,微小区等,接下来就是根据你的需要选择就是了,完全不需要个人进行代码开发。下边是微擎的应用商城的截屏,可以看到应用还是很丰富的。

总结一下,整体的使用体验非常好,按照页面上的描述操作就行了,没有任何的技术门槛。
所有的操作加起来,10分钟就完成了一个公众号后端的搭建,而且没有任何的编码工作,这一点是非常赞的。

发表在 未分类 | 留下评论

tomcat+netty实现TCP连接服务

netty是一个异步的、事件驱动的网络应用程序框架,通过netty可以简化TCP和UDP的socket服务开发(注:目前BAE不支持UDP协议)。

BAE提供的是标准的servlet container环境(tomcat和jetty,本文主要以tomcat为例子),那如何在这样的环境下初始化netty并实现TCP连接的服务呢?

在servlet container环境中,可以通过实现ServletContextListener接口来监听应用启动和停止的事件,我们只需要在启动事件的处理方法中初始化netty即可。

让我们来看一个具体的例子,该例子改编自netty官方的Echo Server例子。

首先,我们需要实现一个ServletContextListener,在contextInitialized方法中初始化netty,让netty监听9000端口:

package test;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class StartNettyServer implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) {
                                ctx.writeAndFlush(msg);
                            }
                        });
                    }
                })
                .option(ChannelOption.SO_BACKLOG, 128)
                .childOption(ChannelOption.SO_KEEPALIVE, true);

        // Bind and start to accept incoming connections.
        b.bind(9000).syncUninterruptibly();
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }

}

然后,在web.xml中配置该listener:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <listener>
        <listener-class>test.StartNettyServer</listener-class>
    </listener>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
</web-app>

最后,打成war包并上传部署,同时将9000端口映射到公网使其可以访问,以BAE专业版为例(BAE基础版需要使用Port服务):

点击保存修改之后,我们通过telnet连上公网IP+9000端口,就可以访问这个Echo Server,输入任何字符串并回车后,服务器会返回相同的内容:

发表在 BAE使用 | 留下评论

【BAE专业版】如何让你的PHP服务支持分布式session

  • 简介

PHP session支持在服务端缓存用户信息以便随后使用。当在BAE部署环境的实例数大于1时,我们无法通过内存实现分布式session,这是因为环境的多个实例并不共享内存。本文主要基于PHP讨论在BAE专业版上实现分布式session的一种方案。

  • 创建简单缓存服务

百度开放云提供简单缓存服务SCS,支持memcache和redis,因此我们可以利用SCS实现分布式session。BAE专业版的环境实例可以通过内网访问SCS。这里我们以memcache为例,当然也可以使用redis。

注意,需要SCS和BAE部署在百度开放云的同一个区域。我们在“华北-北京“区域创建一个memcache。创建成功后,可以在创建的scs集群详情页获取访问地址和端口号,如下图所示。

  • 通过简单缓存服务实现分布式session

创建一个PHP5.4的应用,并部署一个环境,在”环境详情->设置->关联SCS”中,将该环境和创建的memcache建立关联,BAE会在后台将该环境下所有实例的ip加到该memcache的白名单中。关联的具体操作方法可以参考BAE官方文档环境管理中关联RDS或SCS一节。

我们可以通过修改php.ini配置memcache保存session。php.ini的修改方法请参考BAE官方文档php高级配置中的自定义php.ini。在应用根目录下增加一个php.ini文件,将mamcache的配置写入到该文件。

session.save_handler = memcache
session.save_path = "tcp://memcache.utmppnqy.scs.bj.baidubce.com:11211"
  • 验证配置结果

我们通过修改index.php文件测试,验证分布式session是否生效,代码示例如下:

<?php
    session_start();
    // 缓存session开始的时间
    if (!isset($_SESSION['test'])) {
        $_SESSION['test'] = time();
    }

    print session_id();
    print "<br><br>";
    print $_SESSION['test'];
    print "<br><br>";
    print time();
?>

部署代码成功后,通过浏览器刷新访问页面,我们发现打印的session开始时间在同一个session id下面保持不变,即分布式session生效。

发表在 未分类 | 留下评论

【BAE基础版】玩转WordPress模板

伴随着“应用模板”功能的推出,BAE基础版实现了一次华丽的转身。

我们先看一下模板应用和普通应用(空应用)的区别:

(● 支持 – 不支持 ○ 即将支持)

分类 功能 空应用 模板应用
代码管理 打包上传 -
svn -
git -
扩展性 执行单元个数 1-100可调 1固定
内存 64MB-2GB可调 64MB-2GB可调
带宽 5Mb/s可扩展 5Mb/s固定
语言环境 php 5.4 由模板决定
php 5.5(含Zend Guard Loader) 由模板决定
java 7 由模板决定
java 8 由模板决定
python 2.7 由模板决定
node.js 4.2 由模板决定
自定义docker镜像 -
存储 本地文件持久化存储 -
手动备份线上代码 -
模板在线升级 -
模板在线安装插件 -

注意:

  • 使用模板创建的应用,其执行单元个数被限定为1,不支持分布式扩展。
  • 使用模板创建的应用,其本地文件不会因应用重启而被清空,持久化的目录为/home/bae/app。而空应用因支持多个执行单元,本地文件在应用重启时会被清空,因此应将需要持久化存储的文件写到BOS或者数据库中。
  • 使用模板创建的应用支持手动备份线上代码,备份目录为/home/bae/app。
  • 使用模板创建的应用支持多个代码版本的部署、删除和下载操作,部署失败可以手动回滚(重新部署)到之前的版本。空应用目前只能通过SVN/GIT部署最新版本,不支持回滚。

创建

下面我们开始创建一个WordPress应用。

进入“产品服务 / 应用引擎BAE-部署列表 / 添加部署”,选择WordPress模板创建新应用。

选择模板创建应用

配置

回到“产品服务 / 应用引擎BAE-部署列表”,等待应用创建成功后,点击域名进行WordPress的配置。

点击域名进行配置

WordPress需要配置数据库,如果没有可以在BAE基础版的扩展服务中创建一个新的数据库(目前BAE基础版可以创建5个免费MySQL数据库)。当然也可以使用百度RDS数据库,打开外网权限即可。

查看mysql数据库

WordPress配置数据库。

WP配置数据库

其他的WordPress的配置就看着配吧,应该都能轻松搞定,一会功夫就能开始把玩自己的WordPress站点了。

备份

通过模板创建的WordPress没有任何限制,也不用担心在线生成的数据丢失。

有喜欢的主题,装;
有喜欢的插件,装;
出了新的版本,装;
总之就是装装装,随便玩。

如果还是不放心,就去手动备份一下。回到“产品服务 / 应用引擎BAE-部署列表”,点击应用的“打包上传”,进入“发布设置”页面。

点击打包上传进行手动备份

在“代码管理”点击“添加备份”,稍后就会生成一个新的代码版本,直接打包了当时线上/home/bae/app目录下的数据,/home/bae/log下的日志文件不会打包。

添加备份

插件

WP-Mail-SMTP

WordPress模板预装了一个邮件发送的插件WP-Mail-SMTP,配置好后可以允许访客注册账号和找回账号。

首先,进入QQ邮件的设置页面,开启QQ的SMTP服务。

QQ-SMTP密码

然后在WordPress插件管理页面启用WP-Mail-SMTP。

启用WP-Mail-SMTP

然后点击WP-Mail-SMTP的Setting开始配置SMTP。

WP配置SMTP

最后,在设置页最下方输入一个邮箱测试一下,看看是否可以发送成功。

百度云插件

目前模板应用的磁盘空间有限,建议使用百度云插件,将多媒体数据(如图片、视频)上传到BOS。由于该插件还未官方化,用户须自行安装。

首先,进入应用的发布设置页面,对当前线上版本进行备份并下载代码包,下载成功后解压。

应用备份并下载

然后从github下载插件压缩包(压缩包里BaiduBce.phar就是bos的php sdk,插件代码都在wp-bae.php里)。将插件解压后复制到wp-content/plugins目录下。重新打包(zip压缩)代码并上传。

添加插件打包上传

再然后选择刚上传的版本进行部署,注意部署会先清理掉线上磁盘的数据,所以代码修改过程中尽量避免产生新的数据。

打包上传后部署

部署成功后,激活并配置插件,可参照插件下载页面的使用说明。

在“设置-百度云插件”里填写Bucket名、AK、SK、HOST(HOST用来确定bucket所在的region,e.g. bj.bcebos.com)。这里有一点要注意,建议为wordpress单独建一个bucket,然后把bucket设为公共读(即只有本人能上传,但所有人都能读取)。之后在媒体库里正常添加文件即可,所有添加的文件会按照月份存放(e.g. uploads/2015/12/img1.jpg),相同的目录结构会创建在BOS的bucket下。

最后

应用模板有其特殊性,针对的模板多会在线生成一些数据,并不适合放在无状态的容器中运行,因此针对模板类的应用,释放了无状态的限制(应用重启、休眠、开启等操作不再清理线上数据),但同时引入了新的限制,只允许部署一个实例(多个有状态的容器之间的数据同步是个问题,如果使用共享存储,则成本较高)。

 

百度BAE已经开始加快脚步,推陈出新,欢迎试用。

BAE产品首页:
https://bce.baidu.com/product/bae.html

BAE的官方论坛:
http://developer.baidu.com/forum/topic/list?boardId=66

发表在 未分类 | 留下评论

【BAE基础版】在Python Web中增加定时任务运行Python脚本

  • 简介

在BAE Python Web部署中,通过crond定时执行Python脚本时,可能触发定时任务异常。本文主要介绍异常产生原因及解决方案。关于crond使用方法,请参考以下链接:

https://bce.baidu.com/doc/BAE/GUIGettingStarted.html#.E9.85.8D.E7.BD.AEapp.conf

  • 异常现象

以Python Web中的mongo操作为例,配置app.conf,定时执行mongo db操作脚本。(脚本来源:Pyhon连接MongoDB

#-*- coding:utf-8 -*-

import pymongo
from pymongo import MongoClient

def test_mongo():
    ### 连接MongoDB服务
    ### 从管理控制台获取host, port, db_name, api_key, secret_key
    con = MongoClient("mongo.duapp.com", 8908)
    db_name = "CAoKTghXtKNEGBaLAYRj" # 数据库名称
    db = con[db_name]
    api_key = "1df5f7da3c5c48559f34589d83126c6c" # 用户AK
    secret_key = "566417acbb6349a98a09cd6f5edbb402" # 用户SK
    db.authenticate(api_key, secret_key)

    ### 插入数据到集合test
    collection_name = 'test'
    db[collection_name].insert({"id":10, 'value':"test test"})

    ### 查询集合test
    cursor = db[collection_name].find()
    con.close()
    return "select collection test %s"%str(cursor[0])

test_mongo()

将以上脚本保存在根目录/home/bae/app/mongo.py,并配置app.conf,增加定时任务,定时执行mongo db操作:

crond :
  service : on
  crontab :
    - "* * * * * python /home/bae/app/mongo.py 1>/dev/null 2>>/home/bae/log/mongo.error.log"

部署成功后,我们发现该mongo db的collection中并没有新的记录插入,开通port服务ssh登录到该实例上(参考BAE基础版Port服务),mongo.error.log中的信息显示如下:

Traceback (most recent call last):
  File "/home/bae/app/mongo.py", line 3, in
    import pymongo
ImportError: No module named pymongo

以上error信息说明在Python Web的定时脚本中运行用户的Python脚本时,无法加载用户自定义的pymongo依赖包。

  • 问题原因

导致该问题的原因如下:

用户自定义依赖配置文件requirements.txt,用于配置编译时的依赖包。开发者部署代码时,requirements.txt中指定的依赖包会下载安装到应用根目录: /home/bae/app/deps (可参考Python部署文件中requirements.txt的说明)。在Python Web中已将 ”/home/bae/app/deps” 添加到Python默认的模块搜索路径,而定时任务并没有添加该目录到默认的模块搜索路径中。

  • 解决方案

在定时任务运行的python脚本中,将”/home/bae/app/deps”添加到Python默认的模块搜索路径中。

方案一,在python脚本mongo.py的开头为Python添加默认模块搜索路径如下:

import sys
sys.path.append('/home/bae/app/deps')

方案二,将需要Python运行的定时任务封装成api,在定时任务中curl该api。同时需要注意为该api增加权限验证。

发表在 未分类 | 留下评论

实力科普,让网站和App搬家不再痛苦(BAE篇)

给网站、App搬家是个细致的体力活,容易遇到各种意外,轻则停服、影响收入,重则数据丢失,造成不可挽回的损失。因此需要制定一个周密细致的计划,所谓谋定而后动,三思而后行。

 首先要选择一个靠谱的平台。目前提供网站、app托管服务的平台很多,有免费的也有收费的,有境内的也有境外的,有大平台也有小平台。建议站长、开发者朋友从以下几个方面来选择:

稳定性:建议选择比较大的、比较重视这块业务的平台,服务相对有保障,避免停服带来的尴尬。境外的平台虽然不用备案,但是访问速度肯定没法和国内平台比。另外说墙就墙了,因此除非不得已,还是建议选择国内的平台。

性价比:价格是一个关键因素,但也不是越便宜越好。免费的服务不推荐,说停就停了,没有保障,而且往往会在数据迁移方面设置各种障碍。另外还要考虑收费是否灵活,如果不灵活就失去云服务的优势了。

可扩展性:CPU、内存、容量和带宽都要能够很方便的扩展。毕竟等网站、App的流量、数据量上来后,谁都不想再搬家,这个站长、开发者朋友都懂的。

安全性:平台要能够提供最起码的入侵和攻击防护,这一点大平台肯定比小平台更有优势。在互联网上裸奔是个近乎自杀的行为,分分钟让你中招。

接下来以百度开放云应用引擎BAE为例,介绍如何进行网站、App的迁移。

百度应用引擎(Baidu App Engine,简称BAE)是国内商业运营时间最久、用户群体最为庞大的PaaS平台之一,提供弹性、一站式的应用部署服务,支持php/java/node.js/python等各种语言。用户只需上传代码,BAE自动完成运行环境配置、应用部署、均衡负载、资源监控、日志收集等各项任务,大大简化运维部署工作。

同时基于百度开放云海量的资源,基于docker技术和分布式架构,BAE提供灵活、弹性、分钟级的资源扩展能力,升级扩容无需重新部署代码,轻松应对各种高并发访问场景(如“双十一”、“秒杀”、“春运订票”等)。

一般的站长和开发者朋友对BAE应该并不陌生,这里就不详细展开了,不清楚的朋友可以访问其官网、在线帮助、论坛脑补一下:

https://bce.baidu.com/product/bae.html

https://bce.baidu.com/doc/BAE/QuickGuide.html

https://bce.baidu.com/doc/BAE-Pro/QuickGuide.html

http://developer.baidu.com/forum/topic/list?boardId=66

(值得一提的是BAE刚刚支持了自定义docker镜像,这对于当下如火如荼的docker开发者而言是一个福音。)

第一步:评估可行性

迁移网站之前,首先要评估您的网站、App能否在BAE上正常运行。主要从两个方面来判断:

一是运行环境是否满足要求,BAE提供了支持以下语言的运行化境:

语言环境

BAE基础版

BAE专业版

php 5.4

php 5.5(含Zend Guard Loader)

php 5.6(含Zend Guard Loader)

-

java 7

java 8

python 2.7

node.js 4.2

自定义docker镜像

-

(*通过自定义docker镜像,您可以自行安装任何语言需要的依赖和组件。)

二是您的网站、App是否需要读写本地文件。BAE虽然允许程序读写本地文件,但是在应用重启时更新会丢失。这主要是因为BAE是为支持高并发、分布式应用部署而进行设计的,要求每个执行单元/服务器实例上运行的程序是无状态、无差别的,这就要求不能将需要长久保存的数据写到本地(否则下次访问该文件时,会因不知道这个文件存在哪个实例上而导致出错)。此外,应用在故障重启或者发布新版本时,也会从代码库中取出对应的版本覆盖本地空间,导致本地文件被覆盖。通俗来说,就是BAE的代码空间和运行空间是分离的,代码空间里的文件不会丢,运行空间里的文件在重启或发布新版本时会被清空。因此要将需要持久保存的数据写到数据库或者外部存储介质中(如BOS)。

因此,您可能需要修改原来的程序以适应BAE这种分布式部署架构。好处很明显,分布式的架构将使您的应用将更加稳定、健壮,并能够应对高并发的访问场景。

对于一些开源框架(如Wordpress),已经有一些专门的插件,帮助您将本地文件读写改成读写到BOS,详情请参考BOS论坛上的一个帖子

值得注意的是,BAE即将推出应用模板功能,届时将支持本地文件的永久存储,模板原生代码不需要改动即可正常运行,支持在线安装模板插件、升级模板、备份数据,将极大提高对各种开源框架的兼容性。

 

第二步:BAE基础版 vs. 专业版

 需要确认是迁移到BAE基础版还是专业版。这两个版本各有侧重:

BAE基础版:资源共享,更经济、更便捷,适合部署中小型站点

BAE专业版:资源独享,更安全、更强大,适合部署中大型站点

两者详细对比如下(●支持   -不支持    〇即将支持):

 

分类

功能

BAE基础版

BAE专业版

网络

10线BGP网络接入

公网IP

共享IP

独立IP

带宽

共享5Mb/s可扩展

独享1-1000Mb/s可调

端口

随机端口

自定义端口

安全

私有虚拟网络

自定义https证书

WAF防御

流量清洗

存储

BOS(对象存储)

内网连接(另行付费)

内网连接(另行付费)

RDS(MySQL)

外网连接(另行付费)

内网连接(另行付费)

SCS(简单缓存服务)

外网连接(另行付费)

内网连接(另行付费)

MySQL(共享,容量1GB,暂不支持升级)

内网连接(5个免费实例)

-

MongoDB(共享,容量1GB,暂不支持升级)

内网连接(3个免费实例)

内网连接(3个免费实例)

Redis(100000kv,,暂不支持升级)

内网连接(1个免费实例)

-

多环境

- 支持预览

环境变量

版本回滚

资源

计算资源

共享

独享

资源监控

 

第三步:数据库迁移

确认数据库服务是否满足需要。目前BAE基础版提供了免费的MySQL和MongoDB服务,BAE专业版可以对接RDS(关系型数据库)。其中免费MySQL支持从BOS(百度对象存储)导入数据,而RDS提供了数据迁移工具,方便用户进行全量数据迁移。一般推荐的组合是:

BAE基础版+BAE基础版扩展服务中的MySQL/MongoDB/Redis

BAE专业版+RDS+SCS

如果以上数据库不满足您的要求,您还可以用云服务器BCC自行搭建数据库服务器。

 

第四步:搭建网站、App

 接下来是创建BAE应用、部署好代码。创建好数据库,将数据迁移过来。

具体的操作步骤可以参考BAE和RDS相应的帮助文档。RDS目前提供MySQL和SQLServer数据库服务。BAE专业版可以内网访问BAE基础版中的共享MongoDB服务。

如果您的网站、App对性能有较高要求,您还可以考虑使用缓存服务SCSRedis

同样,您还可以使用CDN服务,以提升站点在不同地区的访问速度。

建议对搭建好的网站、App要进行充分的测试。

下图是通过BAE专业版搭建高并发网站、App的系统架构图,供大家参考:

 

第五步:备案

 根据相关法规要求,网站需要进行站点备案(App不需要)。

如果您的站点之前已有备案,则需要进行备案的转入。如果您的站点之前没有备案,则要进行全新备案。

百度开放云提供免费的备案服务,详情可点击这里查看。

 

第六步:切换域名

请注意,在将域名指向对应的BAE站点之前,您的网站必须是已经完成备案的。

 

结束语

 在云计算连接一切的年代,你永远不用担心无家可归。

百度开放云是国内首家提供托管平台服务(BAE)的云计算厂商。四年来,我们累计为超过十五万名用户提供此服务。四年来,我们始终在这里。

关于百度开放云及BAE的更多资讯,请访问 https://bce.baidu.com/index.html

发表在 未分类 | 留下评论

如何让你的应用更加安全保密 – 在BAE上使用Zend Guard Loader

Zend Guard是一个PHP 源码加密产品解决方案,能有效地防止程序未经许可的使用和逆向工程。Zend Guard Loader 则是支持 Zend Guard 加密后的 PHP 代码的运行环境。

目前BAE专业版的php5.5环境已默认支持了Zend Guard Loader用户可以直接使用。

但是由于BAE的php5.4环境(包括专业版和基础版)默认启用了缓存加速扩展OPcache,而php5.4中OPcache和Zend Guard Loader有兼容性问题,所以目前BAE的php5.4环境没有默认支持Zend Guard Loader。本文则介绍了如何在BAE的php5.4环境中使用Zend Guard Loader。

BAE提供了添加php自定义扩展功能(http://godbae.duapp.com/?p=302),利用这个功能,需要Zend Guard Loader的php5.4用户可以通过自定义的方式安装启用Zend Guard Loader。具体步骤如下:

 

1. 下载ZendGuardLoader.so

去zend官网(http://www.zend.com/en/products/loader/downloads#Linux)下载linux版Zend Guard Loader for PHP 5.4 – 64 bit,需要注册账号登陆后方能下载,下载后得到ZendGuardLoader-70429-PHP-5.4-linux-glibc23-x86_64.tar.gz,解压后可获得ZendGuardLoader.so文件

 

2. 在代码中加入ZendGuardLoader并关闭OPcache

2.1 在代码根目录中创建user_extention目录

2.2 将第一步中所得的ZendGuardLoader.so拷入user_extention目录

2.3 在user_extention目录中加入ZendGuardLoader.ini

==>如果你使用的是BAE基础版php5.4,ZendGuardLoader.ini内容如下:

[ZendGuardLoader]
zend_extension=/usr/lib/php5/20100525/ZendGuardLoader.so

==>如果你使用的是BAE专业版php5.4,ZendGuardLoader.ini内容如下:

[ZendGuardLoader]
zend_extension=/home/admin/php/lib/php/20100525/ZendGuardLoader.so

2.4 在user_extention目录中加入opcache_user.ini,内容如下

opcache.enable=0

最终完成的目录结构如下图所示(以基础版为例)
Zend Guard Loader Pic 1

 

3. 上传代码并重启应用

将更新后的代码上传,注意不要漏了.so,重启应用,ZendGuardLoader就生效了,你可以用phpInfo()检查下,确认ZendGuardLoader已启用,OPcache已停用的话,用Zend Guard加密后的php代码就可以在BAE Php 5.4环境中运行啦。
Zend Guard Loader Pic2

发表在 未分类 | 留下评论

【BAE专业版】玩转WordPress系列之快速搭建

准备工作

要搭建WordPress@Cloud,我们只需要如下三个云产品:

  • BAE专业版应用(WordPress网站代码托管和部署服务)
  • RDS实例(WordPress的MySQL数据存储)
  • BOS Bucket(WordPress的多媒体文件存储)

创建 “BAE专业版应用”

首先,上BAE专业版的控制台创建一个应用,初始配置:(选Web、php5.4、打包上传

创建“RDS实例”

然后,上RDS控制台创建一个实例,初始配置:

创建RDS实例

同时在RDS控制台的“账号管理”页面创建一个访问账号,在“数据库管理【BAE专业版】玩转WordPress系列 – 修正”页面创建一个数据库并授权账号(允许读写操作):

创建RDS账号

创建RDS数据库

创建“BOS Bucket”

再然后,上BOS控制台创建一个Bucket,初始配置:(选北京、公共读

创建BOS Bucket

上面选择的初始配置都是最低配置的套餐,后续可根据网站的使用情况调整套餐的配置,比如可以查看RDS的监控,如果磁盘使用率过高,就可以调高RDS的容量。由于Bucket的读写权限是公共读,所以请不要在这个Bucket放置敏感信息。

关联“BAE专业版应用”和“RDS实例”

最后一步,为了能让部署在BAE专业版上的WordPress能够访问RDS实例,需要上BAE专业版的控制台,进入之前创建的应用的设置页面,创建RDS关联。

BAE应用关联RDS

部署WordPress

接下来我们就可以开始愉快的部署WordPress了。

下载WordPress

首先,我们可以去WordPress官网瞧瞧,下载最新版WordPress 4.4.1(修复了一个XSS漏洞),或者上官网指定的中文网站下载中文版WordPress4.4.1。下载后解压到WordPress本地目录:

WordPress本地目录

然后,下载一个BAE的插件(WordPress个人云存储插件,个人贡献),该插件用于将多媒体文件持久化到BOS。关于WordPress在线生成内容的持久化问题,我们后续再讨论。下载解压后,将该插件复制到WordPress本地目录的wp-content/plugins

WordPress本地目录添加BOS插件

打包上传WordPress

首先,上BAE专业版的控制台,进入应用的代码管理页面,下载初始代码。

下载初始代码

将app.conf和bae_app_conf.lua复制到WordPress本地目录:

WordPress本地目录合并BAE初始代码

然后,把WordPress本地目录打包,建议命名以版本号结尾,比如my-wordpress-1.0.0。

再然后,上BAE专业版的控制台,点击应用的部署操作:

WordPress1.0.0打包上传

等待几秒后,可以点击应用的二级域名,打开应用的主页,查看部署是否成功。如果出现如下页面,则部署成功;否者算失败,这时可以查看应用日志(builder.stderr.log)寻找原因。

WordPress初始化向导

在线配置WordPress

点击应用的二级域名,打开应用主页,WordPress会自动引导配置。第一页的配置是数据库配置,数据库名、用户名、密码和主机需要到RDS的控制台寻找,在创建“RDS实例”时都已经准备好。

WordPress初始化向导-配置数据库

WordPress初始化向导-数据库配置成功

接下来一路按照WordPress的提示进行配置,迫不及待的进入WordPress的管理页面,开始领略WordPress的风采。

持久化WordPress在线内容

为什么要把这一步设置拎出来单独作为一节?那是因为这一步非常非常重要。曾经有朋友在BAE基础版上部署了WordPress,一开始玩的很嗨,结果某一天突然发现WordPress变成未配置状态了,部分在线生成的内容在重新配置数据库后也无法恢复了,那叫一个郁闷啊。问题就在于BAE应用目前还不支持永久存储(卷,文件系统),应用一旦重新部署(可能failover了)就会导致在线生成的内容(MySQL的除外)丢失,因此支持持久化在线内容这一功能绝对是WordPress的强需求,期待BAE后续推出。

当然我们也不要气馁,不凡试试曲线救国。WordPress在线生成的内容,可以分为三大类:

  1. 进入MySQL的数据,比如文本内容、配置数据等。本身已经持久化,不再展开。
  2. 配置代码(wp-config.php)、插件、主题等。数据存放在应用部署的磁盘上。我们可以借助BAE的代码托管进行持久化。
  3. 多媒体文件,如果图片、视频等。数据也存放在应用部署的磁盘上。我们可以借助前面下载的BAE的插件(WordPress个人云存储插件),将文件转存到BOS进行持久化。

第二类数据持久化

此类数据目前只能借助BAE的代码托管进行持久化。比如wp-config.php,这个配置代码文件是在WordPress初始化配置的时候在线生成,我们需要从线上抓下来再次随代码提交一次,才能防止应用重启时丢失。操作如下:

  1. 使用BAE专业版的WebSSH功能查看线上部署的文件。在应用的环境详情页的最下面,点击WebSSH,进入WebSSH操作页面,就可以像操作Linux一样查看线上部署的文件了。
    WordPress线上目录(WebSSH)
  2. 找到wp-config.php文件,我本来想直接把这个文件抓下来的,结果发现WebSSH很多命令用不了。只好cat一下,把所有内容复制出来。注意,内容选中的瞬间,会出现一把剪刀,需要快速点击它才能复制。我是直接把WordPress本地目录中的wp-config-sample.php复制到wp-config.php,然后把线上的wp-config.php的内容复制进去。如果有人发现更快捷的方法,望分享。
    WordPress复制wp-config.php(WebSSH)
  3. 重新打包WordPress的本地目录,命名为my-wordpress-1.0.1.zip,再次上传并部署。部署成功后,打开主页,你会发现wp-config.php持久化成功,再也不会出现WordPress的配置向导了。

线上添加的WordPress插件和主题等代码的持久化也是类似的,我们建议去WordPress官网下载,通过打包上传实现持久化。

第三类数据持久化

此类数据我们借助一个BAE的插件(WordPress个人云存储插件),之前已经放入WordPress,现在终于要起作用了。

  1. 打开WordPress主页,进入管理界面,点击插件,启用“百度云插件”。WordPress启用BOS插件
  2. 点击“百度云插件”的设置按钮,对BOS存储进行设置。Bucket可从BOS控制台的找到,之前已经创建好。HOST在Bucket的属性页可以找到。AK/SK在用户中心的安全认证页寻找。WordPress配置BOS插件
  3. 现在发个带图片的文章试试。你会发现添加的媒体会自动生成BOS的URL,并上传到之前配置的Bucket当中,以供随时使用。WordPress插入多媒体WordPress发布第一篇文章

 

数据持久化畅想

曲线救国的方案虽然解决了持久化的问题,但是使用起来显得很不方便。

比如通过代码托管进行持久化的方式,每次WordPress线上加入了新的插件、主题什么的,都要抓下来作为代码提交。而且为了支持WordPress的在线编辑,我们只能部署一个实例,否则就乱套了,新加的插件在哪个实例都不知道,各个实例间还出现了不一致。

通过插件的方式倒是一次性解决了媒体文件的持久化问题,但是毕竟解决的还不够彻底。

敬请期待BAE后续推出WordPress镜像,数据共享方案。到时候我们什么都不用做,就能满足在线内容持久化的需求,同时支持多实例数据共享。

使用WordPress

现在开始使用WordPress生产你的内容吧。

WordPress资源消耗情况

现在WordPress上几乎什么都没有,看看它消耗了多少资源吧。

BAE专业版实例的资源消耗

BAE实例资源消耗

RDS实例的资源消耗

RDS实例资源消耗

发表在 未分类 | 留下评论