Ribbon 和 wowza 的集成开发
Ribbon 是提供 REST 服务的区域感知负载均衡器,它在 wowza 的前端,应该部署在专业的 REST 容器下,而不是流媒体服务器 wowza 下。
本文介绍了 Ribbon 和 wowza 的集成,Ribbon 作为 wowza 的一个插件部署在了 wowza 容器下,仅供 Ribbon 开发、部署的技术參考,现实中绝不可能出现这样的情况。由于 Wowza 毕竟不是专业提供 REST 服务的容器。关于 Ribbon 和 Wowza 真实场景的架构部署,请关注作者兴许博客。
        本文是在《让你的 wowza 服务器提供 RESTful web 服务》样例的基础上进一步进行研发。
        1. 新建 maven 项目
        參考《让你的 wowza 服务器提供 RESTful web 服务》步骤。新建的 maven 项目 defonds-server-module 例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGVmb25kcw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="新建好的mvn项目" align="middle" />
        2. 编辑 Ribbon 配置文件
        依据你自己的集群。配置 Ribbon。比方作者 demo 用的配置文件例如以下:
# Max number of retries on the same server (excluding the first try)
sample-client.ribbon.MaxAutoRetries=1 # Max number of next servers to retry (excluding the first server)
sample-client.ribbon.MaxAutoRetriesNextServer=1 # Whether all operations can be retried for this client
sample-client.ribbon.OkToRetryOnAllOperations=true # Interval to refresh the server list from the source
sample-client.ribbon.ServerListRefreshInterval=2000 # Connect timeout used by Apache HttpClient
sample-client.ribbon.ConnectTimeout=3000 # Read timeout used by Apache HttpClient
sample-client.ribbon.ReadTimeout=3000 # Initial list of servers, can be changed via Archaius dynamic property at runtime
sample-client.ribbon.listOfServers=www.baidu.com:80,www.163.com:80,www.csdn.net:80
然后把这个文件放在你的 classpath 下。
        3. 编写 LB 调用类
