HSF服务的开发与使用

一、背景

      随着网站访问量增加,仅仅靠增加机器已不能满足系统的要求,于是需要对应用系统进行垂直拆分和水平拆分。在拆分之后,各个被拆分的模块如何通信?如何保证性能?如何保证各个应用都以同样的方式交互?这就需要一种负责各个拆分的模块间通信的高性能服务框架(HSF  

HSF全称为High-Speed Service Framework)。

二、HSF做的事情

 

1. 标准Service方式的RPC

    1). service定义:基于OSGI的service定义方式

    2). TCP/IP通信:

           IO方式:nio,采用mina框架

           连接方式:长连接

           服务器端有限定大小的连接池

           WebService方式

    3). 序列化:hessian序列化机制

2. 软件负载体系

    采用软件实现负载均衡,支持随机、轮询、权重、按应用路由等方式。软件负载均衡没有中间点,通过配置中心统一管理。配置中心收集服务提供者和消费者的注册信息,以推送的方式发送到服务消费者直接使用,不经过中间点;注册中心可以感应服务器的状态,出现failover时,实现注册信息重新推送。

3. 模块化、动态化

4. 服务治理

    服务治理利用注册中心实现服务信息管理(服务提供者、调用者信息查询)、服务依赖关系分析、服务运行状况感知、服务可用性保障,如:路由调整、流量分配、服务端降级、调用端降级等

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/marine2010/archive/2010/03/21/5401366.aspx

二:服务的开发

1.HSF服务的开发

1) 基于Maven创建一个web工程HSFService,如下图,其他的可以自定义。

2)创建好好在src/main目录下创建一个java目录,并将其设置为sources folder,如下图所示:

3) 配置项目的pom.xml,如下

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.hsf</groupId>
  <artifactId>HSFService</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>HSFService Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <properties>
    <java-version>1.7.0_67</java-version>
  </properties>
  <dependencies>
    <!-- Junit依赖包-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <!--spring和servlet的依赖包-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring</artifactId>
      <version>2.5.6</version>
      <type>jar</type>
      <scope>compile</scope>
    </dependency>
    <!-- mysql依赖包-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
    </dependency>
    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.2.2</version>
    </dependency>
    <!-- Ibatits依赖包-->
    <dependency>
      <groupId>org.apache.servicemix.bundles</groupId>
      <artifactId>org.apache.servicemix.bundles.ibatis-sqlmap</artifactId>
      <version>2.3.4.726_4</version>
    </dependency>
    <!-- 淘宝HSF服务的依赖包-->
    <dependency>
      <groupId>com.taobao.hsf</groupId>
      <artifactId>hsf.app.spring</artifactId>
      <version>1.4.9.2</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>HSFService</finalName>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>${java-version}</source>
          <target>${java-version}</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

4) 编写服务接口和服务的实现

代码如下:

package com.hsf.services;
import java.lang.String;
public interface SayHelloService{
    public String sayHello(String user);
}
package com.hsf.services.impl;
import com.hsf.services.SayHelloService;
public class SayHelloServiceImpl implements SayHelloService {
      public String sayHello(String user) {
        return "Hello "+user+" ,Time is "+System.currentTimeMillis()+"(ms)";
      }
    }

5) 在Spring的配置文件中配置HSFSpringProviderBean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns="http://www.springframework.org/schema/beans"       xsi:schemaLocation="            http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-3.1.xsd                ">
    <!-- HSF服务配置-->
    <!--配置SayHelloService服务的实现 -->
    <bean id="SayHelloServiceImpl" class="com.hsf.services.impl.SayHelloServiceImpl"/>
    <!--配置SayHelloService服务提供者-->
    <bean id="SayHelloService" class="com.taobao.hsf.app.spring.util.HSFSpringProviderBean" init-method="init">
        <!--配置服务提供者对外提供的接口SayHelloService-->
        <property name="serviceInterface">
            <value>com.hsf.services.SayHelloService</value>
        </property>
        <!--服务的实现者-->
        <property name="target">
            <ref bean="SayHelloServiceImpl"/>
        </property>
        <property name="serviceVersion">
            <value>1.0.0.0.dev</value>
        </property>
        <!-- 组别一致的服务才能互相调用-->
        <property name="serviceGroup">
            <value>HSF</value>
        </property>
        <property name="serviceName">
            <value>SayHello</value>
        </property>
    </bean>
    <!--配置SayHelloService服务的消费者-->
    <bean id="SayHelloServiceConsumer" class="com.taobao.hsf.app.spring.util.HSFSpringConsumerBean" init-method="init">
     <!--服务的接口名和版本号须与服务提供者定义的一致-->
        <property name="interfaceName">
            <value>com.hsf.services.SayHelloService</value>
        </property>
        <property name="version">
            <value>1.0.0.0.dev</value>
        </property>
    </bean>
</beans>

6) 在Web.xml中配置spring的上下文环境

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xmlns="http://java.sun.com/xml/ns/javaee"         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"         id="WebApp_ID" version="3.0">
  <display-name>HSFService</display-name>
 <!-- 默认显示界面 -->
  <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
      <welcome-file>index.html</welcome-file>
  </welcome-file-list>
   <!-- 配置spring上下文环境applicationContext -->
   <context-param>
       <param-name>contextConfigLocation</param-name>
       <!-- 应用上下文配置文件 -->
       <param-value>classpath*:applicationContext.xml</param-value>
   </context-param>
    <!--配置spring启动listener入口 -->
    <listener>        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>
 

 

7) 将HSFService部署,启动tomcat,即可在HSF服务治理中心http://ops.jm.taobao.net/hsfops中根据自己主机的IP查找自己发布的服务

 

8) 将服务接口SayHelloService打成Jar包(二方包)以供客户端使用

2.HSF服务的使用

1) 在客户端的pom.xml文件中添加对HSF的依赖

1 <dependency>
2   <groupId>com.taobao.hsf</groupId>
3   <artifactId>hsf.app.spring</artifactId>
4   <version>1.4.9.2</version>
5 </dependency>

2) 在客户端的Spring配置文件中配置HSFSpringConsumerBean

<!--配置SayHelloService服务的消费者-->
<bean id="SayHelloServiceConsumer" class="com.taobao.hsf.app.spring.util.HSFSpringConsumerBean" init-method="init">
    <!--服务的接口名和版本号须与服务提供者定义的一致-->
    <property name="interfaceName">
        <value>com.hsf.services.SayHelloService</value>
    </property>
    <property name="version">
        <value>1.0.0.0.dev</value>
    </property>
</bean>

 

3)引入服务端打好的二方Jar包com.hsf.services.jar,创建SayHelloServlet使用服务

SayHelloServlet的代码如下:

package com.hsf.consumer;
import com.hsf.services.SayHelloService;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class SayHelloServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //通过ServletContext获取Spring的上下文
        WebApplicationContext context= WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        //通过BeanFactory获取服务的消费者SayHelloServiceConsumer
        SayHelloService sayHelloService= (SayHelloService) context.getBean("SayHelloServiceConsumer");

        PrintWriter out=response.getWriter();
        //调用服务
        out.println(sayHelloService.sayHello("xiwu.xxw"));
        out.close();
        return;
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }
}

5)部署该web工程到tomcat,启动tomcat后访问http://localhost:8079/ SayHello?name=zhangsna 即可看到打印出“Hello zhangsan,Time is xxxxx (ms)

 

 

 

 

 

背景: WEBX -- 阿里巴巴网站所采用的WEB应用框架.

HSF接口: com.taobao.item.service.ItemQueryService

需求: 根据商品ID取得商品信息

载体: TBCMS系统

实现步骤: 1. 创建 /bundle/war/src/webroot/META-INF/autoconf/item-hsf-xml.vm

