SOFA RPC 服务发布过程

在 SOFARPC 框架中,启动服务器的过程涉及多个步骤,包括服务器配置、初始化、启动服务器以及注册服务等。下面将结合提供的代码片段详细介绍启动服务器的过程。

1. 服务器配置

在启动服务器之前,需要对服务器进行配置,包括设置协议、端口、是否为守护线程等。以下是一个配置示例:

ServerConfig serverConfig = new ServerConfig()
    .setProtocol("bolt") // 设置协议,默认bolt
    .setPort(12200) // 设置端口,默认12200
    .setDaemon(false); // 非守护线程

在上述代码中,创建了一个ServerConfig对象,并设置了服务器的协议为bolt,端口为12200,且不是守护线程。

2. 服务提供者配置

除了服务器配置,还需要配置服务提供者,包括指定接口、实现、服务器和应用信息等。以下是一个服务提供者配置示例:

ApplicationConfig applicationConfig = new ApplicationConfig().setAppName("serverApp");

ProviderConfig<HelloService> providerConfig = new ProviderConfig<HelloService>()
    .setInterfaceId(HelloService.class.getName()) // 指定接口
    .setRef(new HelloServiceImpl()) // 指定实现
    .setServer(serverConfig) // 指定服务端
    .setApplication(applicationConfig) // 指定应用配置
    .setRegister(true); // 是否注册到注册中心

在上述代码中,创建了一个ApplicationConfig对象,并设置了应用的名称为serverApp。然后创建了一个ProviderConfig对象,指定了服务的接口为HelloService,实现为HelloServiceImpl,服务器为之前配置的serverConfig,应用配置为applicationConfig,并设置是否注册到注册中心。

3. 初始化服务器

在启动服务器之前,需要对服务器进行初始化。不同的服务器实现类有不同的初始化方式,以下是BoltServer的初始化示例:

@Extension("bolt")
public class BoltServer implements Server {
    @Override
    public void init(ServerConfig serverConfig) {
        this.serverConfig = serverConfig;
        bizExecutor = initExecutor(serverConfig);
        if (bizExecutor instanceof ThreadPoolExecutor) {
            bizThreadPool = (ThreadPoolExecutor) bizExecutor;
        }
        boltServerProcessor = new BoltServerProcessor(this);
    }

    protected Executor initExecutor(ServerConfig serverConfig) {
        Executor executor = BusinessPool.initExecutor(
            ThreadPoolConstant.BIZ_THREAD_NAME_PREFIX + serverConfig.getPort(), serverConfig);
        if (executor instanceof ThreadPoolExecutor) {
            configureThreadPoolExecutor((ThreadPoolExecutor) executor, serverConfig);
        }
        return executor;
    }

    protected void configureThreadPoolExecutor(ThreadPoolExecutor executor, ServerConfig serverConfig) {
        executor.setRejectedExecutionHandler(new SofaRejectedExecutionHandler());
        if (serverConfig.isPreStartCore()) { // 初始化核心线程池
            executor.prestartAllCoreThreads();
        }
    }
}

在上述代码中,BoltServerinit方法接收一个ServerConfig对象,并进行了一系列的初始化操作

  1. 保存服务器配置信息。
  2. 初始化业务执行器(Executor)。
  3. 如果业务执行器是线程池执行器(ThreadPoolExecutor),则将其赋值给 bizThreadPool
  4. 创建 BoltServerProcessor 实例。

4. 启动服务器

在初始化服务器之后,可以调用start方法启动服务器。以下是BoltServer的启动示例:

@Override
public void start() {
    if (started) {
        return;
    }
  // synchronized 关键字对当前对象加锁,
    synchronized (this) {
        if (started) {
            return;
        }
        // 生成Server对象
        remotingServer = initRemotingServer();
        try {
          // 底层用到netty框架,绑定端口、启动 EventLoopGroup,负责处理网络事件,如连接建立、数据读写、注册处理器
            if (remotingServer.start()) {
                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info("Bolt server has been bind to {}:{}", serverConfig.getBoundHost(),
                        serverConfig.getPort());
                }
            } else {
                throw new SofaRpcRuntimeException(LogCodes.getLog(LogCodes.ERROR_START_BOLT_SERVER));
            }
            started = true;

            if (EventBus.isEnable(ServerStartedEvent.class)) {
                EventBus.post(new ServerStartedEvent(serverConfig, bizThreadPool));
            }

        } catch (SofaRpcRuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new SofaRpcRuntimeException(LogCodes.getLog(LogCodes.ERROR_START_BOLT_SERVER), e);
        }
    }
}

protected RemotingServer initRemotingServer() {
    // 该方法创建一个 RpcServer 实例,并将其绑定到 ServerConfig 中指定的主机和端口。
    RemotingServer remotingServer = new RpcServer(serverConfig.getBoundHost(), serverConfig.getPort());
    remotingServer.registerUserProcessor(boltServerProcessor);
    return remotingServer;
}

在上述代码中,BoltServerstart方法首先检查服务器是否已经启动,如果已经启动则直接返回。然后生成一个RemotingServer对象,remotingServer.start()BoltServer 启动过程中的核心步骤,负责启动底层的 RpcServer,使其开始监听客户端的请求。通过对启动结果的处理,确保服务器能够安全、可靠地启动,并及时通知其他组件服务器的启动状态并调用其start方法启动服务器。如果启动成功,则记录日志并发布ServerStartedEvent事件;如果启动失败,则抛出异常。

5. 注册服务

在服务器启动之后,需要将服务注册到服务器上。以下是BoltServer的服务注册示例:

@Override
public void registerProcessor(ProviderConfig providerConfig, Invoker instance) {
    // 缓存Invoker对象
    String key = ConfigUniqueNameGenerator.getUniqueName(providerConfig);
    invokerMap.put(key, instance);
    ReflectCache.registerServiceClassLoader(key, providerConfig.getProxyClass().getClassLoader());
    // 缓存接口的方法
    for (Method m : providerConfig.getProxyClass().getMethods()) {
        ReflectCache.putOverloadMethodCache(key, m);
    }
}

该方法的核心目的是在服务器端注册服务提供者的处理逻辑,让服务器知道如何处理客户端对特定服务的调用。具体来说,它完成以下几个主要任务:

  1. 缓存调用器对象:将服务提供者的调用器(Invoker)缓存起来,以便在接收到客户端请求时能够快速找到对应的处理逻辑。服务器在处理请求时确实会调用服务器的Invoker,这个过程后面文章在进行解析
  2. 解析服务方法:对服务接口的方法进行解析,缓存方法信息,确保服务器能够正确处理方法调用。
  3. 注册服务到服务器:将服务配置和调用器注册到服务器的处理逻辑中,使得服务器能够处理该服务的请求。

6. 发布服务

最后,调用ProviderConfigexport方法发布服务,该方法会调用上述的初始化、启动和注册服务的步骤。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值