程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 基於netty輕量的高性能分布式RPC服務框架forest<下篇>,nettyforest

基於netty輕量的高性能分布式RPC服務框架forest<下篇>,nettyforest

編輯:JAVA綜合教程

基於netty輕量的高性能分布式RPC服務框架forest<下篇>,nettyforest


基於netty輕量的高性能分布式RPC服務框架forest<上篇>

文章已經簡單介紹了forest的快速入門,本文旨在介紹forest用戶指南。

基本介紹

Forest是一套基於java開發的RPC框架,除了常規的點對點調用外,Motan還提供服務治理功能,包括服務節點的自動發現、摘除、高可用和負載均衡等。

架構概述

Forest中分為服務提供方(RPC Server),服務調用方(RPC Client)和服務注冊中心(Registry)三個角色。

Server提供服務,向Registry注冊自身服務,並向注冊中心定期發送心跳匯報狀態; Client使用服務,需要向注冊中心訂閱RPC服務,Client根據Registry返回的服務列表,與具體的Sever建立連接,並進行RPC調用。 當Server發生變更時,Registry會同步變更,Client感知後會對本地的服務列表作相應調整。 三者的交互關系如下圖:

 

模塊概述

forest代碼層面包含三個module

forest-common:一些基礎的功用的功能

forest-rpc:和rpc相關的核心功能實現,

forest-demo:一些forest示例的推薦示例

 

forest從設計的分層包含以下基層,分層設計圖如下:

配置概述

Forest體功能了靈活的功能,可以基於注解來配置,也可以通過spring xml來覆蓋這些配置,當然你可以可以代碼裡面自己構造。

配置優先級如下:注解默認配置<spring xml配置(或者代碼構造)

基於注解配置

1.interface api的配置

a. inteface api類上可以通過@ServiceProvider注解來提供服務,@ServiceProvider用於接口類上,可以配置參數如下:

public @interface ServiceProvider {
    String serviceName() default "";//服務名稱,隔離級別是以一個服務為粒度
    HaStrategyType haStrategyType() default HaStrategyType.FAIL_FAST;
    LoadBalanceType loadBalanceType() default LoadBalanceType.RANDOM;
    String hashKey() default "";// 僅當使用hash策略時候使用
    int connectionTimeout() default Constants.CONNECTION_TIMEOUT;
}

  

接口層提供給調用方,調用方的client可以繼承interface上的@ServiceProvider配置作為默認配置。

b. interface method可以通過@MethodProvider注解來提供具體的業務服務,參數配置如下:

public @interface MethodProvider {
    String methodName() default "";
    SerializeType serializeType() default SerializeType.Kyro;
    CompressType compressType() default CompressType.None;
    int timeout() default Constants.DEFAULT_TIMEOUT; // 客戶端超時時間
}

  

你可以針對不同的業務方法指定不同的序列化方式或者 壓縮方式。

2.server端interface impl的配置

a. servcieImpl可以通過@ServiceExport注解來發布服務,interface impl只有加上了@ServiceExport才會發布服務。 如果不指定port,則使用默認的port,如需和其他業務隔離,建議使用不同的port來發布。

public @interface ServiceExport {
    int port() default Constants.DEF_PORT;
}

  

當然你也可以加上@Path來暴露restful的path,Forest支持基於jersey的restful服務。

b. servcieImpl可以通過@MethodExport注解來發布方法

serviceImpl的方法上面同時可以支持其他的注解,類似如下:

 /**
     * 支持jersey,可以通過配置打開,同時啟動http服務
     *
     * @param str
     * @return
     */
    @Path("/hello/{str}")
    @GET
    @Produces("text/plain")

    @MethodExport
    @Rate(2)
    @Override
    public String say(@PathParam("str") String str) {
        return "say " + str;
    }

  

基於spring xml配置

對於客戶端,是沒有辦法控制提供方提供接口層的注解配置,如果客戶端想自定義配置,可以選擇基於spring xml的配置來覆蓋服務提供方推薦的默認配置。

示例如下:

  <bean id="methodConfig" class="com.zhizus.forest.common.config.MethodConfig">
        <property name="compressType">
            <util:constant static-field="com.zhizus.forest.common.CompressType.None"/>
        </property>
        <property name="serializeType">
            <util:constant static-field="com.zhizus.forest.common.SerializeType.Fastjson"/>
        </property>
        <property name="timeout" value="5000"/>
    </bean>

    <bean id="sampleServiceProxy" class="com.zhizus.forest.support.spring.ForestProxyFactoryBean">
        <property name="serviceInterface" value="com.zhizus.forest.demo.api.SampleService"/>
        <!--methodConfMap如果不配置,則使用接口方法注解上面的配置-->
        <property name="methodConfigMap">
            <map>
                <entry key="echo" value-ref="methodConfig"/>
                <entry key="say" value-ref="methodConfig"/>
            </map>
        </property>
    </bean>

  

有的時候覺得xml配置很麻煩,但是又不想使用服務提供方注解上面的默認配置,那麼我們可以可以使用代碼自己實例化, 示例如下:

SampleService sampleService = Forest.from(SampleService.class, ServiceProviderConfig.Builder.newBuilder()
                .withMethodConfig("say", MethodConfig.Builder.newBuilder()
                        .withCompressType(CompressType.None)
                        .withSerializeType(SerializeType.Fastjson)
                        .build())
                .withMethodConfig("echo", MethodConfig.Builder.newBuilder()
                        .withCompressType(CompressType.None)
                        .withSerializeType(SerializeType.Hession2)
                        .build())
                .build());

  

常用功能介紹

壓縮方式&序列化方式

Forest在協議層面支持多種壓縮方式&多種序列化方式,也就是說,你可以指定某一個請求的壓縮方式和序列化的方式。壓縮方式和序列化方式的粒度都是每個請求的。

  • 目前支持的壓縮方式:1.gzip 2.snappy
  • 目前支持的序列化方式:1.hession2, 2.fastjson, 3.kyro

負載均衡

RANDOM, ROBBIN, HASH

容錯

 FAIL_FAST,
 FAIL_OVER,

客戶端的隔離

Forest支持定制策略,(在一個時間段出現一定次數的錯誤,則自動將服務隔離開來,一段時間後恢復)

內置連接池

Forest采用common-pool2連接池來管理連接,每個客戶端的proxy對應一個或者多個pool,不需要額外的創建連接池來提供吞吐。

第三方服務的支持

Forest基於hystrix使用示例

hystrix是一個非常優秀的服務容錯組件,這裡也非常推薦能使用hystrix對forest提供的服務做一層包裝來加強服務的容錯降級能力。

服務端支持連接器&限流

Forest可以自定義攔截器,同時也可以自定義限流。只需要在發布的方法上面加上對應的注解。

@Component
public class SampleServiceCommand {

    @Resource(name = "sampleServiceProxy")
    SampleService remoteServiceRef;

    @HystrixCommand(groupKey = "ExampleGroup", commandKey = "HelloWorld", threadPoolKey = "HelloWorldPool", fallbackMethod = "sayFallback")
    public String say(String str) {
        String say = remoteServiceRef.say(str);
        System.out.println("say:" + say);
        str.toString();
        return say;
    }

    public String sayFallback(String str) {
        return "sayFallBack:" + str;
    }
}

  

xml 配置如下:

 <context:component-scan base-package="com.zhizus.forest.demo.client"/>

    <!--添加hystrix aop-->
    <aop:aspectj-autoproxy/>
    <bean id="hystrixAspect" class="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"></bean>

    <bean id="methodConfig" class="com.zhizus.forest.common.config.MethodConfig">
        <property name="compressType">
            <util:constant static-field="com.zhizus.forest.common.CompressType.None"/>
        </property>
        <property name="serializeType">
            <util:constant static-field="com.zhizus.forest.common.SerializeType.Fastjson"/>
        </property>
        <property name="timeout" value="5000"/>
    </bean>

    <bean id="zkRegistry" class="com.zhizus.forest.common.registry.impl.ZkServiceDiscovery">
        <property name="connStr" value="localhost:2181"/>
    </bean>

    <bean id="sampleServiceProxy" class="com.zhizus.forest.support.spring.ForestProxyFactoryBean">
        <property name="serviceInterface" value="com.zhizus.forest.demo.api.SampleService"/>
        <!--注冊本地-->
        <property name="discovery" ref="zkRegistry"/>
        <!--methodConfMap如果不配置,則使用接口方法注解上面的配置-->
        <property name="methodConfigMap">
            <map>
                <entry key="echo" value-ref="methodConfig"/>
                <entry key="say" value-ref="methodConfig"/>
            </map>
        </property>
    </bean>

  

對jersey的支持

有時候,我們需要同時暴露http服務供第三方服務調用或者測試。針對這些情況,Forest支持基於jersey的restful服務。

http服務打開的開關:server.properties

http.server.start=true

  

其他的參數配置,詳見:com.zhizus.forest.common.config.ServerConfig 之後,我們可以無阻礙的使用基於jersey的restful服務了。

性能測試

對Forest進行了簡單的壓測,發現在hession2的序列化方式下,win64 8g內存可以達到8w+的tps。 其他的情況也均在3w+的tps。

當然Forest應該還有一些性能優化空間,到目前為止,還沒有對其進行一些性能優化。

client代碼:

 public static void benchmarkTest() throws Exception {
        final SampleService sampleService = Forest.from(SampleService.class);
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 20; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 1000000000; i++) {
                        String say = sampleService.echo("hello");
                        if (i % 10000 == 0) {
                            System.out.println(say);
                        }
                    }
                }
            });
        }
    }

  

服務端加上系統自帶的metric攔截器:

 @Interceptor("metricInterceptor")
    @MethodExport
    @Override
    public String echo(String msg) {
        return "echo>>> " + msg;
    }

  

console日志:

23:10:10.295 [pool-1-thread-1] INFO MetricInterceptor 34 - methodName:/sampleService/say, current tps:83342, avgTime:0, maxTime:63, minTime:0
23:10:11.298 [pool-1-thread-1] INFO MetricInterceptor 34 - methodName:/sampleService/say, current tps:86271, avgTime:0, maxTime:63, minTime:0
23:10:12.295 [pool-1-thread-1] INFO MetricInterceptor 34 - methodName:/sampleService/say, current tps:86063, avgTime:0, maxTime:63, minTime:0

源代碼地址:forest

歡迎各路大俠參與。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved