运用nginx搭建高可用,高并发的wcf集群

缓解方案中的数据层项目初期使用的是oracle 11g + ef5
创设的实体模型,在分页时遭遇了skip参数为0报错的题目,没有找到相关资料。

    

于是决定升级到ef6,在oracle官网中获知,Oracle Data Provider for .NET in
ODAC 12c Release 3
先导襄助ef6(https://docs.oracle.com/cd/E56485\_01/win.121/e55744/release\_changes.htm\#CIHGIAEG)

       
很多情形下基于wcf的复杂性均衡都首选zookeeper,这样可以具有更好的决定粒度,但zk对C#
不大自己,实现起来相对来说相比较辛苦,实际意况下,如若

安装步骤:

您的载重机制粒度很粗糙的话,优先利用nginx就可以搞定,既可以兑现复杂均衡,又有何不可兑现双机热备,以细小的代码量实现大家的事务,下边具体享受下。

1.安装odac,下载地址http://www.oracle.com/technetwork/database/windows/downloads/utilsoft-087491.html

 

2.数据层项目标.net版本改成4.5之上,使用nuget安装 EntityFramework
6 +Oracle.ManagedDataAccess
+Oracle.ManagedDataAccess.EntityFramework,都安装新型稳定版。

一:准备的素材

安装后app.config和web.config都会被参加如下配置项

 

<configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <section name="oracle.manageddataaccess.client" type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.122.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
  </configSections>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="mssqllocaldb" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="Oracle.ManagedDataAccess.Client" type="Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.122.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
    </providers>
  </entityFramework>
  <system.data>
    <DbProviderFactories>
      <remove invariant="Oracle.ManagedDataAccess.Client" />
      <add name="ODP.NET, Managed Driver" invariant="Oracle.ManagedDataAccess.Client" description="Oracle Data Provider for .NET, Managed Driver" type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.122.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
    </DbProviderFactories>
  </system.data>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <publisherPolicy apply="no" />
        <assemblyIdentity name="Oracle.ManagedDataAccess" publicKeyToken="89b483f429c47342" culture="neutral" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <oracle.manageddataaccess.client>
    <version number="*">
      <dataSources>
        <dataSource alias="SampleDataSource" descriptor="(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL))) " />
      </dataSources>
    </version>
  </oracle.manageddataaccess.client>

  1. 话不多说,一图胜千言,图中的服务器都是选用vmware虚拟化,如下图:

注意 entityFramework和 system.data中的版本号,nuget安装后自动生成的形似没问题,我在装置从前把网上找的素材里的布置项放在其中了,可是版本号不一致,程序启动不了,一直没放在心上到版本号,

     图片 1

找了好一会才意识是那六个地点。

《1》 三台windows机器
,多个WCF的windows服务器承载(192.168.23.187,192.168.23.188),一台Client的服务器(192.168.23.1)

3.然后就足以加上实体模型了。此时倘诺vs中显示找不到与ef6
兼容的实业框架提供程序
,需要将配置文件中的ef节的 <provider
invariantName=”System.Data.SqlClient”
type=”System.Data.Entity.SqlServer.SqlProviderService(Service)s,
EntityFramework.SqlServer”
/>删掉或者注释掉,保存后再另行尝试添加实体模型。

《2》 一台Centos机器,用来承载web复杂均衡nginx(192.168.23.190)。

增长实体模型时需要先不选用数据库里的表,即生成空模型,然后打开edmx文件,在模型浏览器中当选实体模型,在性质中把DDL生成模板改成SSDLToOracle.tt
(VS),数据库生成工作流改成Generate Oracle Via T4
(TPT).xaml
(VS)。

《3》在有着的Client的Hosts文件中增添host映射:【192.168.23.190
cluster.com】,方便通过域名的花样拜访nginx所在服务器的ip地址。

如此这般做的原委是倘诺DDL生成模板使用默认项SSDLToOracle.tt
oracle中的number(1,0)和number(2,0)类型的字段生成的实体性质的类型会是int16,然后运行的时候报映射不匹配的荒谬(错误代码2019)。

 

报错原因是oracle从ODP.NET
12.1.0.2起来为ef6用到新的默认类型映射,官网证实https://docs.oracle.com/cd/E56485\_01/win.121/e55744/entityDataTypeMapping.htm\#ODPNT8303,其中的 New
Default Mappings 段。

二:环境搭建

SSDLToOracle.tt模板生成的性质的项目是number(1,0)对应boolean,number(2,0)对应byte,这么些相应关系与新映射是同一的。

  1. WCF程序

附上ef5的映射

    既然是测试,肯定就是简约的次第,代码就不完全交由了。

Oracle Type Default EDM Type Custom EDM Type
Number(1,0) Int16 bool
Number(2,0) to Number(3,0) Int16 byte
Number(4,0) Int16 Int16
Number(5,0) Int16 Int32
Number(6,0) to Number(9,0) Int32 Int32
Number(10,0) Int32 Int64
Number(11,0) to Number(18,0) Int64 Int64
Number(19,0) Int64 Decimal

 

《1》
HomeService(Service)实现类代码如下(输出当前server的ip地址,方便查看):

 1     public class HomeService : IHomeService
 2     {
 3         public string DoWork(string msg)
 4         {
 5             var ip = Dns.GetHostAddresses(Dns.GetHostName()).FirstOrDefault(i => i.AddressFamily ==
 6                                                                AddressFamily.InterNetwork).ToString();
 7 
 8             return string.Format("当前 request 由 server={0} 返回", ip);
 9         }
10     }

 

《2》 App.Config代码

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3   <startup>
 4     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
 5   </startup>
 6   <system.serviceModel>
 7     <behaviors>
 8       <serviceBehaviors>
 9         <behavior name="">
10           <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
11           <serviceDebug includeExceptionDetailInFaults="false" />
12         </behavior>
13       </serviceBehaviors>
14     </behaviors>
15     <services>
16       <service name="WcfService.HomeService">
17         <endpoint address="/HomeService" binding="basicHttpBinding" contract="WcfService.IHomeService">
18           <identity>
19             <dns value="localhost" />
20           </identity>
21         </endpoint>
22         <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
23         <host>
24           <baseAddresses>
25             <add baseAddress="http://192.168.23.187:8733" />
26           </baseAddresses>
27         </host>
28       </service>
29     </services>
30   </system.serviceModel>
31 </configuration>

 

因为windows的两台机器的ip地址是192.168.23.187,192.168.23.188,所以安排的时候注意一下config中的baseAddress地址。

 

  1. centos上的nginx搭建

   
nginx我想我们用的仍旧相比多的,去官网下载最新的就好【nginx-1.13.6】:http://nginx.org/en/download.html,下载之后,就是例行的三板斧安装!!!

[root@localhost nginx-1.13.6]# ./configure --prefix=/usr/myapp/nginx
[root@localhost nginx-1.13.6]# make && make install

   

    然后在nginx的装置目录上边找到conf文件,修改里面的nginx.conf 配置。

[root@localhost nginx]# cd conf
[root@localhost conf]# ls
fastcgi.conf            koi-utf             nginx.conf           uwsgi_params
fastcgi.conf.default    koi-win             nginx.conf.default   uwsgi_params.default
fastcgi_params          mime.types          scgi_params          win-utf
fastcgi_params.default  mime.types.default  scgi_params.default
[root@localhost conf]# vim nginx.conf

 

   
详细布置如下,注意下边“标红”的地点,权重依据1:5的法子开展调用,关于任何的安排,我们能够在网上搜一下就可以了。

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    upstream  cluster.com{
                 server 192.168.23.187:8733 weight=1;
                 server 192.168.23.188:8733 weight=5;
                 }

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass http://cluster.com; 
            #设置主机头和客户端真实地址,以便服务器获取客户端真实IP
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Server $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header  X-Real-IP  $remote_addr; 
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

 

 3. client端的顺序搭建

《1》 第一件事就是将 192.168.23.190
映射到本机的host中去,因为服务不提供给第三方使用,所以加host如故很自在的。

192.168.23.190 cluster.com

图片 2

 

《2》
然后就是client端程序添加服务引用,因为添加了host映射,所以服务引用地址就是”http://cluster.com"。
代码如下:

图片 3

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             for (int i = 0; i < 1000; i++)
 6             {
 7                 HomeServiceClient client = new HomeServiceClient();
 8 
 9                 var info = client.DoWork("hello world!");
10 
11                 Console.WriteLine(info);
12 
13                 System.Threading.Thread.Sleep(1000);
14             }
15 
16             Console.Read();
17         }
18     }

 

末段来执行以下顺序,看看1000次巡回中,是不是比照权重1:5
的艺术对后端的wcf举办调用的???

图片 4

图片 5

 

观察没有,是不是很牛逼,我只需要通过cluster.com举办劳动走访,nginx会自动给自家复杂均衡,那就是大家开发中很是简单化的wcf复杂均衡。

 

指望本篇对您有帮衬~~~~
  附完整源代码:cluster.zip