package com.defonds.wms.module.server; import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException; import com.netflix.client.ClientException;
import com.netflix.client.ClientFactory;
import com.netflix.client.http.HttpRequest;
import com.netflix.client.http.HttpResponse;
import com.netflix.config.ConfigurationManager;
import com.netflix.niws.client.http.RestClient;
import com.wowza.wms.http.HTTProvider2Base;
import com.wowza.wms.http.IHTTPRequest;
import com.wowza.wms.http.IHTTPResponse;
import com.wowza.wms.logging.WMSLogger;
import com.wowza.wms.logging.WMSLoggerFactory;
import com.wowza.wms.vhost.IVHost; public class RibbonLBRestService extends HTTProvider2Base {
private static final WMSLogger logger = WMSLoggerFactory.getInstance().getLoggerObj(RibbonLBRestService.class.getName());
public static RestClient restClient = null; static {
try {
// Load the properties file using Archaius ConfigurationManager
ConfigurationManager.loadPropertiesFromResources("sample-client.properties");
// Use ClientFactory to create client and the load balancer
RibbonLBRestService.restClient = (RestClient) ClientFactory.getNamedClient("sample-client");
} catch (IOException e) {
logger.error(e.getMessage(), e);
} } @Override
public void onHTTPRequest(IVHost arg0, IHTTPRequest request, IHTTPResponse response) {
String jsonObject = null;
response.setHeader("Content-Type", "application/json");
try {
String serverURI = RibbonLBRestService.getURI();
response.setResponseCode(200);
jsonObject = "{\"server_uri\":\"" + serverURI + "\"}";
} catch (ClientException e2) {
response.setResponseCode(400);
jsonObject = "{\"error_code\":\"40039\"}";
logger.error(e2.getMessage(), e2); } catch (URISyntaxException e3) {
response.setResponseCode(400);
jsonObject = "{\"error_code\":\"40023\"}";
logger.error(e3.getMessage(), e3);
} finally {
// Get the printwriter object from response to write the required json object to the output stream
OutputStream out = response.getOutputStream();
try {
out.write(jsonObject.getBytes());
out.flush();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
} } public synchronized static String getURI() throws ClientException, URISyntaxException {
// Build the http request using the builder
// Note that we only supply the path part (“/”) of the URI
// The complete URI will be computed by the client once the server is chosen by the load balancer
HttpRequest ribbonRequest = HttpRequest.newBuilder().uri(new URI("/")).build();
HttpResponse ribbonResponse;
// Call client.executeWithLoadBalancer() API, not the execute() API
ribbonResponse = RibbonLBRestService.restClient.executeWithLoadBalancer(ribbonRequest);
return ribbonResponse.getRequestedURI().toString();
} public synchronized static void changeServersPoolDynamically(String serverList) throws ClientException {
// Dynamically change the server pool from the configuration
ConfigurationManager.getConfigInstance().setProperty(
"sample-client.ribbon.listOfServers", serverList);
logger.debug("changing servers ...");
try {
// Wait until server list is refreshed (2 seconds refresh interval defined in properties file)
Thread.sleep(3000);
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
} }
这个类将会给 ribbonLB 的 REST 请求返回一台服务器地址。假设请求失败,返回对应的错误码。
这个类还提供了一个公开方法,用于动态调整负载均衡节点。
        4. 编写动态改动负载均衡节点接口
package com.defonds.wms.module.server; import java.io.IOException;
import java.io.OutputStream; import com.netflix.client.ClientException;
import com.wowza.wms.http.HTTProvider2Base;
import com.wowza.wms.http.IHTTPRequest;
import com.wowza.wms.http.IHTTPResponse;
import com.wowza.wms.logging.WMSLogger;
import com.wowza.wms.logging.WMSLoggerFactory;
import com.wowza.wms.vhost.IVHost; public class RibbonChangeInstanceService extends HTTProvider2Base {
private static final WMSLogger logger = WMSLoggerFactory.getInstance().getLoggerObj(RibbonChangeInstanceService.class.getName()); @Override
public void onHTTPRequest(IVHost arg0, IHTTPRequest request, IHTTPResponse response) {
String serverList = request.getParameter("server_list"); // TODO Authorization // TODO serverList str check String jsonObject = null;
response.setHeader("Content-Type", "application/json");
try {
RibbonLBRestService.changeServersPoolDynamically(serverList);
response.setResponseCode(200);
jsonObject = "{\"error_code\":\"0\"}"; // server list is changed successfully
} catch (ClientException e2) {
response.setResponseCode(400);
jsonObject = "{\"error_code\":\"40039\"}";
logger.error(e2.getMessage(), e2);
} finally {
// Get the printwriter object from response to write the required json object to the output stream
OutputStream out = response.getOutputStream();
try {
out.write(jsonObject.getBytes());
out.flush();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
} } }
这个类提供了一个用于动态改动负载均衡节点池的接口。假设改动成功返回错误码为 0,否则为其它值。
5. 编辑 maven 依赖
编辑项目 pom.xml。将上边依赖到的包导入:
<!-- ribbon -->
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-core</artifactId>
<version>0.3.12</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-httpclient</artifactId>
<version>0.3.12</version>
</dependency>
6. 编辑 VHost.xml
        编辑 %wowza%/conf/VHost.xml,把上边写的两个 HTTPProvider 加入进去:
<HTTPProvider>
<BaseClass>com.defonds.wms.module.server.RibbonLBRestService</BaseClass>
<RequestFilters>ribbonLB*</RequestFilters>
<AuthenticationMethod>none</AuthenticationMethod>
</HTTPProvider>
<HTTPProvider>
<BaseClass>com.defonds.wms.module.server.RibbonChangeInstanceService</BaseClass>
<RequestFilters>ribbonChange*</RequestFilters>
<AuthenticationMethod>none</AuthenticationMethod>
</HTTPProvider>
7. 项目又一次打包部署
        命令行切换到你的 defonds-server-module 项目文件夹下,运行		
mvn package
        8. 訪问接口
        debug 启动 defonds-server-module,然后在浏览器訪问 http://localhost:1935/ribbonLB,以向 Ribbon 要一个服务器地址,返回结果例如以下:
{"server_uri":"http://www.csdn.net:80/"}
        返回的是服务器 URL 是 http://www.csdn.net:80/。然后在浏览器訪问 http://localhost:1935/ribbonChange?server_list=www.qq.com:80,www.126.com:80。以动态调整负载均衡节点。返回结果例如以下:
{"error_code":"0"}
        这个返回码说明已经调整成功。我们能够继续訪问 http://localhost:1935/ribbonLB 验证一下,返回结果是:
{"server_uri":"http://www.qq.com:80/"}
        没错,确实成功了。
注意
        以上 Ribbon 动态调整的负载均衡节点是内存里的配置。服务器下的 sample-client.properties 配置的节点依然是:
sample-client.ribbon.listOfServers=www.baidu.com:80,www.163.com:80,www.csdn.net:80
这样 REST 服务重新启动后。读取的负载均衡节点依然是改动前的。假设你想在 REST 服务器断电重新启动后读取改动后的。最好把 Ribbon 属性在分布式缓存服务器中进行存放和读取,比方 Redis。
另:本文演示样例代码已上传 CSDN 资源。下载地址:http://download.csdn.net/detail/defonds/7526359。
Ribbon 和 wowza 的集成开发的更多相关文章
- neurosolutions  人工神经网络集成开发环境   keras
		人工神经网络集成开发环境 : http://www.neurosolutions.com/ keras: https://github.com/fchollet/keras 文档 http ... 
- windows和linux中搭建python集成开发环境IDE——如何设置多个python环境
		本系列分为两篇: 1.[转]windows和linux中搭建python集成开发环境IDE 2.[转]linux和windows下安装python集成开发环境及其python包 3.windows和l ... 
- 【超全整理】J2EE集成开发环境MyEclipse使用心得汇总
		一.首先我们为什么需要MyEclipse? 下面允许我做一些简要的介绍: 应该大家都知道另一个MyEclipse的近亲——Eclipse的优点:免费.程序代码排版功能.有中文汉化包.可增设许多功能强大 ... 
- 【Python基础学习一】在OSX系统下搭建Python语言集成开发环境 附激活码
		Python是一门简单易学,功能强大的编程语言.它具有高效的高级数据结构和简单而有效的面向对象编程方法.Python优雅的语法和动态类型以及其解释性的性质,使它在许多领域和大多数平台成为编写脚本和快速 ... 
- 使用IntelliJ IDEA 13搭建Android集成开发环境(图文教程)
		[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ... 
- 【转】windows和linux中搭建python集成开发环境IDE
		本系列分为两篇: 1.[转]windows和linux中搭建python集成开发环境IDE 2.[转]linux和windows下安装python集成开发环境及其python包 3.windows和l ... 
- 【转】linux和windows下安装python集成开发环境及其python包
		本系列分为两篇: 1.[转]windows和linux中搭建python集成开发环境IDE 2.[转]linux和windows下安装python集成开发环境及其python包 3.windows和l ... 
- Windows下的Objective-C集成开发环境(IDE)(转)
		Objective-C是苹果软件的编程语言,想要上机学习.调试,有一个集成开发环境(IDE)方便很多.有三类方法搭建Objective-C的集成开发环境: 1) 使用苹果的平台,集成开发环境使用X ... 
- Linux搭建Scrapy爬虫集成开发环境
		安装Python 下载地址:http://www.python.org/, Python 有 Python 2 和 Python 3 两个版本, 语法有些区别,ubuntu上自带了python2.7. ... 
随机推荐
- JSON数据转换成table表格
			<%@ page contentType="text/html; charset=UTF-8" %> <%@taglib uri="/struts-ta ... 
- [Android 源码]  Android源码下载
			Android源码下载 为了能够顺利的下载Android的源码,同时也为了避免在网络上再次搜寻如何下载源码的麻烦,我把下载过程记录在这篇文档中. 官网中也有详细的介绍: http://source.a ... 
- OpenShift DNS的机制
			为什么不直接用kube-dns? 为什么不直接用kube-dns? 为什么不直接用kube-dns? 感谢各位前辈的专研,在下午有限的时间里把Openshift DNS的机制理了一下.更详细的材料大家 ... 
- 【转载】惠新宸:PHP在百度的应用现状及展望
			http://blog.sina.com.cn/s/blog_645f8e970100qvd8.html 惠新宸,百度PHP高级顾问,年二十有八,好追根究底,有不良嗜好, 幸性本善.乙酉年识互联网,丁 ... 
- SPSS19.0实战之多元线性回归
			线性回归数据来自于国泰安数据服务中心的经济研究数据库.网址:http://www.gtarsc.com/p/sq/.数据名称为:全国各地区能源消耗量与产量,该数据的年度标识为2006年,地区包括我国3 ... 
- Servlet学习笔记(一):生命周期
			一.Servlet 生命周期: Servlet 生命周期可被定义为从创建直到毁灭的整个过程.以下是 Servlet 遵循的过程:初始化——响应请求——终止——回收 Servlet 通过调用 init ... 
- Java项目在jsp页面中引入jquery框架的步骤
			环境:在Java web项目中引入juqery框架 工具:MyEclipse8.5 [步骤如下] A:新建一个Java web项目TestJquery,在WebRoot目录下创建一个jquery文件 ... 
- 【Python】安装Python的mysql模块
			在控制台中输入pip install pymysql即可,以下是输出: C:\Users\horn1\Desktop\python\15>pip install pymysql Collecti ... 
- Mac怎样改动开机password
			Mac开机password忘了,咋办?开不开机啦 1.打开你的Mac,command +S 进入你的终端界面 2.输入/sbin/mount -uaw / 3.输入rm /var/db/.AppleS ... 
- Python 创建特殊元组tuple
			创建1个元素的tuple (1,) 创建单元素tupletuple和list一样,可以包含 0 个.1个和任意多个元素.包含多个元素的 tuple,前面我们已经创建过了.包含 0 个元素的 tupl ... 
