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. ...
随机推荐
- 虚拟机网络配置详解(NAT、桥接、Hostonly) z
http://www.cnblogs.com/beginmind/p/6379881.html VirtualBox中有四种网络连接方式: NAT Bridged Adapter Internal H ...
- appium+python自动化57-chromedriver与chrome版本
前言 由于app的webview自动化是依赖于chromedriver的,并且每个app的webview版本号都不太一样,这就导致了,每次都需要重新去下载对应的chromedriver版本.如何根据当 ...
- 推荐两份学习 Kotlin 和机器学习的资料
最近 Kotlin 和人工智能比较火,有不少同学留言问我怎么学习 Kotlin,怎么学习机器学习,今天就给大家推荐两份不错的学习资料. 1. Kotlin 学习资料其实,在我看来最好的学习资料就是 K ...
- Latex中为作者添加多个单位属性(IEEE模板)
\author{ \IEEEauthorblockN{name1 name1\IEEEauthorrefmark{1}\IEEEauthorrefmark{2}, name2 name2\IEEEa ...
- OpenCV学习(14) 细化算法(2)
前面一篇教程中,我们实现了Zhang的快速并行细化算法,从算法原理上,我们可以知道,算法是基于像素8邻域的形状来决定是否删除当前像素.还有很多与此算法相似的细化算法,只是判断的条件不一样. ...
- PowerDesigner教程系列(三)概念数据模型
目标: 本文主要介绍属性的标准检查约束.如何定义属性的附加检查. 一.定义属性的标准检查约束 标准检查约束是一组确保属性有效的表达式.在实体属性的特性窗口,打开如图所示的检查选项卡. 在这个选项卡可以 ...
- 安装Office2007时出现1706错误的解决方案
前几天,重做了系统.周末因为接到一笔单子,很兴奋啊.第一次接到私活.然后就装Office2007,打算看需求的.居然安装的时候出现错误,提示1706错误,后面一串错误信息,也懒得看,以为是文件坏了. ...
- 【云计算】jenkins,docker,mesos,marathon,k8s相关资料
参考资料: 基于Apache Mesos 构建高可靠,高可用的Jenkins CI:http://blog.csdn.net/ebay/article/details/43529401 Docker ...
- 实现一个类似Chrome新功能提示的popoup
先让我们看一下Chrome的popup是什么样的: 这个“直接搜索网页”与“在打开的标签页之间切换”就是两个功能导航,还做了一个动画效果,会不停的上下晃. 我通过WindowManager的addVi ...
- 【树莓派】-bash: /usr/local/java/jdk1.8.0_161/bin/java: cannot execute binary file: Exec format error
遇到这样的问题:-bash: /usr/local/java/jdk1.8.0_161/bin/java: cannot execute binary file: Exec format error ...