RMI不支持远程注册(绑定)

两台机器:

1.Linux(192.168.80.129)

2.Windows(192.168.80.1)

Linux作为服务注册机,Windows作为服务提供者。

服务接口:

package com.zzj.jndi.service;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface JndiService extends Remote {
	
	public int getNext() throws RemoteException;
}

接口实现类:

package com.zzj.jndi.service.impl;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import com.zzj.jndi.service.JndiService;

/**
 * Unicast:单播(点到点)
 * @author lenovo
 *
 */
public class JndiServiceImpl extends UnicastRemoteObject implements JndiService {
	private static final long serialVersionUID = 1L;
	
	private int next;
	
	public JndiServiceImpl() throws RemoteException {
		super();
	}

	/**
	 * 非线程安全的
	 */
	public int getNext() throws RemoteException {
		return ++next;
	}
}

服务注册类:

package com.zzj.jndi.registry;

import java.rmi.registry.LocateRegistry;

public class RMIRegistry {
	
	public static void main(String[] args) throws Exception {
		/* 必须将java.rmi.server.hostname设置为服务器对外公布的IP,
		 * 否则客户端会去找127.0.0.1
		 */
		System.setProperty("java.rmi.server.hostname", "192.168.80.129");
		System.setProperty("java.security.policy", "/root/Desktop/rmi.policy");
		
		if (System.getSecurityManager() == null) {
			System.setSecurityManager(new SecurityManager());
		}
		
		//注册RMI服务器端口
        LocateRegistry.createRegistry(8080);
        System.out.println("注册服务已启动...");
        System.in.read(); // press any key to exit
        System.out.println("exit!");
	}
}

服务提供者:

package com.zzj.jndi.provider;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import com.zzj.jndi.service.JndiService;
import com.zzj.jndi.service.impl.JndiServiceImpl;

public class RmiServiceProvider3 {
	
	public static void main(String[] args) throws Exception {
		System.setProperty("java.security.policy", "E:\\eclipsejee\\javase\\src\\rmi.policy");
		if(System.getSecurityManager() == null){
            System.setSecurityManager(new SecurityManager());
        }
		
		Registry registry = LocateRegistry.getRegistry("192.168.80.129", 8080);
		JndiService jndiService = new JndiServiceImpl();
		registry.bind("jndiService", jndiService);
		
		System.out.println("Jndi服务已绑定...");
	}

}

安全策略文件rmi.policy:

grant {
    permission java.security.AllPermission;
};
将服务注册类RMIRegistry和服务接口类JndiService打成Jar包RMIRegistry.jar,放到Linux上,启动服务注册类:
java -cp RMIRegistry.jar com.zzj.jndi.registry.RMIRegistry
在Windows上启动提供者,抛出以下错误:
Exception in thread "main" java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
	java.rmi.AccessException: Registry.Registry.bind disallowed; origin /192.168.80.1 is non-local host
	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:459)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:293)
	at sun.rmi.transport.Transport$2.run(Transport.java:202)
	at sun.rmi.transport.Transport$2.run(Transport.java:199)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:198)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:567)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.access$400(TCPTransport.java:619)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:684)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:681)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:681)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)
	at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:275)
	at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:252)
	at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:378)
	at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source)
	at com.zzj.jndi.provider.RmiServiceProvider3.main(RmiServiceProvider3.java:19)
Caused by: java.rmi.AccessException: Registry.Registry.bind disallowed; origin /192.168.80.1 is non-local host
	at sun.rmi.registry.RegistryImpl.checkAccess(RegistryImpl.java:306)
	at sun.rmi.registry.RegistryImpl.bind(RegistryImpl.java:198)
	at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:449)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:293)
	at sun.rmi.transport.Transport$2.run(Transport.java:202)
	at sun.rmi.transport.Transport$2.run(Transport.java:199)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:198)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:567)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:828)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.access$400(TCPTransport.java:619)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:684)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$1.run(TCPTransport.java:681)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:681)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

异常是由registry.bind方法抛出来的,查看Java api:

RemoteException - if remote communication with the registry failed; if exception
        is a ServerException containing an AccessException, then the registry denies the 
        caller access to perform this operation (if originating from a non-local host, for example)

由于RMI不支持远程绑定,导致服务注册与服务提供者高度耦合,所以无法实现高可用。要让RMI实现高可用,必须借助像zookeeper这样的分布式协调系统。




  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值