代码:
<?xml version="1.0" encoding="GB2312"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
  <bean id="itemQueryService" class="com.taobao.hsf.app.spring.util.HSFSpringConsumerBean" init-method="init">
   <property name="interfaceName">
    <value>com.taobao.item.service.ItemQueryService</value>
   </property>
   <property name="version">
    <value>${item_provide_service_version}</value>
   </property>
   <!--asyncallMethods为可选配置[List],含义为调用此服务时需要采用异步调用的方法名列表,默认为空集合,即所有方法都采用同步调用-->
   <property name="asyncallMethods">
    <list>
</list>
</property>
</bean>

</beans>  

2.其中: ${item_provide_service_version} 需要在 auto-config.xml 中配置,在 <group name="arkcms-bundle-war"> ...</group>中增加:

<property name="item.provide.service.version" defaultValue="1.0.0.daily" desc="itemClient调用版本"/>

同时在 <script>...</script>中增加:

<generate template="item-hsf.xml.vm" destfile="WEB-INF/biz/bean/item-hsf.xml" charset="GBK"/>

3.在 /bundle/war/src/webroot/WEB-INF/cms-biz-services.xml中增加:

        <service name="BeanFactoryService" class="com.alibaba.service.spring.DefaultBeanFactoryService">
            <property name="bean.descriptors">

                     ....................

                    <value>/cms/biz/bean/item-hsf.xml</value>
            </property>
        </service>

至此,我们已经引入了ItemQueryService的HSF服务.

4. 接下来我们就要做Servlet接口了,当然写一个servlet直接调用hsf也是可以的,但是从结构考虑,我们还是先本地封装一层先.

但是首先,需要对 /all/project.xml 中需要增加对ItemQueryService的支持:

    <projects name="taobao/itemcenter" version="1.9.5">
     <project id="taobao/itemcenter/itemcenter-client"/>
     <project id="taobao/itemcenter/itemcenter-common"/>
    </projects>

并在/biz/project.xml和/web/project.xml中增加:

<?xml version="1.0" encoding="GB2312"?>

<project id="tbcms/web" extends="../all/project.xml">
    <build>
        <dependencies>
                  ............
        <include uri="taobao/itemcenter/itemcenter-client"/>
        <include uri="taobao/itemcenter/itemcenter-common"/>
        </dependencies>
    </build>
</project>

命令行模式下执行:antx reactor goals=eclipse来执行对依赖包的装载.(前提是对/antx/repository.project/taobao/itemcenter/进行SVN更新)

本地封装: 在/biz/src/java/com/ark/cms/biz/util/item/下创建ItemService.java接口:

package com.ark.cms.biz.util.item;

import com.taobao.item.domain.DbRoute;
import com.taobao.item.domain.query.ItemIdDO;
import com.taobao.item.domain.result.ItemResultDO;
import com.taobao.item.exception.IcException;
/**
 * 根据id取得商品信息
 * @author duxing
 *
 */
public interface ItemService {
 public ItemResultDO getItemById(ItemIdDO itemId,DbRoute mainDbRoute) throws IcException;
}
 

在biz/src/java/com/ark/cms/biz/util/item/impl/下 ItemServiceImpl.java进行实现:

package com.ark.cms.biz.util.item.impl;

import com.ark.cms.biz.util.item.ItemService;
import com.taobao.item.domain.DbRoute;
import com.taobao.item.domain.query.ItemIdDO;
import com.taobao.item.domain.query.QueryItemOptionsDO;
import com.taobao.item.domain.result.ItemResultDO;
import com.taobao.item.exception.IcException;
import com.taobao.item.service.ItemQueryService;

/**
 * 根据id取得商品信息 实现
 * @author duxing
 *
 */

public class ItemServiceImpl implements ItemService {

 private ItemQueryService itemQueryService;

 public void setItemQueryService(ItemQueryService itemQueryService) {
  this.itemQueryService = itemQueryService;
 }

 @SuppressWarnings("deprecation")
 public ItemResultDO getItemById(ItemIdDO itemId, DbRoute mainDbRoute) throws IcException {
  QueryItemOptionsDO options = null;
  return itemQueryService.queryItemById(itemId, options, mainDbRoute);
 }

}
然后将此接口移交给spring,在 /bundle/war/src/webroot/META-INF/autoconf/item-hsf-xml.vm中增加 

<bean id="itemService" class="com.ark.cms.biz.util.item.impl.ItemServiceImpl"></bean>

至此,我们已经在spring中产生一个itemService

5.接下来创建servlet

在/web/src/java/com/ark/cms/web/下创建ItemServiceServlet.java

因为servlet中不能直接用set形式让spring来set itemService进来,所以只能采用一下方法获取itemService:

  BeanFactoryService beanFactory = (BeanFactoryService) BizServiceManager.getInstance().getService(BeanFactoryService.SERVICE_NAME);
  ItemService itemService = (ItemService) beanFactory.getBean("itemService");

完整代码如下:

package com.ark.cms.web;

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.service.spring.BeanFactoryService;
import com.ark.cms.biz.core.BizServiceManager;
import com.ark.cms.biz.util.item.ItemService;
import com.taobao.item.domain.DbRoute;
import com.taobao.item.domain.ItemDO;
import com.taobao.item.domain.query.ItemIdDO;
import com.taobao.item.domain.result.ItemResultDO;
import com.taobao.item.exception.IcException;


/**
 * 根据id取得商品大图的接口
 * @author duxing
 *
 */
public class ItemServiceServlet extends HttpServlet {

 private static final long serialVersionUID = -3348559907279438489L;

 @Override
 protected void doPost(HttpServletRequest request,
   HttpServletResponse response) throws ServletException, IOException {
// http://item.taobao.com/auction/item_detail-db1-67af640ba3f16a2006cd63f1f...
// long itemId=4399800173l;

  String item_id = request.getParameter("item_id");

  String xid = request.getParameter("xid");
  DbRoute mainDbRoute=DbRoute.getDbRouteByXid(xid);

  ItemIdDO itemIDDO=new ItemIdDO();
  if(item_id!=null){
   itemIDDO.setItemIdStr(item_id);
  }
  if(request.getParameter("item_num_id")!=null){
   Long item_num_id = Long.valueOf(request.getParameter("item_num_id"));
   itemIDDO.setItemId(item_num_id);
  }
  if(request.getParameter("id")!=null){
   Long id = Long.valueOf(request.getParameter("id"));
   itemIDDO.setItemId(id);
  }
// 两种id的传入方式
// itemIDDO.setItemId(itemId);
// itemIDDO.setItemIdStr("67af640ba3f16a2006cd63f1f5dddc271");

  ItemResultDO itemResultDO;
  BeanFactoryService beanFactory = (BeanFactoryService) BizServiceManager.getInstance().getService(BeanFactoryService.SERVICE_NAME);
  ItemService itemService = (ItemService) beanFactory.getBean("itemService");
  try {
   itemResultDO=itemService.getItemById(itemIDDO, mainDbRoute);
  } catch (IcException e) {
   e.printStackTrace();
   itemResultDO=new ItemResultDO();
  }

  ItemDO itemDO=itemResultDO.getItem();
  byte[] result="".getBytes();
  if(itemDO!=null){
   result=itemDO.getPictUrl().getBytes();
  }
  response.setContentType("text/xml;charset=gb2312");
  response.setContentLength(result.length);
  OutputStream out = response.getOutputStream();
  out.write(result);
  out.flush();

 }
}
6.servlet写好了之后我们就要配置进WEBX了:

在 /bundle/war/src/webroot/META-INF/autoconf/web.xml.vm中增加:

      <servlet-mapping>

        <servlet-name>ItemServiceServlet</servlet-name>
        <url-pattern>/item/query</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>ItemServiceServlet</servlet-name>
        <servlet-class>com.ark.cms.web.ItemServiceServlet</servlet-class>
    </servlet>

7.至此,开发完成 

命令行模式下执行:antx reactor goals=clean,default来对项目重新编译打包.重启本地服务器进行测试.

对/item/query接口进行post的时候触发此servlet.

 

 

 

 

转载于:https://my.oschina.net/fivewang/blog/700349

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值