从Ubuntu mount到Solaris 10的NFS遇到的问题
2010-04-21 16:52
357 查看
废话暂且不提,直接开始:
应用场景:
Mina + Spring 提供对外服务
需求:
在整个系统没有准备好之前,系统对外拒绝服务,因为本系统涉及到一些初始化索引一些比较耗费时间的问题,所以即使spring启动了,但是数据没有准备好,依然不能提供服务。
刚开始的时候,使用 spring的 init-method,但是经历各种蛋疼以后,发现可行性太低,所以我就想,能不能监听spring的事件来做呢,结果有了如下想法:
public class InitData implements ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware{
private ApplicationContext applicationContext;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
InitDataService service = applicationContext.getBean(InitDataService.class);
List<ISearchService> searchServices = service.getSearchServices();
int serviceAmount = searchServices.size();
final ExecutorService exec = Executors.newFixedThreadPool(serviceAmount);
final CountDownLatch downLatch = new CountDownLatch(serviceAmount + 1);
final CyclicBarrier barrier = new CyclicBarrier(serviceAmount, new ServiceReadyThread(downLatch));
for (ISearchService iSearchService : searchServices) {
Thread task = new Thread(new InitLuceneIndexThread(iSearchService, barrier, downLatch));
exec.execute(task);
}
try {
downLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}//等待所有的并发访问完
exec.shutdown();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
这个是整个想法的核心,下面围绕这个核心,我来做一些解释。
首先实现了ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware二个接口,一个是监听ContextRefreshedEvent事件,一个是拿到applicationContext。
InitDataService service = applicationContext.getBean(InitDataService.class);
单独写出来的一个类,因为我的service类有很多,那么如果我把这些类都放到配置文件中,以后只要实现各自的方法和更改配置文件就可以了。
ublic class InitDataService {
private List<ISearchService> searchServices;
public List<ISearchService> getSearchServices() {
return searchServices;
}
public void setSearchServices(List<ISearchService> searchServices) {
this.searchServices = searchServices;
}
}
<bean id="initDataService" class="com.playsnail.search.service.init.InitDataService">
<property name="searchServices">
<list>
<ref bean="各种实现了ISearchService的Service"/>
</list>
</property>
</bean>
int serviceAmount = searchServices.size();
final ExecutorService exec = Executors.newFixedThreadPool(serviceAmount);
final CountDownLatch downLatch = new CountDownLatch(serviceAmount + 1);
final CyclicBarrier barrier = new CyclicBarrier(serviceAmount, new ServiceReadyThread(downLatch));
因为CyclicBarrier和CountDownLatch在定义的时候要指定需要同步的数量。所以有了 int serviceAmount = searchServices.size();
然后建立一个线程池,建立CyclicBarrier和CountDownLatch的实例,
这里需要注意ServiceReadyThread这个参数,这个是我打开整个服务的一个标志位
public class ServiceReadyThread implements Runnable{
private CountDownLatch downLatch;
public ServiceReadyThread(CountDownLatch downLatch){
this.downLatch = downLatch;
}
@Override
public void run() {
LuceneUtil.setIndexReady(true);
downLatch.countDown();
}
}
因为这里也需要downLatch.countDown(); 所以上述的CountDownLatch的参数会 +1.
for (ISearchService iSearchService : searchServices) {
Thread task = new Thread(new InitLuceneIndexThread(iSearchService, barrier, downLatch));
exec.execute(task);
}
这个目的就是把每个service加入到一个单独的线程中执行,那么这些线程的同步就是CyclicBarrier的工作了。
InitLuceneIndexThread的代码public class InitLuceneIndexThread implements Runnable{
private CyclicBarrier barrier;
private ISearchService searchService;
private CountDownLatch downLatch;
public InitLuceneIndexThread(ISearchService searchService, CyclicBarrier barrier, CountDownLatch downLatch){
this.searchService = searchService;
this.barrier = barrier;
this.downLatch = downLatch;
}
@Override
public void run() {
searchService.createIndexIfInValid();
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}finally{
downLatch.countDown(); //放在finally中执行你懂的
}
}
}
try {
downLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}//等待所有的并发访问完
上面的代码的意思就是等待所有的线程执行完,大家看到,这个是downLatch的事情。
执行完以后,没有以后了。。。。。
但是一个问题是我前面说的,这个功能是个服务提供的标识符。那怎么做的呢,
注意到ServiceReadyThread 中的 LuceneUtil.setIndexReady(true);了吗?
接下来看看这个标志符的定义
private static volatile boolean isIndexReady = false; //定义为volatile 你也懂的
get()and set()。。。。。。。
前面提过,我们的服务提供是用Mina做的,那么就在Mina的Handler里面做文章,如果isIndexReady为false
,则不让客户端建立连接。
郑重申明,该想法只是完成了代码部分,没有进行测试,让大家帮我参谋参谋有什么需要改进的地方,毕竟一个人的力量是有限的,我相信群众。Come on, Man, 大家来找茬。
应用场景:
Mina + Spring 提供对外服务
需求:
在整个系统没有准备好之前,系统对外拒绝服务,因为本系统涉及到一些初始化索引一些比较耗费时间的问题,所以即使spring启动了,但是数据没有准备好,依然不能提供服务。
刚开始的时候,使用 spring的 init-method,但是经历各种蛋疼以后,发现可行性太低,所以我就想,能不能监听spring的事件来做呢,结果有了如下想法:
public class InitData implements ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware{
private ApplicationContext applicationContext;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
InitDataService service = applicationContext.getBean(InitDataService.class);
List<ISearchService> searchServices = service.getSearchServices();
int serviceAmount = searchServices.size();
final ExecutorService exec = Executors.newFixedThreadPool(serviceAmount);
final CountDownLatch downLatch = new CountDownLatch(serviceAmount + 1);
final CyclicBarrier barrier = new CyclicBarrier(serviceAmount, new ServiceReadyThread(downLatch));
for (ISearchService iSearchService : searchServices) {
Thread task = new Thread(new InitLuceneIndexThread(iSearchService, barrier, downLatch));
exec.execute(task);
}
try {
downLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}//等待所有的并发访问完
exec.shutdown();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
这个是整个想法的核心,下面围绕这个核心,我来做一些解释。
首先实现了ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware二个接口,一个是监听ContextRefreshedEvent事件,一个是拿到applicationContext。
InitDataService service = applicationContext.getBean(InitDataService.class);
单独写出来的一个类,因为我的service类有很多,那么如果我把这些类都放到配置文件中,以后只要实现各自的方法和更改配置文件就可以了。
ublic class InitDataService {
private List<ISearchService> searchServices;
public List<ISearchService> getSearchServices() {
return searchServices;
}
public void setSearchServices(List<ISearchService> searchServices) {
this.searchServices = searchServices;
}
}
<bean id="initDataService" class="com.playsnail.search.service.init.InitDataService">
<property name="searchServices">
<list>
<ref bean="各种实现了ISearchService的Service"/>
</list>
</property>
</bean>
int serviceAmount = searchServices.size();
final ExecutorService exec = Executors.newFixedThreadPool(serviceAmount);
final CountDownLatch downLatch = new CountDownLatch(serviceAmount + 1);
final CyclicBarrier barrier = new CyclicBarrier(serviceAmount, new ServiceReadyThread(downLatch));
因为CyclicBarrier和CountDownLatch在定义的时候要指定需要同步的数量。所以有了 int serviceAmount = searchServices.size();
然后建立一个线程池,建立CyclicBarrier和CountDownLatch的实例,
这里需要注意ServiceReadyThread这个参数,这个是我打开整个服务的一个标志位
public class ServiceReadyThread implements Runnable{
private CountDownLatch downLatch;
public ServiceReadyThread(CountDownLatch downLatch){
this.downLatch = downLatch;
}
@Override
public void run() {
LuceneUtil.setIndexReady(true);
downLatch.countDown();
}
}
因为这里也需要downLatch.countDown(); 所以上述的CountDownLatch的参数会 +1.
for (ISearchService iSearchService : searchServices) {
Thread task = new Thread(new InitLuceneIndexThread(iSearchService, barrier, downLatch));
exec.execute(task);
}
这个目的就是把每个service加入到一个单独的线程中执行,那么这些线程的同步就是CyclicBarrier的工作了。
InitLuceneIndexThread的代码public class InitLuceneIndexThread implements Runnable{
private CyclicBarrier barrier;
private ISearchService searchService;
private CountDownLatch downLatch;
public InitLuceneIndexThread(ISearchService searchService, CyclicBarrier barrier, CountDownLatch downLatch){
this.searchService = searchService;
this.barrier = barrier;
this.downLatch = downLatch;
}
@Override
public void run() {
searchService.createIndexIfInValid();
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}finally{
downLatch.countDown(); //放在finally中执行你懂的
}
}
}
try {
downLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}//等待所有的并发访问完
上面的代码的意思就是等待所有的线程执行完,大家看到,这个是downLatch的事情。
执行完以后,没有以后了。。。。。
但是一个问题是我前面说的,这个功能是个服务提供的标识符。那怎么做的呢,
注意到ServiceReadyThread 中的 LuceneUtil.setIndexReady(true);了吗?
接下来看看这个标志符的定义
private static volatile boolean isIndexReady = false; //定义为volatile 你也懂的
get()and set()。。。。。。。
前面提过,我们的服务提供是用Mina做的,那么就在Mina的Handler里面做文章,如果isIndexReady为false
,则不让客户端建立连接。
郑重申明,该想法只是完成了代码部分,没有进行测试,让大家帮我参谋参谋有什么需要改进的地方,毕竟一个人的力量是有限的,我相信群众。Come on, Man, 大家来找茬。
相关文章推荐
- solaris 10 mount Linux NFS的问题
- ubuntu 10.04 挂载nfs遇到的问题
- Solaris 10 安装及SVC管理及X及Vmware及其它可能遇到的一些问题
- 嵌入式开发(一)虚拟机上的ubuntu系统上搭建nfs过程及遇到问题
- 近期遇到的几个Solaris 10 的问题
- ubuntu nfs配置 以及mount.nfs:access denied by server while mounting问题解决
- 在Solaris上mount Linux NFS文件系统的问题
- Solaris 10 安装及SVC管理及X及Vmware及其它可能遇到的一些问题
- Ubuntu 16.04 nfs mount to freebsd 10
- 华硕 A550jk-4710HQ 装Windows 10和Ubuntu 16.04遇到的各种各样的问题
- weblogic10使用时遇到的问题总结
- ubuntu编译libevent遇到的问题
- ubuntu14.04安装matlab2010遇到的问题
- Ubuntu 14.04-64bit安装pip遇到的问题及tensorflow的安装
- ubuntu 下用nfs挂载不上问题
- ubuntu下安装nginx+tomcat+jdk所遇到的所有问题
- 使用ubuntu安装xen后使用virsh version命令遇到的问题
- 在64位ubuntu上编译kitkat4.4时遇到HashSet_jni.h错误导致编译中止的问题
- ArcSDE 10 for Microsoft SQL Server 2008安装以及导入数据遇到的问题总结
- ubuntu常用软件安装及遇到的问题